From f273d2abeefa0d77d306bcfab3135195afbc31c3 Mon Sep 17 00:00:00 2001 From: Lisa Junger Date: Wed, 19 Nov 2014 10:44:08 +0100 Subject: added functionality for reply all to service. --- service/pixelated/adapter/mail.py | 10 ++++++ service/pixelated/adapter/mail_service.py | 4 +++ service/pixelated/config/app_factory.py | 31 ++++++++++++++-- service/pixelated/controllers/mails_controller.py | 4 +++ service/test/integration/drafts_test.py | 2 ++ service/test/integration/reply_test.py | 42 ++++++++++++++++++++++ service/test/unit/adapter/mail_service_test.py | 8 +++++ service/test/unit/adapter/mail_test.py | 9 +++++ .../test/unit/controllers/mails_controller_test.py | 7 ++++ 9 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 service/test/integration/reply_test.py (limited to 'service') diff --git a/service/pixelated/adapter/mail.py b/service/pixelated/adapter/mail.py index 949daa9e..6beac4c2 100644 --- a/service/pixelated/adapter/mail.py +++ b/service/pixelated/adapter/mail.py @@ -329,3 +329,13 @@ class PixelatedMail(Mail): 'mailbox': self.mailbox_name.lower(), 'attachments': self.parts['attachments'] if self.parts else [] } + + def to_reply_template(self): + template = self.as_dict() + recipients = template['header']['to'][0] + for recipient in recipients: + if recipient == InputMail.FROM_EMAIL_ADDRESS: + recipients.remove(recipient) + template['header']['to'][0] = recipients + template['header']['subject'] = 'Re: %s' % template['header']['subject'] + return template diff --git a/service/pixelated/adapter/mail_service.py b/service/pixelated/adapter/mail_service.py index 6c093b6d..722b9a29 100644 --- a/service/pixelated/adapter/mail_service.py +++ b/service/pixelated/adapter/mail_service.py @@ -83,3 +83,7 @@ class MailService: def drafts(self): raise NotImplementedError() + + def reply_all_template(self, mail_id): + mail = self.mail(mail_id) + return mail.to_reply_template() diff --git a/service/pixelated/config/app_factory.py b/service/pixelated/config/app_factory.py index ede19e60..2021556d 100644 --- a/service/pixelated/config/app_factory.py +++ b/service/pixelated/config/app_factory.py @@ -62,13 +62,40 @@ def update_info_sync_and_index_partial(sync_info_controller, search_engine, mail return wrapper +def _setup_routes(app, home_controller, mails_controller, tags_controller, features_controller, sync_info_controller, + attachments_controller): + # mails + app.route('/mails', methods=['GET'])(mails_controller.mails) + app.route('/mail//read', methods=['POST'])(mails_controller.mark_mail_as_read) + app.route('/mail//unread', methods=['POST'])(mails_controller.mark_mail_as_unread) + app.route('/mails/unread', methods=['POST'])(mails_controller.mark_many_mail_unread) + app.route('/mails/read', methods=['POST'])(mails_controller.mark_many_mail_read) + app.route('/mail/', methods=['GET'])(mails_controller.mail) + app.route('/mail//reply_all_template', methods=['GET'])(mails_controller.reply_all_template) + app.route('/mail/', methods=['DELETE'])(mails_controller.delete_mail) + app.route('/mails', methods=['DELETE'])(mails_controller.delete_mails) + app.route('/mails', methods=['POST'])(mails_controller.send_mail) + app.route('/mail//tags', methods=['POST'])(mails_controller.mail_tags) + app.route('/mails', methods=['PUT'])(mails_controller.update_draft) + # tags + app.route('/tags', methods=['GET'])(tags_controller.tags) + # features + app.route('/features', methods=['GET'])(features_controller.features) + # sync info + app.route('/sync_info', methods=['GET'])(sync_info_controller.sync_info) + # attachments + app.route('/attachment/', methods=['GET'])(attachments_controller.attachment) + # static + app.route('/', methods=['GET'], branch=True)(home_controller.home) + + def init_leap_session(app): try: leap_session = LeapSession.open(app.config['LEAP_USERNAME'], app.config['LEAP_PASSWORD'], app.config['LEAP_SERVER_NAME']) - except ConnectionError: - print("Can't connect to the requested provider") + except ConnectionError, error: + print("Can't connect to the requested provider", error) sys.exit(1) except LeapAuthException, e: print("Couldn't authenticate with the credentials provided %s" % e.message) diff --git a/service/pixelated/controllers/mails_controller.py b/service/pixelated/controllers/mails_controller.py index 3a2e0d3b..d84018dc 100644 --- a/service/pixelated/controllers/mails_controller.py +++ b/service/pixelated/controllers/mails_controller.py @@ -123,6 +123,10 @@ class MailsController: self._search_engine.index_mail(self._mail_service.mail(ident)) return respond_json({'ident': ident}, request) + def reply_all_template(self, request, mail_id): + mail = self._mail_service.reply_all_template(mail_id) + return respond_json(mail, request) + def _format_exception(self, exception): exception_info = map(str, list(exception.args)) return '\n'.join(exception_info) diff --git a/service/test/integration/drafts_test.py b/service/test/integration/drafts_test.py index 2ba14dfd..7fd0a46b 100644 --- a/service/test/integration/drafts_test.py +++ b/service/test/integration/drafts_test.py @@ -14,6 +14,8 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . +import unittest + from test.support.integration import * diff --git a/service/test/integration/reply_test.py b/service/test/integration/reply_test.py new file mode 100644 index 00000000..177cbb6b --- /dev/null +++ b/service/test/integration/reply_test.py @@ -0,0 +1,42 @@ +# +# 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 test.support.integration_helper import MailBuilder, SoledadTestBase +from pixelated.adapter.mail import InputMail + + +class ReplyTest(SoledadTestBase): + + def setUp(self): + SoledadTestBase.setUp(self) + + def tearDown(self): + SoledadTestBase.tearDown(self) + + def test_get_provides_template_for_reply_all(self): + InputMail.FROM_EMAIL_ADDRESS = 'user@pixelated.org' + mail = MailBuilder().with_subject('some subject').with_to_addresses(['user@pixelated.org', 'another@pixelated.org']).with_ident(1).build_input_mail() + self.add_mail_to_inbox(mail) + + mails = self.get_mails_by_tag('inbox') + self.assertNotIn('read', mails[0].status) + + response = self.reply_all_template(mail.ident) + + self.assertEquals(200, response['code']) + self.assertEquals(['another@pixelated.org'], response['body']['header']['to'][0]) + self.assertEquals('Re: some subject', response['body']['header']['subject']) diff --git a/service/test/unit/adapter/mail_service_test.py b/service/test/unit/adapter/mail_service_test.py index c69f8f74..e5085724 100644 --- a/service/test/unit/adapter/mail_service_test.py +++ b/service/test/unit/adapter/mail_service_test.py @@ -49,3 +49,11 @@ class TestMailService(unittest.TestCase): self.mail_service.delete_mail(1) verify(self.mailboxes).move_to_trash(1) + + def test_reply_all_template(self): + mail = mock() + when(self.mail_service).mail(1).thenReturn(mail) + + self.mail_service.reply_all_template(1) + + verify(mail).to_reply_template() diff --git a/service/test/unit/adapter/mail_test.py b/service/test/unit/adapter/mail_test.py index e0879b44..cf821035 100644 --- a/service/test/unit/adapter/mail_test.py +++ b/service/test/unit/adapter/mail_test.py @@ -125,6 +125,15 @@ class TestPixelatedMail(unittest.TestCase): self.assertNotIn('\n', address) self.assertNotIn(',', address) self.assertEquals(4, len(mail.headers[header_label])) + def test_to_reply_template_removes_user_from_to(self): + InputMail.FROM_EMAIL_ADDRESS = 'user@pixelated.org' + fdoc, hdoc, bdoc = test_helper.leap_mail(flags=['\\Recent']) + mail = PixelatedMail.from_soledad(fdoc, hdoc, bdoc, soledad_querier=self.querier) + hdoc.content['headers']['To'] = ['me@pixelated.org', 'user@pixelated.org'] + + template = mail.to_reply_template() + + self.assertFalse('user@pixelated.org' in template['header']['to'][0]) def test_content_type_is_read_from_headers_for_plain_mail_when_converted_to_raw(self): fdoc, hdoc, bdoc = test_helper.leap_mail(flags=['\\Recent'], body=u'some umlaut \xc3', extra_headers={'Content-Type': 'text/plain; charset=ISO-8859-1'}) diff --git a/service/test/unit/controllers/mails_controller_test.py b/service/test/unit/controllers/mails_controller_test.py index 6d566c83..c5234039 100644 --- a/service/test/unit/controllers/mails_controller_test.py +++ b/service/test/unit/controllers/mails_controller_test.py @@ -113,6 +113,13 @@ class TestMailsController(unittest.TestCase): verify(self.mail_service).delete_permanent(1) + def test_reply_all_returns_template(self): + when(self.mail_service).reply_all_template(1).thenReturn(self.input_mail.json) + + self.mails_controller.reply_all_template(self.dummy_request, 1) + + verify(self.mail_service).reply_all_template(1) + def _successfuly_send_mail(self, ident, mail): sent_mail = mock() sent_mail.mailbox_name = 'TRASH' -- cgit v1.2.3