def assert_forward_content_equal(self, content): """ Asserts that the content of the forwarded message is equal to the given ``content``. """ msg = mail.outbox[0].message() self.assertEqual(get_decoded_message_payload(msg), content)
def bounce_is_for_spam(message): spam_bounce_re = [ # Google blocks executables files # 552-5.7.0 This message was blocked because its content presents a[...] # 552-5.7.0 security issue. Please visit # 552-5.7.0 https://support.google.com/mail/?p=BlockedMessage to [...] # 552 5.7.0 message content and attachment content guidelines. [...] r"552-5.7.0 This message was blocked", # host ...: 550 High probability of spam # host ...: 554 5.7.1 Message rejected because it contains malware # 550 Executable files are not allowed in compressed files. r"55[0-9] .*(?:spam|malware|virus|[Ee]xecutable files)", ] # XXX: Handle delivery report properly for part in message.walk(): if not part or part.is_multipart(): continue text = get_decoded_message_payload(part) if text is None: continue for line in text.splitlines()[0:15]: for rule in spam_bounce_re: if re.search(rule, line): return True return False
def create_dak_rm_news(message, package, body=None, version=''): """Create a :class:`News` out of a removal email sent by DAK.""" if not body: body = get_decoded_message_payload(message) suite = re.search(r"have been removed from (\S+):", body).group(1) title = "Removed {ver} from {suite}".format(ver=version, suite=suite) return mail_news.create_news(message, package, title=title)
def _get_message_body(msg): """ Returns the message body, joining together all parts into one string. :param msg: The original received package message :type msg: :py:class:`email.message.Message` """ return '\n'.join(get_decoded_message_payload(part) for part in msg.walk() if not part.is_multipart())
def process(message): """ The function which actually processes a received command email message. :param message: The received command email message. :type message: ``bytes`` """ assert isinstance(message, six.binary_type), 'Message must be given as bytes' msg = message_from_bytes(message) email = extract_email_address_from_header(msg.get('From', '')) logdata = { 'from': email, 'msgid': msg.get('Message-ID', 'no-msgid-present@localhost'), } logger.info("control <= %(from)s %(msgid)s", logdata) if 'X-Loop' in msg and DISTRO_TRACKER_CONTROL_EMAIL in msg.get_all('X-Loop'): logger.info("control :: discarded %(msgid)s due to X-Loop", logdata) return # Get the first plain-text part of the message plain_text_part = next(typed_subpart_iterator(msg, 'text', 'plain'), None) if not plain_text_part: # There is no plain text in the email send_plain_text_warning(msg, logdata) return # Decode the plain text into a unicode string try: text = get_decoded_message_payload(plain_text_part) except UnicodeDecodeError: send_plain_text_warning(msg, logdata) return lines = extract_command_from_subject(msg) + text.splitlines() # Process the commands factory = CommandFactory({'email': email}) confirmation_set = ConfirmationSet() processor = CommandProcessor(factory) processor.confirmation_set = confirmation_set processor.process(lines) confirmation_set.ask_confirmation_all() # Send a response only if there were some commands processed if processor.is_success(): send_response(msg, processor.get_output(), recipient_email=email, cc=set(confirmation_set.get_emails())) else: logger.info("control :: no command processed in %(msgid)s", logdata)
def _create_news_from_dak_email(message): x_dak = message['X-DAK'] katie = x_dak.split()[1] if katie != 'rm': # Only rm mails are processed. return body = get_decoded_message_payload(message) if not body: # The content cannot be decoded. return # Find all lines giving information about removed source packages re_rmline = re.compile(r"^\s*(\S+)\s*\|\s*(\S+)\s*\|.*source", re.M) source_removals = re_rmline.findall(body) # Add a news item for each source removal. created_news = [] for removal in source_removals: package_name, version = removal created_news.append( create_dak_rm_news(message, package_name, body=body, version=version)) return created_news
def create_news_from_email_message(message): """ In Debian's implementation, this function creates news when the received mail's origin is either the testing watch or katie. """ subject = message.get("Subject", None) if not subject: return subject_words = subject.split() # Source upload? if len(subject_words) > 1 and subject_words[0] in ('Accepted', 'Installed'): if 'source' not in subject: # Only source uploads should be considered. return package_name = subject_words[1] package = get_or_none(SourcePackageName, name=package_name) if package: return [EmailNews.objects.create_email_news(message, package)] # DAK rm? elif 'X-DAK' in message: x_dak = message['X-DAK'] katie = x_dak.split()[1] if katie != 'rm': # Only rm mails are processed. return body = get_decoded_message_payload(message) if not body: # The content cannot be decoded. return # Find all lines giving information about removed source packages re_rmline = re.compile(r"^\s*(\S+)\s*\|\s*(\S+)\s*\|.*source", re.M) source_removals = re_rmline.findall(body) # Find the suite from which the packages have been removed suite = re.search(r"have been removed from (\S+):", body).group(1) news_from = message.get('Sender', '') # Add a news item for each source removal. created_news = [] for removal in source_removals: package_name, version = removal package = get_or_none(SourcePackageName, name=package_name) if not package: # This package is not tracked continue title = "Removed {ver} from {suite}".format(ver=version, suite=suite) created_news.append(EmailNews.objects.create_email_news( title=title, message=message, package=package, created_by=news_from)) return created_news # Testing Watch? elif 'X-Testing-Watch-Package' in message: package_name = message['X-Testing-Watch-Package'] package = get_or_none(SourcePackageName, name=package_name) if not package: # This package is not tracked return title = message.get('Subject', '') if not title: title = 'Testing Watch Message' return [ EmailNews.objects.create_email_news( title=title, message=message, package=package, created_by='Britney') ]