def test_more_encodings(self): # these are unicode strings to reflect behavior after loading 'route_email' tasks from mongo s_msg = """Date: Sat, 25 May 2019 09:32:00 +1000 From: <*****@*****.**> To: <*****@*****.**> Subject: bugs Content-Type: text/plain; charset=GBK Content-Transfer-Encoding: base64 VGhlIFNuYXA3IGFwcGxpY2F0aW9uKGJhc2VkIG9uIHNuYXA3LWZ1bGwtMS40LjIpIGhhcyBiZWVu IHJ1biBvdmVyIGEgd2VlayBvbiBRTlg2LjYuMCwKQnV0IHNvbWV0aW1lcyAsc3lzdGVtIHNjcmVl biB3aWxsIHByaW50CiJsZGQ6RkFUQUw6Y291bGQgbm90IGxvYWQgbGlicmFyeSBsaWJzb2NrZXQu c28uMyIsClRoZSBhcHBsaWNhdGlvbidzIGNvbW11bmljYXRpb24gd29yayB3ZWxsICxidXQgdGhl IGZ0cCx0ZWxuZXQscGluZyBjYW4ndCB3b3JrICEKCgpXaHk/ """ msg = parse_message(s_msg) assert isinstance(msg['payload'], six.text_type) assert_in('The Snap7 application', msg['payload']) s_msg = """Date: Sat, 25 May 2019 09:32:00 +1000 From: <*****@*****.**> To: <*****@*****.**> Subject: bugs Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit > Status: closed > Created: Thu May 23, 2019 09:24 PM UTC by admin1 > Attachments: > > • foo.txt (1.0 kB; text/plain) > """ msg = parse_message(s_msg) assert isinstance(msg['payload'], six.text_type) assert_in('• foo', msg['payload']) s_msg = """Date: Sat, 25 May 2019 09:32:00 +1000 From: <*****@*****.**> To: <*****@*****.**> Subject: bugs Content-Type: TEXT/PLAIN; format=flowed; charset=ISO-8859-15 Content-Transfer-Encoding: 8BIT programmed or èrogrammed ? """ msg = parse_message(s_msg) assert isinstance(msg['payload'], six.text_type) assert_in('èrogrammed', msg['payload'])
def test_unicode_complex_message(self): charset = 'utf-8' p1 = MIMEText(u'''По оживлённым берегам Громады стройные теснятся Дворцов и башен; корабли Толпой со всех концов земли К богатым пристаням стремятся;'''.encode(charset), 'plain', charset) p2 = MIMEText(u'''<p>По оживлённым берегам Громады стройные теснятся Дворцов и башен; корабли Толпой со всех концов земли К богатым пристаням стремятся;</p>'''.encode(charset), 'plain', charset) msg1 = MIMEMultipart() msg1['Message-ID'] = '<*****@*****.**>' msg1.attach(p1) msg1.attach(p2) s_msg = msg1.as_string() msg2 = parse_message(s_msg) for part in msg2['parts']: if part['payload'] is None: continue assert isinstance(part['payload'], unicode)
def test_more_encodings_multipart(self): # these are unicode strings to reflect behavior after loading 'route_email' tasks from mongo s_msg = """Date: Sat, 25 May 2019 09:32:00 +1000 From: <*****@*****.**> To: <*****@*****.**> Subject: bugs Content-Type: multipart/alternative; boundary="===============7387203749754534836==" --===============7387203749754534836== Content-Type: text/plain; charset="utf-8" > Status: closed > Created: Thu May 23, 2019 09:24 PM UTC by admin1 > Attachments: > > • foo.txt (1.0 kB; text/plain) > --===============7387203749754534836== Content-Type: text/html; charset="utf-8" <html><head>... blah blah ... > • foo.txt (1.0 kB; text/plain) """ msg = parse_message(s_msg) assert isinstance(msg['parts'][1]['payload'], six.text_type) assert isinstance(msg['parts'][2]['payload'], six.text_type) assert_in('• foo', msg['parts'][1]['payload']) assert_in('• foo', msg['parts'][2]['payload'])
def test_unicode_simple_message(self): charset = 'utf-8' msg1 = MIMEText( u'''По оживлённым берегам Громады стройные теснятся Дворцов и башен; корабли Толпой со всех концов земли К богатым пристаням стремятся;'''.encode(charset), 'plain', charset) msg1['Message-ID'] = '<*****@*****.**>' s_msg = msg1.as_string() msg2 = parse_message(s_msg) assert isinstance(msg2['payload'], unicode)
def test_handle_artifact_unicode(qg): """ Tests that app.handle_artifact_message can accept utf strings """ ticket = mock.MagicMock() ticket.get_discussion_thread.return_value = (mock.MagicMock(), mock.MagicMock()) post = mock.MagicMock() qg.return_value = post a = app.Application(c.project, c.app.config) msg = dict(payload='foo ƒ†©¥˙¨ˆ'.encode('utf-8'), message_id=1, headers={}) a.handle_artifact_message(ticket, msg) assert_equal(post.attach.call_args[0][1].getvalue(), 'foo ƒ†©¥˙¨ˆ'.encode('utf-8')) msg = dict(payload='foo'.encode('utf-8'), message_id=1, headers={}) a.handle_artifact_message(ticket, msg) assert_equal(post.attach.call_args[0][1].getvalue(), b'foo') msg = dict(payload="\x94my quote\x94".encode('utf-8'), message_id=1, headers={}) a.handle_artifact_message(ticket, msg) assert_equal(post.attach.call_args[0][1].getvalue(), '\x94my quote\x94'.encode('utf-8')) # assert against prod example msg_raw = """Message-Id: <*****@*****.**> From: foo <*****@*****.**> To: "[forge:site-support]" <*****@*****.**> MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: multipart/alternative; boundary="_----------=_150235203132168580" Date: Thu, 10 Aug 2017 10:00:31 +0200 Subject: Re: [forge:site-support] #15391 Unable to join (my own) mailing list This is a multi-part message in MIME format. --_----------=_150235203132168580 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Hi --_----------=_150235203132168580 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset="utf-8" <!DOCTYPE html> <html><body>Hi</body></html> --_----------=_150235203132168580-- """ msg = mail_util.parse_message(msg_raw) for p in [p for p in msg['parts'] if p['payload'] != None]: # filter here mimics logic in `route_email` a.handle_artifact_message(ticket, p)
def route_email(peer, mailfrom, rcpttos, data): ''' Route messages according to their destination: <topic>@<mount_point>.<subproj2>.<subproj1>.<project>.projects.domain.net gets sent to c.app.handle_message(topic, message) ''' try: msg = mail_util.parse_message(data) except Exception: # pragma no cover log.exception('Parse Error: (%r,%r,%r)', peer, mailfrom, rcpttos) return if mail_util.is_autoreply(msg): log.info('Skipping autoreply message: %s', msg['headers']) return mail_user = mail_util.identify_sender(peer, mailfrom, msg['headers'], msg) with h.push_config(c, user=mail_user): log.info('Received email from %s', c.user.username) # For each of the addrs, determine the project/app and route # appropriately for addr in rcpttos: try: userpart, project, app = mail_util.parse_address(addr) with h.push_config(c, project=project, app=app): if not app.has_access(c.user, userpart): log.info('Access denied for %s to mailbox %s', c.user, userpart) elif not c.app.config.options.get('AllowEmailPosting', True): log.info("Posting from email is not enabled") else: if msg['multipart']: msg_hdrs = msg['headers'] for part in msg['parts']: if part.get('content_type', '').startswith('multipart/'): continue msg = dict(headers=dict( msg_hdrs, **part['headers']), message_id=part['message_id'], in_reply_to=part['in_reply_to'], references=part['references'], filename=part['filename'], content_type=part['content_type'], payload=part['payload']) c.app.handle_message(userpart, msg) else: c.app.handle_message(userpart, msg) except exc.MailError as e: log.error('Error routing email to %s: %s', addr, e) except Exception: log.exception('Error routing mail to %s', addr)
def test_unicode_simple_message(self): charset = 'utf-8' msg1 = MIMEText(u'''По оживлённым берегам Громады стройные теснятся Дворцов и башен; корабли Толпой со всех концов земли К богатым пристаням стремятся;'''.encode(charset), 'plain', charset) msg1['Message-ID'] = '<*****@*****.**>' s_msg = msg1.as_string() msg2 = parse_message(s_msg) assert isinstance(msg2['payload'], unicode)
def route_email( peer, mailfrom, rcpttos, data): ''' Route messages according to their destination: <topic>@<mount_point>.<subproj2>.<subproj1>.<project>.projects.domain.net gets sent to c.app.handle_message(topic, message) ''' try: msg = mail_util.parse_message(data) except: # pragma no cover log.exception('Parse Error: (%r,%r,%r)', peer, mailfrom, rcpttos) return if mail_util.is_autoreply(msg): log.info('Skipping autoreply message: %s', msg['headers']) return mail_user = mail_util.identify_sender(peer, mailfrom, msg['headers'], msg) with h.push_config(c, user=mail_user): log.info('Received email from %s', c.user.username) # For each of the addrs, determine the project/app and route # appropriately for addr in rcpttos: try: userpart, project, app = mail_util.parse_address(addr) with h.push_config(c, project=project, app=app): if not app.has_access(c.user, userpart): log.info('Access denied for %s to mailbox %s', c.user, userpart) elif not c.app.config.options.get('AllowEmailPosting', True): log.info("Posting from email is not enabled") else: if msg['multipart']: msg_hdrs = msg['headers'] for part in msg['parts']: if part.get('content_type', '').startswith('multipart/'): continue msg = dict( headers=dict(msg_hdrs, **part['headers']), message_id=part['message_id'], in_reply_to=part['in_reply_to'], references=part['references'], filename=part['filename'], content_type=part['content_type'], payload=part['payload']) c.app.handle_message(userpart, msg) else: c.app.handle_message(userpart, msg) except exc.MailError, e: log.error('Error routing email to %s: %s', addr, e) except:
def test_handle_artifact_unicode(qg): """ Tests that app.handle_artifact_message can accept utf strings """ ticket = mock.MagicMock() ticket.get_discussion_thread.return_value = (mock.MagicMock(), mock.MagicMock()) post = mock.MagicMock() qg.return_value = post a = app.Application(c.project, c.app.config) msg = dict(payload=u'foo ƒ†©¥˙¨ˆ', message_id=1, headers={}) a.handle_artifact_message(ticket, msg) assert_equal(post.attach.call_args[0][1].getvalue(), 'foo ƒ†©¥˙¨ˆ') msg = dict(payload='foo', message_id=1, headers={}) a.handle_artifact_message(ticket, msg) assert_equal(post.attach.call_args[0][1].getvalue(), 'foo') msg = dict(payload="\x94my quote\x94", message_id=1, headers={}) a.handle_artifact_message(ticket, msg) assert_equal(post.attach.call_args[0][1].getvalue(), '\x94my quote\x94') # assert against prod example msg_raw = """Message-Id: <*****@*****.**> From: foo <*****@*****.**> To: "[forge:site-support]" <*****@*****.**> MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: multipart/alternative; boundary="_----------=_150235203132168580" Date: Thu, 10 Aug 2017 10:00:31 +0200 Subject: Re: [forge:site-support] #15391 Unable to join (my own) mailing list This is a multi-part message in MIME format. --_----------=_150235203132168580 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Hi --_----------=_150235203132168580 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset="utf-8" <!DOCTYPE html> <html><body>Hi</body></html> --_----------=_150235203132168580-- """ msg = mail_util.parse_message(msg_raw) for p in filter(lambda p: p['payload'] != None, msg['parts']): # filter here mimics logic in `route_email` a.handle_artifact_message(ticket, p)