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 _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) # msg = message_from_string(message) if 'X-Loop' in msg and PTS_CONTROL_EMAIL in msg.get_all('X-Loop'): 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) 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) return lines = extract_command_from_subject(msg) + text.splitlines() # Process the commands factory = CommandFactory({ 'email': extract_email_address_from_header(msg['From']), }) 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(), set(confirmation_set.get_emails()))
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 by the PTS 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 by the PTS 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') ]