From 4ac714acfd3192a397028f1260c5929e80ef15b5 Mon Sep 17 00:00:00 2001 From: Alexandre Pretto Nunes Date: Wed, 28 Jan 2015 14:42:47 -0200 Subject: #249 make the sending process a deferred --- service/pixelated/adapter/services/mail_sender.py | 4 +++- service/pixelated/adapter/services/mail_service.py | 12 ++++++++---- service/pixelated/resources/mails_resource.py | 18 ++++++++++++++---- 3 files changed, 25 insertions(+), 9 deletions(-) (limited to 'service') diff --git a/service/pixelated/adapter/services/mail_sender.py b/service/pixelated/adapter/services/mail_sender.py index 50c17ba5..1c2d7ce1 100644 --- a/service/pixelated/adapter/services/mail_sender.py +++ b/service/pixelated/adapter/services/mail_sender.py @@ -35,4 +35,6 @@ class MailSender(): file=StringIO(mail.to_smtp_format()), deferred=resultDeferred) - return reactor.connectTCP('localhost', 4650, senderFactory) + reactor.connectTCP('localhost', 4650, senderFactory) + + return resultDeferred diff --git a/service/pixelated/adapter/services/mail_service.py b/service/pixelated/adapter/services/mail_service.py index 3b70890b..26b4e162 100644 --- a/service/pixelated/adapter/services/mail_service.py +++ b/service/pixelated/adapter/services/mail_service.py @@ -45,10 +45,14 @@ class MailService: return not(not(self.querier.get_header_by_chash(mail_id))) def send(self, last_draft_ident, mail): - self.mail_sender.sendmail(mail) - if last_draft_ident: - self.mailboxes.drafts().remove(last_draft_ident) - return self.mailboxes.sent().add(mail) + result = self.mail_sender.sendmail(mail) + + def success(_): + if last_draft_ident: + self.mailboxes.drafts().remove(last_draft_ident) + return self.mailboxes.sent().add(mail) + result.addCallback(success) + return result def mark_as_read(self, mail_id): return self.mail(mail_id).mark_as_read() diff --git a/service/pixelated/resources/mails_resource.py b/service/pixelated/resources/mails_resource.py index a6eb0fe0..40b29cfc 100644 --- a/service/pixelated/resources/mails_resource.py +++ b/service/pixelated/resources/mails_resource.py @@ -1,6 +1,7 @@ import json from pixelated.adapter.model.mail import InputMail -from pixelated.resources import respond_json +from pixelated.resources import respond_json, respond_json_deferred +from twisted.web import server from twisted.web.resource import Resource @@ -102,10 +103,19 @@ class MailsResource(Resource): draft_id = content_dict.get('ident') if draft_id: self._search_engine.remove_from_index(draft_id) - _mail = self._mail_service.send(draft_id, _mail) - self._search_engine.index_mail(_mail) + sendDeferred = self._mail_service.send(draft_id, _mail) - return respond_json(_mail.as_dict(), request) + def onSuccess(mail): + self._search_engine.index_mail(mail) + respond_json_deferred(mail.as_dict(), request) + + def onError(error): + return respond_json_deferred({'message': _format_exception(error)}, request, status_code=422) + + sendDeferred.addCallback(onSuccess) + sendDeferred.addErrback(onError) + + return server.NOT_DONE_YET except Exception as error: return respond_json({'message': _format_exception(error)}, request, status_code=422) -- cgit v1.2.3 From a484020944f7e89200f6b0d86e72084f0dec5491 Mon Sep 17 00:00:00 2001 From: Jefferson Stachelski Date: Wed, 28 Jan 2015 15:06:00 -0200 Subject: #249 removed unecessary return --- service/pixelated/resources/mails_resource.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'service') diff --git a/service/pixelated/resources/mails_resource.py b/service/pixelated/resources/mails_resource.py index 40b29cfc..6cf3df8e 100644 --- a/service/pixelated/resources/mails_resource.py +++ b/service/pixelated/resources/mails_resource.py @@ -110,7 +110,7 @@ class MailsResource(Resource): respond_json_deferred(mail.as_dict(), request) def onError(error): - return respond_json_deferred({'message': _format_exception(error)}, request, status_code=422) + respond_json_deferred({'message': _format_exception(error)}, request, status_code=422) sendDeferred.addCallback(onSuccess) sendDeferred.addErrback(onError) -- cgit v1.2.3 From cad4bbf073663db828fa7ac43b27ae00556e2797 Mon Sep 17 00:00:00 2001 From: Jefferson Stachelski Date: Fri, 30 Jan 2015 14:04:16 -0200 Subject: 249 Implemented a feature that send an email when something was wrong to send email --- service/pixelated/adapter/model/mail.py | 11 ++++ service/pixelated/adapter/services/mail_service.py | 16 +++--- service/pixelated/resources/mails_resource.py | 59 +++++++++++----------- service/test/unit/adapter/test_mail_service.py | 2 +- 4 files changed, 47 insertions(+), 41 deletions(-) (limited to 'service') diff --git a/service/pixelated/adapter/model/mail.py b/service/pixelated/adapter/model/mail.py index 42953064..dfc0ea1c 100644 --- a/service/pixelated/adapter/model/mail.py +++ b/service/pixelated/adapter/model/mail.py @@ -185,6 +185,17 @@ class InputMail(Mail): mime_multipart['From'] = InputMail.FROM_EMAIL_ADDRESS return mime_multipart.as_string() + @staticmethod + def delivery_error_template(delivery_address): + return InputMail.from_dict({ + 'body': "Mail undelivered for %s" % delivery_address, + 'header': { + 'bcc': [], + 'cc': [], + 'subject': "Mail undelivered for %s" % delivery_address + } + }) + @staticmethod def from_dict(mail_dict): input_mail = InputMail() diff --git a/service/pixelated/adapter/services/mail_service.py b/service/pixelated/adapter/services/mail_service.py index 26b4e162..7bf76676 100644 --- a/service/pixelated/adapter/services/mail_service.py +++ b/service/pixelated/adapter/services/mail_service.py @@ -13,8 +13,6 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . - - class MailService: __slots__ = ['leap_session', 'account', 'mailbox_name'] @@ -44,15 +42,13 @@ class MailService: def mail_exists(self, mail_id): return not(not(self.querier.get_header_by_chash(mail_id))) - def send(self, last_draft_ident, mail): - result = self.mail_sender.sendmail(mail) + def send(self, mail): + self.mail_sender.sendmail(mail) - def success(_): - if last_draft_ident: - self.mailboxes.drafts().remove(last_draft_ident) - return self.mailboxes.sent().add(mail) - result.addCallback(success) - return result + def move_to_send(self, last_draft_ident, mail): + if last_draft_ident: + self.mailboxes.drafts().remove(last_draft_ident) + return self.mailboxes.sent().add(mail) def mark_as_read(self, mail_id): return self.mail(mail_id).mark_as_read() diff --git a/service/pixelated/resources/mails_resource.py b/service/pixelated/resources/mails_resource.py index 6cf3df8e..4280d7ec 100644 --- a/service/pixelated/resources/mails_resource.py +++ b/service/pixelated/resources/mails_resource.py @@ -3,15 +3,14 @@ from pixelated.adapter.model.mail import InputMail from pixelated.resources import respond_json, respond_json_deferred from twisted.web import server from twisted.web.resource import Resource - - -def _format_exception(e): - exception_info = map(str, list(e.args)) - return '\n'.join(exception_info) +from leap.common.events import ( + register, + unregister, + events_pb2 as proto +) class MailsUnreadResource(Resource): - isLeaf = True def __init__(self, mail_service, search_engine): @@ -29,7 +28,6 @@ class MailsUnreadResource(Resource): class MailsReadResource(Resource): - isLeaf = True def __init__(self, mail_service, search_engine): @@ -47,7 +45,6 @@ class MailsReadResource(Resource): class MailsDeleteResource(Resource): - isLeaf = True def __init__(self, mail_service, search_engine): @@ -73,6 +70,15 @@ class MailsDeleteResource(Resource): class MailsResource(Resource): + def _register_smtp_error_handler(self): + + def on_error(event): + delivery_error_mail = InputMail.delivery_error_template(delivery_address=event.content) + delivery_error_mail = self._mail_service.mailboxes.inbox().add(delivery_error_mail) + self._search_engine.index_mail(delivery_error_mail) + + register(signal=proto.SMTP_SEND_MESSAGE_ERROR, callback=on_error) + def __init__(self, search_engine, mail_service, draft_service): Resource.__init__(self) self.putChild('delete', MailsDeleteResource(mail_service, search_engine)) @@ -82,9 +88,11 @@ class MailsResource(Resource): self._draft_service = draft_service self._mail_service = mail_service self._search_engine = search_engine + self._register_smtp_error_handler() def render_GET(self, request): - mail_ids, total = self._search_engine.search(request.args.get('q')[0], request.args.get('w')[0], request.args.get('p')[0]) + mail_ids, total = self._search_engine.search(request.args.get('q')[0], request.args.get('w')[0], + request.args.get('p')[0]) mails = self._mail_service.mails(mail_ids) response = { @@ -97,27 +105,18 @@ class MailsResource(Resource): return respond_json(response, request) def render_POST(self, request): - try: - content_dict = json.loads(request.content.read()) - _mail = InputMail.from_dict(content_dict) - draft_id = content_dict.get('ident') - if draft_id: - self._search_engine.remove_from_index(draft_id) - sendDeferred = self._mail_service.send(draft_id, _mail) - - def onSuccess(mail): - self._search_engine.index_mail(mail) - respond_json_deferred(mail.as_dict(), request) - - def onError(error): - respond_json_deferred({'message': _format_exception(error)}, request, status_code=422) - - sendDeferred.addCallback(onSuccess) - sendDeferred.addErrback(onError) - - return server.NOT_DONE_YET - except Exception as error: - return respond_json({'message': _format_exception(error)}, request, status_code=422) + content_dict = json.loads(request.content.read()) + _mail = InputMail.from_dict(content_dict) + draft_id = content_dict.get('ident') + + self._mail_service.send(_mail) + sent_mail = self._mail_service.move_to_send(draft_id, _mail) + self._search_engine.index_mail(sent_mail) + + if draft_id: + self._search_engine.remove_from_index(draft_id) + + return respond_json(sent_mail.as_dict(), request) def render_PUT(self, request): content_dict = json.loads(request.content.read()) diff --git a/service/test/unit/adapter/test_mail_service.py b/service/test/unit/adapter/test_mail_service.py index fca6e79b..32b45dc4 100644 --- a/service/test/unit/adapter/test_mail_service.py +++ b/service/test/unit/adapter/test_mail_service.py @@ -34,7 +34,7 @@ class TestMailService(unittest.TestCase): def test_send_mail(self): mail = "mail" - self.mail_service.send(1, mail) + self.mail_service.send(mail) verify(self.mail_sender).sendmail(mail) -- cgit v1.2.3