From a44f7738f43a349a8c3fd4768dd54add13b3ce12 Mon Sep 17 00:00:00 2001 From: Duda Dornelles Date: Mon, 1 Sep 2014 16:24:46 -0300 Subject: support multiple to, cc and bcc --- service/pixelated/adapter/pixelated_mail.py | 12 +++++- service/pixelated/adapter/pixelated_mail_sender.py | 10 +++-- service/pixelated/support/__init__.py | 15 ++++++++ service/pixelated/support/functional.py | 20 ++++++++++ service/test/adapter/pixelated_mail_sender_test.py | 44 ++++++++++++++++++++++ service/test/adapter/pixelated_mail_test.py | 18 +++++---- service/test/adapter/test_helper.py | 14 +++++++ 7 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 service/pixelated/support/__init__.py create mode 100644 service/pixelated/support/functional.py create mode 100644 service/test/adapter/pixelated_mail_sender_test.py diff --git a/service/pixelated/adapter/pixelated_mail.py b/service/pixelated/adapter/pixelated_mail.py index e43d5510..d20a93f4 100644 --- a/service/pixelated/adapter/pixelated_mail.py +++ b/service/pixelated/adapter/pixelated_mail.py @@ -42,7 +42,13 @@ class PixelatedMail: self.headers['from'] = [_from] def get_to(self): - return self.headers['to'][0] + return self.headers['to'] + + def get_cc(self): + return self.headers['cc'] + + def get_bcc(self): + return self.headers['bcc'] def _extract_status(self): return Status.from_flags(self.leap_mail.getFlags()) @@ -81,7 +87,9 @@ class PixelatedMail: def to_mime_multipart(self): mime_multipart = MIMEMultipart() - mime_multipart['To'] = self.headers['to'][0] + mime_multipart['To'] = ", ".join(self.headers['to']) + mime_multipart['Cc'] = ", ".join(self.headers['cc']) + mime_multipart['Bcc'] = ", ".join(self.headers['bcc']) mime_multipart['Subject'] = self.headers['subject'] mime_multipart.attach(MIMEText(self.body, 'plain')) return mime_multipart diff --git a/service/pixelated/adapter/pixelated_mail_sender.py b/service/pixelated/adapter/pixelated_mail_sender.py index 3ace6814..6f6340da 100644 --- a/service/pixelated/adapter/pixelated_mail_sender.py +++ b/service/pixelated/adapter/pixelated_mail_sender.py @@ -14,6 +14,7 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . import smtplib +from pixelated.support.functional import flatten class PixelatedMailSender(): @@ -22,7 +23,10 @@ class PixelatedMailSender(): self.smtp_client = smtplib.SMTP('localhost', 4650) def sendmail(self, mail): - _from = self.account_email_address - _to = mail.get_to() + recipients = flatten([mail.get_to(), mail.get_cc(), mail.get_bcc()]) - self.smtp_client.sendmail(_from, _to, mail.to_smtp_format(_from=_from)) + self.smtp_client.sendmail( + self.account_email_address, + recipients, + mail.to_smtp_format(_from=self.account_email_address) + ) diff --git a/service/pixelated/support/__init__.py b/service/pixelated/support/__init__.py new file mode 100644 index 00000000..2756a319 --- /dev/null +++ b/service/pixelated/support/__init__.py @@ -0,0 +1,15 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . diff --git a/service/pixelated/support/functional.py b/service/pixelated/support/functional.py new file mode 100644 index 00000000..e779f5bc --- /dev/null +++ b/service/pixelated/support/functional.py @@ -0,0 +1,20 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . +from itertools import chain + + +def flatten(_list): + return list(chain.from_iterable(_list)) diff --git a/service/test/adapter/pixelated_mail_sender_test.py b/service/test/adapter/pixelated_mail_sender_test.py new file mode 100644 index 00000000..0a8c017b --- /dev/null +++ b/service/test/adapter/pixelated_mail_sender_test.py @@ -0,0 +1,44 @@ +# +# Copyright (c) 2014 ThoughtWorks, Inc. +# +# Pixelated is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pixelated is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with Pixelated. If not, see . +import unittest +from pixelated.adapter.pixelated_mail import PixelatedMail +from pixelated.adapter.pixelated_mail_sender import PixelatedMailSender +from mockito import * +import test_helper + + +class PixelatedMailSenderTest(unittest.TestCase): + def setUp(self): + self.mail_address = "pixelated@pixelated.org" + self.mail_sender = PixelatedMailSender(self.mail_address) + self.mail_sender.smtp_client = mock() + + def test_send_mail_sends_to_To_Cc_and_Bcc(self): + mail_dict = test_helper.mail_dict() + mail_dict['header']['to'] = ['to@pixelated.org', 'anotherto@pixelated.org'] + mail_dict['header']['cc'] = ['cc@pixelated.org', 'anothercc@pixelated.org'] + mail_dict['header']['bcc'] = ['bcc@pixelated.org', 'anotherbcc@pixelated.org'] + + mail = PixelatedMail.from_dict(mail_dict) + mail.to_smtp_format = lambda _from: "mail as smtp string" + + self.mail_sender.sendmail(mail) + + expected_recipients = ['to@pixelated.org', 'anotherto@pixelated.org', 'cc@pixelated.org', + 'anothercc@pixelated.org', + 'bcc@pixelated.org', 'anotherbcc@pixelated.org'] + + verify(self.mail_sender.smtp_client).sendmail(self.mail_address, expected_recipients, "mail as smtp string") diff --git a/service/test/adapter/pixelated_mail_test.py b/service/test/adapter/pixelated_mail_test.py index 8c1d5896..e0b9a662 100644 --- a/service/test/adapter/pixelated_mail_test.py +++ b/service/test/adapter/pixelated_mail_test.py @@ -24,10 +24,10 @@ class TestPixelatedMail(unittest.TestCase): mail_dict = { 'body': 'Este \xe9 o corpo', 'header': { - 'cc': ['cc@pixelated.org'], - 'to': ['to@pixelated.org'], - 'subject': 'Oi', - 'bcc': ['bcc@pixelated.org'] + 'cc': ['cc@pixelated.org', 'anothercc@pixelated.org'], + 'to': ['to@pixelated.org', 'anotherto@pixelated.org'], + 'bcc': ['bcc@pixelated.org', 'anotherbcc@pixelated.org'], + 'subject': 'Oi' }, 'ident': '', 'tags': ['sent'] @@ -62,9 +62,9 @@ class TestPixelatedMail(unittest.TestCase): mail = PixelatedMail.from_dict(self.mail_dict) - self.assertEqual(mail.headers['cc'], ['cc@pixelated.org']) - self.assertEqual(mail.headers['to'], ['to@pixelated.org']) - self.assertEqual(mail.headers['bcc'], ['bcc@pixelated.org']) + self.assertEqual(mail.headers['cc'], ['cc@pixelated.org', 'anothercc@pixelated.org']) + self.assertEqual(mail.headers['to'], ['to@pixelated.org', 'anotherto@pixelated.org']) + self.assertEqual(mail.headers['bcc'], ['bcc@pixelated.org', 'anotherbcc@pixelated.org']) self.assertEqual(mail.headers['subject'], 'Oi') self.assertEqual(mail.ident, '') self.assertEqual(mail.tags, ['sent']) @@ -81,7 +81,9 @@ class TestPixelatedMail(unittest.TestCase): mime_multipart = mail.to_mime_multipart() - self.assertRegexpMatches(mime_multipart.as_string(), "\nTo: to@pixelated.org\n") + self.assertRegexpMatches(mime_multipart.as_string(), "\nTo: to@pixelated.org, anotherto@pixelated.org\n") + self.assertRegexpMatches(mime_multipart.as_string(), "\nCc: cc@pixelated.org, anothercc@pixelated.org\n") + self.assertRegexpMatches(mime_multipart.as_string(), "\nBcc: bcc@pixelated.org, anotherbcc@pixelated.org\n") self.assertRegexpMatches(mime_multipart.as_string(), "\nSubject: Oi\n") self.assertRegexpMatches(mime_multipart.as_string(), "\nEste \xe9 o corpo") diff --git a/service/test/adapter/test_helper.py b/service/test/adapter/test_helper.py index f61ee49d..07914aea 100644 --- a/service/test/adapter/test_helper.py +++ b/service/test/adapter/test_helper.py @@ -25,6 +25,20 @@ LEAP_FLAGS = ['\\Seen', 'List'] +def mail_dict(): + return { + 'header': { + 'to': ['to@pixelated.org', 'anotherto@pixelated.org'], + 'cc': ['cc@pixelated.org', 'anothercc@pixelated.org'], + 'bcc': ['bcc@pixelated.org', 'anotherbcc@pixelated.org'], + 'subject': 'Subject' + }, + 'body': 'Body', + 'ident': '', + 'tags': [] + } + + def leap_mail(uid=0, leap_flags=LEAP_FLAGS, extra_flags=[], headers={'date': str(datetime.now())}): flags = leap_flags + extra_flags return Mock(getUID=Mock(return_value=uid), -- cgit v1.2.3