def testEmailParsing(self): # create an initial "from" email message = email.message_from_file( open("./testdata/mail3.txt", "r")) name, mto = parseaddr(message['to']) name, mfrom = parseaddr(message['from']) for part in message.walk(): if part.get_content_maintype() == "multipart": continue # it's just a container if part.get_content_type() == "text/plain": body = part.get_payload(decode=True) break try: user = CustomUser.objects.get( email=mfrom) except CustomUser.DoesNotExist: user = CustomUser.objects.create(email=mfrom, username=mfrom) user.set_unusable_password() user.save() recipient, _ = CustomUser.objects.get_or_create( email=mto, username=mto) mail = Mail.objects.create( subject=message['subject'], mfrom=user, mto=recipient, message=body) # now we simulate a reply, and override a couple of relevant # headers raw_email = email.message_from_file( open("./testdata/mail4.txt", "r")) new_mto = user.proxy_email raw_email.replace_header('in-reply-to', "<%s>" % mail.message_id) raw_email.replace_header('references', "<%s>" % mail.message_id) raw_email.replace_header('to', "%s <%s>" % (mail.message_id, new_mto)) fp = StringIO(raw_email.as_string()) response = make_response_from_file(fp) self.assertTrue(response) # now parse in an email that isn't a response to anything fp = open("./testdata/mail2.txt", "r") response = make_response_from_file(fp) self.assertEqual(response, EX_NOUSER) # and now try threading based on subject line as a fallback... raw_email = email.message_from_file( open("./testdata/mail2.txt", "r")) new_mto = user.proxy_email del(raw_email['in-reply-to']) del(raw_email['references']) raw_email.replace_header('subject', "Re:RE: re:%s" % mail.subject) raw_email.replace_header('to', "%s <%s>" % (mail.message_id, new_mto)) fp = StringIO(raw_email.as_string()) response = make_response_from_file(fp) self.assertTrue(response)
def testSendAndReply(self): user = CustomUser.objects.create(email="*****@*****.**", username="******", needs_moderation=False) data = QueryDict("").copy() SUBJECT = "Test Send And Reply" data.update({'mto':'*****@*****.**', 'mfrom':user.email, 'subject':SUBJECT, 'message':'Hi'}) form = MailForm(None, data) self.assertFalse(form.is_valid()) data.update({'mto':'*****@*****.**', 'mfrom':user.email, 'subject':SUBJECT, 'name': 'One Baz', 'message':'Hi'}) form = MailForm(None, data) self.assertTrue(form.is_valid()) mail_obj = form.save() c = Client() response = c.get('/process', follow=True) self.assertContains(response, SUBJECT) self.assertEquals(mail.outbox[0].subject, SUBJECT) message_id = mail.outbox[0].extra_headers['Message-ID'] REPLY_SUBJECT = "Re: %s" % SUBJECT response = EmailMessage(REPLY_SUBJECT, "Hello back", "*****@*****.**", [user.proxy_email], headers={'In-Reply-To':'<%s>' % message_id}) response.send() self.assertEquals(mail.outbox[-1].subject, REPLY_SUBJECT) reply_fp = StringIO(mail.outbox[-1].message().as_string()) response = make_response_from_file(reply_fp) self.assertTrue(response) # this was like a different person at the same company # replying to the message -- let's check that while we're here couser1 = CustomUser.objects.get(email='*****@*****.**') couser2 = CustomUser.objects.get(email='*****@*****.**') self.assertEqual(couser1.organisation, couser2.organisation) # two emails should have been created, threaded together mails = Mail.objects.order_by('created') self.assertEqual(mails[0].childwalk().next(), mails[1]) # and an email should have been sent to the original sender, # with a proxied reply-to address self.assertEqual(mail.outbox[-1].to[0], user.email) self.assertEqual(mail.outbox[-1].from_email, couser2.email) self.assertEqual(mail.outbox[-1].extra_headers['Reply-To'], couser2.proxy_email)