def create_long_lines_test(): val = "hello" * 1024 text = create.text("plain", val, "utf-8") eq_('ascii', text.charset) create.from_string(text.to_string()) eq_(val, text.body)
def test_bounce_detect(): for i, tc in enumerate([{ 'desc': 'Common bounce example', 'mime': create.from_string(BOUNCE), 'result': bounce.Result( score=1.875, status=u'5.1.1', notification=( u"This is the mail system at host mail.example.com.\n\n" u"I'm sorry to have to inform you that your message could not\n" u"be delivered to one or more recipients. It's attached below.\n\n" u"For further assistance, please send mail to postmaster.\n\n" u"If you do so, please include this problem report. You can\n" u"delete your own text from the attached returned message.\n\n" u" The mail system\n\n" u"<*****@*****.**>: host\n" u" gmail-smtp-in.l.google.com[209.85.210.17] said: 550-5.1.1 The email account\n" u" that you tried to reach does not exist. Please try 550-5.1.1\n" u" double-checking the recipient's email address for typos or 550-5.1.1\n" u" unnecessary spaces. Learn more at 550 5.1.1\n" u" http://mail.google.com/support/bin/answer.py?answer=6596 17si20661415yxe.22\n" u" (in reply to RCPT TO command)\n"), diagnostic_code=( u"smtp; 550-5.1.1 The email account that you tried to reach does" u" not exist. Please try 550-5.1.1 double-checking the recipient's email" u" address for typos or 550-5.1.1 unnecessary spaces. Learn more at" u" 550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596" u" 17si20661415yxe.22")), 'is_bounce': True }, { 'desc': 'Office365 bounce messages lack Content-Description', 'mime': create.from_string(BOUNCE_OFFICE365), 'result': bounce.Result( score=1.25, status=u'5.1.10', notification=u'', diagnostic_code=( u'smtp;550 5.1.10 RESOLVER.ADR.RecipientNotFound; ' u'Recipient [email protected] not found by SMTP address lookup')), 'is_bounce': True }, { 'desc': 'Regular message', 'mime': create.from_string(SIGNED), 'result': bounce.Result( score=0.0, status=u'', notification=u'', diagnostic_code=u''), 'is_bounce': False }]): print('Test case #%d: %s' % (i, tc['desc'])) # When result = bounce.detect(tc['mime']) # Then eq_(result, tc['result']) eq_(result.is_bounce(), tc['is_bounce'])
def create_bounced_email_attached_message_test(): attached_message = """MIME-Version: 1.0 From: Test <*****@*****.**> To: [email protected] Content-Type: multipart/alternative; boundary=f403045f50f42690580546f0cb4d --f403045f50f42690580546f0cb4d Content-Type: text/plain Content-Transfer-Encoding: 8bit how are you? --f403045f50f42690580546f0cb4d-- """ google_delivery_failed = """Delivered-To: [email protected] Content-Type: multipart/report; boundary=f403045f50f42d03f10546f0cb14; report-type=delivery-status --f403045f50f42d03f10546f0cb14 Content-Type: message/delivery-status --f403045f50f42d03f10546f0cb14 Content-Type: message/rfc822 {msg} --f403045f50f42d03f10546f0cb14-- """.format(msg=attached_message) message = create.from_string(google_delivery_failed) eq_(google_delivery_failed, message.to_string()) eq_(attached_message, message.get_attached_message().to_string())
def max_header_length_test(): message = create.from_string(LONG_HEADER) # this used to fail because exceeded max depth recursion ok_(message.headers.getraw('subject').encode("utf-8") in message.to_string()) unicode_subject = (u"Это сообщение с длинным сабжектом " u"специально чтобы проверить кодировки") ascii_subject = "This is simple ascii subject" with patch.object( headers.encoding, 'MAX_HEADER_LENGTH', len(ascii_subject) + 1): eq_(Header(ascii_subject.encode("ascii"), "ascii", header_name="Subject"), encode_unstructured("Subject", ascii_subject)) with patch.object( headers.encoding, 'MAX_HEADER_LENGTH', len(unicode_subject) + 1): eq_(Header(unicode_subject.encode("utf-8"), "utf-8", header_name="Subject"), encode_unstructured("Subject", unicode_subject)) with patch.object(headers.encoding, 'MAX_HEADER_LENGTH', 1): eq_(ascii_subject.encode("utf-8"), encode_unstructured("Subject", ascii_subject)) eq_(unicode_subject.encode("utf-8"), encode_unstructured("Subject", unicode_subject))
def create_newlines_in_headers_test(): text = create.text("plain", 'yo', "utf-8") text.headers['Subject'] = 'Hello,\nnewline\r\n\r\n' text.headers.add('To', u'\n\nПревед, медвед\n!\r\n') text = create.from_string(text.to_string()) eq_('Hello,newline', text.headers['Subject']) eq_(u'Превед, медвед!', text.headers['To'])
def parse_message(self, pure_string=False): msg_string = utils.uncompress(self.message.read()) try: if pure_string: return msg_string return from_string(msg_string) except Exception, err: logger.error(str(err)) return recover(msg_string)
def create_singlepart_ascii_long_lines_test(): very_long = "very long line " * 1000 + "preserve my newlines \r\n\r\n" message = create.text("plain", very_long) message2 = create.from_string(message.to_string()) eq_("quoted-printable", message2.content_encoding.value) eq_(very_long, message2.body) message2 = email.message_from_string(message.to_string()) eq_(very_long, message2.get_payload(decode=True))
def test_bug_line_is_too_long(): # It was possible to create a message with a very long header value, but # it was impossible to parse such message. msg = create.text('plain', 'foo', 'utf-8') msg.headers.add('bar', 'y' * 10000) encoded_msg = msg.to_string() decoded_msg = create.from_string(encoded_msg) # When/Then decoded_msg.headers
def create_enclosed_test(): message = create.text("plain", u"Превед") message.headers['From'] = u' Саша <*****@*****.**>' message.headers['To'] = u'Женя <*****@*****.**>' message.headers['Subject'] = u"Все ли ок? Нормальненько??" message = create.message_container(message) message2 = create.from_string(message.to_string()) eq_('message/rfc822', message2.content_type) eq_(u"Превед", message2.enclosed.body) eq_(u'Саша <*****@*****.**>', message2.enclosed.headers['From'])
def test_bounce_analyzer_on_bounce(): bm = create.from_string(BOUNCE) ok_(bm.is_bounce()) eq_("5.1.1", bm.bounce.status) eq_( "smtp; 550-5.1.1 The email account that you tried to reach does" " not exist. Please try 550-5.1.1 double-checking the recipient's email" " address for typos or 550-5.1.1 unnecessary spaces. Learn more at" " 550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596" " 17si20661415yxe.22", bm.bounce.diagnostic_code, )
def max_header_length_test(): message = create.from_string(LONG_HEADER) # this used to fail because exceeded max depth recursion message.to_string() ascii_subject = "This is simple ascii subject" eq_(Header(ascii_subject.encode("ascii"), "ascii", header_name="Subject"), _encode_unstructured("Subject", ascii_subject)) unicode_subject = (u"Это сообщение с длинным сабжектом " u"специально чтобы проверить кодировки") eq_(Header(unicode_subject.encode("utf-8"), "utf-8", header_name="Subject"), _encode_unstructured("Subject", unicode_subject))
def add_header_preserve_original_encoding_test(): message = create.from_string(ENCODED_HEADER) # save original encoded from header original_from = message.headers.getraw('from') # check if the raw header was not decoded ok_('=?UTF-8?B?Rm9vLCBCYXI=?=' in original_from) # add a header message.headers.add('foo', 'bar') # check original encoded header is still in the mime string ok_(original_from in message.to_string())
def message_complete(key, message_string, sender=None): result = { 'files': [], 'headers': {} } parsing_errors = [] errors_count = 0 try: msg = from_string(message_string) except Exception, err: logger.error("%s:%s" % (key, str(err))) parsing_errors.append(str(err)) msg = recover(message_string)
def create_multipart_nested_test(): message = create.multipart("mixed") nested = create.multipart("alternative") nested.append( create.text("plain", u"Саша с уралмаша"), create.text("html", u"<html>Саша с уралмаша</html>")) message.append( create.text("plain", "Hello"), nested) message2 = create.from_string(message.to_string()) eq_(2, len(message2.parts)) eq_('text/plain', message2.parts[0].content_type) eq_('Hello', message2.parts[0].body) eq_(u"Саша с уралмаша", message2.parts[1].parts[0].body) eq_(u"<html>Саша с уралмаша</html>", message2.parts[1].parts[1].body)
def max_header_length_test(): message = create.from_string(LONG_HEADER) # this used to fail because exceeded max depth recursion message.to_string() ascii_subject = 'This is simple ascii subject' eq_('This is simple ascii subject', _encode_unstructured('Subject', ascii_subject)) unicode_subject = (u'Это сообщение с длинным сабжектом ' u'специально чтобы проверить кодировки') eq_('=?utf-8?b?0K3RgtC+INGB0L7QvtCx0YnQtdC90LjQtSDRgSDQtNC70LjQvdC9?=\r\n' ' =?utf-8?b?0YvQvCDRgdCw0LHQttC10LrRgtC+0Lwg0YHQv9C10YbQuNCw0LvRjNC90L4g?=\r\n' ' =?utf-8?b?0YfRgtC+0LHRiyDQv9GA0L7QstC10YDQuNGC0Ywg0LrQvtC00LjRgNC+0LI=?=\r\n' ' =?utf-8?b?0LrQuA==?=', _encode_unstructured('Subject', unicode_subject))
def create_multipart_with_text_non_unicode_attachment_test(): """Make sure we encode text attachment in base64 """ message = create.multipart("mixed") filename = "text-attachment.txt" message.append( create.text("plain", "Hello"), create.text("html", "<html>Hello</html>"), create.binary( "text", "plain", u"Саша с уралмаша".encode("koi8-r"), filename, "attachment")) message2 = create.from_string(message.to_string()) eq_(3, len(message2.parts)) attachment = message2.parts[2] ok_(attachment.is_attachment()) eq_("base64", attachment.content_encoding.value) eq_(u"Саша с уралмаша", attachment.body)
def create_enclosed_nested_test(): nested = create.multipart("alternative") nested.append( create.text("plain", u"Саша с уралмаша"), create.text("html", u"<html>Саша с уралмаша</html>")) message = create.multipart("mailgun-recipient-variables") variables = {"a": u"<b>Саша</b>" * 1024} message.append( create.binary("application", "json", json.dumps(variables)), create.message_container(nested)) message2 = create.from_string(message.to_string()) eq_(variables, json.loads(message2.parts[0].body)) nested = message2.parts[1].enclosed eq_(2, len(nested.parts)) eq_(u"Саша с уралмаша", nested.parts[0].body) eq_(u"<html>Саша с уралмаша</html>", nested.parts[1].body)
def create_multipart_simple_test(): message = create.multipart("mixed") message.append( create.text("plain", "Hello"), create.text("html", "<html>Hello</html>")) ok_(message.is_root()) assert_false(message.parts[0].is_root()) assert_false(message.parts[1].is_root()) message2 = create.from_string(message.to_string()) eq_(2, len(message2.parts)) eq_("multipart/mixed", message2.content_type) eq_(2, len(message.parts)) eq_("Hello", message.parts[0].body) eq_("<html>Hello</html>", message.parts[1].body) message2 = email.message_from_string(message.to_string()) eq_("multipart/mixed", message2.get_content_type()) eq_("Hello", message2.get_payload()[0].get_payload(decode=False)) eq_("<html>Hello</html>", message2.get_payload()[1].get_payload(decode=False))
def create_multipart_with_attachment_test(): message = create.multipart("mixed") filename = u"Мейлган картиночка картиночечка с длинным именем и пробельчиками" message.append( create.text("plain", "Hello"), create.text("html", "<html>Hello</html>"), create.binary( "image", "png", MAILGUN_PNG, filename, "attachment")) eq_(3, len(message.parts)) message2 = create.from_string(message.to_string()) eq_(3, len(message2.parts)) eq_("base64", message2.parts[2].content_encoding.value) eq_(MAILGUN_PNG, message2.parts[2].body) eq_(filename, message2.parts[2].content_disposition.params['filename']) eq_(filename, message2.parts[2].content_type.params['name']) ok_(message2.parts[2].is_attachment()) message2 = email.message_from_string(message.to_string()) eq_(3, len(message2.get_payload())) eq_(MAILGUN_PNG, message2.get_payload()[2].get_payload(decode=True))
def create_bounced_email_test(): google_delivery_failed = """Delivered-To: [email protected] Content-Type: multipart/report; boundary=f403045f50f42d03f10546f0cb14; report-type=delivery-status --f403045f50f42d03f10546f0cb14 Content-Type: message/delivery-status --f403045f50f42d03f10546f0cb14 Content-Type: message/rfc822 MIME-Version: 1.0 From: Test <*****@*****.**> To: [email protected] Content-Type: multipart/alternative; boundary=f403045f50f42690580546f0cb4d There should be a boundary here! --f403045f50f42d03f10546f0cb14-- """ message = create.from_string(google_delivery_failed) eq_(google_delivery_failed, message.to_string()) eq_(None, message.get_attached_message())
def from_part_message_simple_test(): message = create.from_string(IPHONE) parts = list(message.walk()) message = create.from_message(parts[2]) eq_(u'\n\n\n~Danielle', message.body)
def create_singlepart_unicode_test(): message = create.text("plain", u"Привет, курилка") message = create.from_string(message.to_string()) eq_("base64", message.content_encoding.value) eq_(u"Привет, курилка", message.body)
def create_singlepart_ascii_test(): message = create.text("plain", u"Hello") message = create.from_string(message.to_string()) eq_("7bit", message.content_encoding.value) eq_("Hello", message.body)
def test_bounce_no_headers_error_message(): msg = create.from_string("Nothing") assert_false(msg.is_bounce())
print(sa) msg = '''MIME-Version: 1.0 Content-Type: text/plain From: Example1 <*****@*****.**> To: Example2 <*****@*****.**> Subject: hello, message Date: Mon, 10 Sep 2019 12:43:03 -0700 this is a single part message.''' from flanker import mime fs = mime.from_string(msg) print(fs.body) print(fs.headers.items()) print(fs.content_type) print(fs.subject) print(fs.content_type.is_singlepart()) print(fs.content_type.is_multipart()) from flanker.mime import create message = create.text("plain", "hello, world!") message.headers['From'] = u'Example1 <*****@*****.**>' message.headers['To'] = u'Example2 <*****@*****.**>' message.headers['Subject'] = u"hello" message = create.from_string(message.to_string()) print(message.to_string())
def test_bounce_detect(): for i, tc in enumerate([{ 'desc': 'Common bounce example', 'mime': create.from_string(BOUNCE), 'result': bounce.Result( score=1.875, status=u'5.1.1', notification= (u"This is the mail system at host mail.example.com.\n\n" u"I'm sorry to have to inform you that your message could not\n" u"be delivered to one or more recipients. It's attached below.\n\n" u"For further assistance, please send mail to postmaster.\n\n" u"If you do so, please include this problem report. You can\n" u"delete your own text from the attached returned message.\n\n" u" The mail system\n\n" u"<*****@*****.**>: host\n" u" gmail-smtp-in.l.google.com[209.85.210.17] said: 550-5.1.1 The email account\n" u" that you tried to reach does not exist. Please try 550-5.1.1\n" u" double-checking the recipient's email address for typos or 550-5.1.1\n" u" unnecessary spaces. Learn more at 550 5.1.1\n" u" http://mail.google.com/support/bin/answer.py?answer=6596 17si20661415yxe.22\n" u" (in reply to RCPT TO command)\n"), diagnostic_code= (u"smtp; 550-5.1.1 The email account that you tried to reach does" u" not exist. Please try 550-5.1.1 double-checking the recipient's email" u" address for typos or 550-5.1.1 unnecessary spaces. Learn more at" u" 550 5.1.1 http://mail.google.com/support/bin/answer.py?answer=6596" u" 17si20661415yxe.22")), 'is_bounce': True }, { 'desc': 'Office365 bounce messages lack Content-Description', 'mime': create.from_string(BOUNCE_OFFICE365), 'result': bounce.Result( score=1.25, status=u'5.1.10', notification=u'', diagnostic_code= (u'smtp;550 5.1.10 RESOLVER.ADR.RecipientNotFound; ' u'Recipient [email protected] not found by SMTP address lookup' )), 'is_bounce': True }, { 'desc': 'Regular message', 'mime': create.from_string(SIGNED), 'result': bounce.Result(score=0.0, status=u'', notification=u'', diagnostic_code=u''), 'is_bounce': False }]): print('Test case #%d: %s' % (i, tc['desc'])) # When result = bounce.detect(tc['mime']) # Then eq_(result, tc['result']) eq_(result.is_bounce(), tc['is_bounce'])
def test_bounce_analyzer_on_regular(): bm = create.from_string(SIGNED) assert_false(bm.is_bounce())
def from_string_message_test(): message = create.from_string(IPHONE) parts = list(message.walk()) eq_(3, len(parts)) eq_(u'\n\n\n~Danielle', parts[2].body)