def _decode_message(self, msg): assert isinstance(msg, email.message.Message) headers = {name: self._decode_header(value) for name, value in msg.items()} subject = self._decode_header(msg.get(u'subject', u'')) from_header = self._decode_header(msg.get(u'from', u'')) from_name, from_mail = parseaddr(from_header) text = u'' html = u'' attachments = [] for part in msg.walk(): if part.is_multipart(): continue content_type = part.get_content_type() charset = part.get_content_charset() content = part.get_payload(decode=True) disposition = self._decode_header(part.get(u'Content-Disposition', u'')) is_attachment = disposition.startswith(u'attachment') if not text and content_type == u'text/plain' and not is_attachment: text = self._decode_content(content, charset) elif not html and content_type == u'text/html' and not is_attachment: html = self._decode_content(content, charset) else: default = u'attachment{}'.format(guess_extension(content_type, u'.bin')) filename = part.get_filename(default) attachments.append(Attachment( file=ContentFile(content), name=filename, content_type=content_type, )) recipients = [] for header_name, type in ((u'to', Recipient.TYPES.TO), (u'cc', Recipient.TYPES.CC), (u'bcc', Recipient.TYPES.BCC)): header = self._decode_header(msg.get(header_name, u'')) for rcp_address in header.split(','): rcp_name, rcp_mail = parseaddr(rcp_address) if rcp_mail: recipients.append(Recipient( name=rcp_name, mail=rcp_mail, type=type, status=Recipient.STATUSES.INBOUND, )) message = Message( type=Message.TYPES.INBOUND, processed=None, from_name=from_name, from_mail=from_mail, subject=subject, text=text, html=html, headers=headers, ) message.save() for recipient in recipients: recipient.message = message recipient.save() for attachment in attachments: attachment.generic_object = message attachment.save() return message
def _enqueue(self, message): # Based on djrill.mail.backends.DjrillBackend; We can't use Djrill directly because it # sends the mail synchronously during user requests. sanitized = sanitize_address(message.from_email, message.encoding) from_name, from_mail = parseaddr(sanitized) subject = message.subject text = message.body if message.content_subtype != u'html' else None html = message.body if message.content_subtype == u'html' else None headers = message.extra_headers # We may have only one plaintext and one html message body. If the message has more # plaintext and/or html aternatives, they are converted to attachments. remnant_alternatives = [] for content, content_type in getattr(message, u'alternatives', []): if content_type == u'text/plain' and text is None: text = content elif content_type == u'text/html' and html is None: html = content else: ext = guess_extension(content_type, u'.bin') remnant_alternatives.append((u'message{}'.format(ext), content, content_type)) recipients = [] for addresses, type in ((message.to, Recipient.TYPES.TO), (message.cc, Recipient.TYPES.CC), (message.bcc, Recipient.TYPES.BCC)): for addr in addresses: sanitized = sanitize_address(addr, message.encoding) name, mail = parseaddr(sanitized) recipients.append(Recipient( name=name, mail=mail, type=type, status=Recipient.STATUSES.QUEUED, )) attachments = [] for attachment in message.attachments + remnant_alternatives: if isinstance(attachment, MIMEBase): name = attachment.get_filename() content = attachment.get_payload(decode=True) content_type = attachment.get_content_type() else: name, content, content_type = attachment if not content_type: content_type = DEFAULT_ATTACHMENT_MIME_TYPE if not name: name = u'attachment{}'.format(guess_extension(content_type, u'.bin')) attachments.append(Attachment( file=ContentFile(content), name=name, content_type=content_type, )) msg = Message( type=Message.TYPES.OUTBOUND, from_name=from_name, from_mail=from_mail, subject=subject, text=text or u'', html=html or u'', headers=headers, ) msg.save() message.instance = msg for recipient in recipients: recipient.message = msg recipient.save() for attachment in attachments: attachment.generic_object = msg attachment.save()
def _enqueue(self, message): # Based on djrill.mail.backends.DjrillBackend; We can't use Djrill directly because it # sends the mail synchronously during user requests. from_name, from_mail = parseaddr(message.from_email) subject = message.subject text = message.body if message.content_subtype != u'html' else None html = message.body if message.content_subtype == u'html' else None headers = message.extra_headers # We may have only one plaintext and one html message body. If the message has more # plaintext and/or html aternatives, they are converted to attachments. remnant_alternatives = [] for content, content_type in getattr(message, u'alternatives', []): if content_type == u'text/plain' and text is None: text = content elif content_type == u'text/html' and html is None: html = content else: ext = guess_extension(content_type, u'.bin') remnant_alternatives.append((u'message{}'.format(ext), content, content_type)) recipients = [] for addresses, type in ((message.to, Recipient.TYPES.TO), (message.cc, Recipient.TYPES.CC), (message.bcc, Recipient.TYPES.BCC)): for addr in addresses: name, mail = parseaddr(addr) recipients.append(Recipient( name=name, mail=mail, type=type, status=Recipient.STATUSES.QUEUED, )) attachments = [] for attachment in message.attachments + remnant_alternatives: if isinstance(attachment, MIMEBase): name = attachment.get_filename() content = attachment.get_payload(decode=True) content_type = attachment.get_content_type() else: name, content, content_type = attachment if not content_type: content_type = DEFAULT_ATTACHMENT_MIME_TYPE if not name: name = u'attachment{}'.format(guess_extension(content_type, u'.bin')) attachments.append(Attachment( file=ContentFile(content), name=name, )) msg = Message( type=Message.TYPES.OUTBOUND, from_name=from_name, from_mail=from_mail, subject=subject, text=text or u'', html=html or u'', headers=headers, ) msg.save() message.instance = msg for recipient in recipients: recipient.message = msg recipient.save() for attachment in attachments: attachment.generic_object = msg attachment.save()
def test_unknown_content_type_with_default_extension(self): self.assertEqual(guess_extension(u'application/nonexistent', u'.bin'), u'.bin')
def _decode_message(self, msg): assert isinstance(msg, email.message.Message) headers = { name: self._decode_header(value) for name, value in msg.items() } subject = self._decode_header(msg.get(u'subject', u'')) from_header = self._decode_header(msg.get(u'from', u'')) from_name, from_mail = parseaddr(from_header) text = u'' html = u'' attachments = [] for part in msg.walk(): if part.is_multipart(): continue content_type = part.get_content_type() charset = part.get_content_charset() content = part.get_payload(decode=True) disposition = self._decode_header( part.get(u'Content-Disposition', u'')) is_attachment = disposition.startswith(u'attachment') if not text and content_type == u'text/plain' and not is_attachment: text = self._decode_content(content, charset) elif not html and content_type == u'text/html' and not is_attachment: html = self._decode_content(content, charset) else: default = u'attachment{}'.format( guess_extension(content_type, u'.bin')) filename = part.get_filename(default) attachments.append( Attachment( file=ContentFile(content), name=filename, )) recipients = [] for header_name, type in ((u'to', Recipient.TYPES.TO), (u'cc', Recipient.TYPES.CC), (u'bcc', Recipient.TYPES.BCC)): header = self._decode_header(msg.get(header_name, u'')) for rcp_address in header.split(','): rcp_name, rcp_mail = parseaddr(rcp_address) if rcp_mail: recipients.append( Recipient( name=rcp_name, mail=rcp_mail, type=type, status=Recipient.STATUSES.INBOUND, )) message = Message( type=Message.TYPES.INBOUND, processed=None, from_name=from_name, from_mail=from_mail, subject=subject, text=text, html=html, headers=headers, ) message.save() for recipient in recipients: recipient.message = message recipient.save() for attachment in attachments: attachment.generic_object = message attachment.save() return message
def test_application_pdf(self): self.assertEqual(guess_extension(u'application/pdf'), u'.pdf')
def test_unknown_content_type(self): self.assertIsNone(guess_extension(u'application/nonexistent'))
def test_text_plain(self): self.assertEqual(guess_extension(u'text/plain'), u'.txt')
def test_application_octet_stream(self): self.assertEqual(guess_extension(u'application/octet-stream'), u'.bin')