From b727ab8090790db2854dac191faee702f085ac20 Mon Sep 17 00:00:00 2001 From: Duda Dornelles Date: Fri, 29 Aug 2014 16:29:22 -0300 Subject: Refactoring into mailboxes and mailsender - less colaborators for mail service --- service/pixelated/adapter/mail_service.py | 73 ++++------------------ service/pixelated/adapter/pixelated_mail_sender.py | 28 +++++++++ service/pixelated/adapter/pixelated_mailbox.py | 7 +++ service/pixelated/adapter/pixelated_mailboxes.py | 28 +++++++++ service/pixelated/bitmask_libraries/session.py | 20 +++++- service/pixelated/search_query.py | 1 + service/pixelated/user_agent.py | 29 +++++---- 7 files changed, 111 insertions(+), 75 deletions(-) create mode 100644 service/pixelated/adapter/pixelated_mail_sender.py create mode 100644 service/pixelated/adapter/pixelated_mailboxes.py (limited to 'service/pixelated') diff --git a/service/pixelated/adapter/mail_service.py b/service/pixelated/adapter/mail_service.py index 48495d51..6949d6cb 100644 --- a/service/pixelated/adapter/mail_service.py +++ b/service/pixelated/adapter/mail_service.py @@ -13,79 +13,33 @@ # # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . -import traceback -import sys -import os -import smtplib -from pixelated.bitmask_libraries.smtp import LeapSmtp + from twisted.internet import defer -from pixelated.bitmask_libraries.config import LeapConfig -from pixelated.bitmask_libraries.provider import LeapProvider -from pixelated.bitmask_libraries.session import LeapSessionFactory -from pixelated.bitmask_libraries.auth import LeapCredentials from pixelated.adapter.pixelated_mailbox import PixelatedMailbox from pixelated.adapter.tag import Tag -def open_leap_session(username, password, server_name): - try: - certs_home = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..", "certificates")) - - config = LeapConfig(certs_home=certs_home) - provider = LeapProvider(server_name, config) - session = LeapSessionFactory(provider).create(LeapCredentials(username, password)) - return session - except: - traceback.print_exc(file=sys.stdout) - raise - - class MailService: __slots__ = ['leap_session', 'account', 'mailbox_name'] - def __init__(self, leap_session): - self.leap_session = leap_session - self.account = leap_session.account - self.user_email = leap_session.account_email() - self.mailbox_name = 'INBOX' - - def start(self): - try: - self.smtp_server = self._create_smtp_server() - self.smtp_client = self._create_smtp_client(self.smtp_server.smtp_info()) - except: - traceback.print_exc(file=sys.stdout) - raise - - def _create_smtp_server(self): - server = LeapSmtp(self.leap_session.provider, self.leap_session.nicknym.keymanager, self.leap_session.srp_session) - server.start() - return server - - def _create_smtp_client(self, smtp_info): - smtp_servername, smtp_port = smtp_info - client = smtplib.SMTP(smtp_servername, smtp_port) - return client + def __init__(self, mailboxes, mail_sender): + self.mailboxes = mailboxes + self.mail_sender = mail_sender @property def mailbox(self): - return PixelatedMailbox(self.account.getMailbox(self.mailbox_name)) + return self.mailboxes.inbox() def mails(self, query): + _mails = None + if not query: return self.mailbox.mails() - mails = [] if query['tags']: - tags = [Tag(tag) for tag in query['tags']] - for leap_mailbox_name in self.account.mailboxes: - mailbox = PixelatedMailbox(self.account.getMailbox(leap_mailbox_name)) - if len(mailbox.all_tags().intersection(tags)): - # mailbox has at least one mail with tag - for mail in mailbox.mails(): - if len(mail.tags.intersection(tags)) > 0: - mails.append(mail) - return mails + _mails = self.mailboxes.mails_by_tag(query['tags']) + + return sorted(_mails or [], key=lambda mail: mail.date, reverse=True) def update_tags(self, mail_id, new_tags): mail = self.mail(mail_id) @@ -113,17 +67,14 @@ class MailService: def _set_mail_flags(self, mail_id, flags, operation): observer = defer.Deferred() - leap_mailbox = self.account.getMailbox(self.mailbox_name) + leap_mailbox = self.mailboxes.leap_inbox_mailbox() self.mailbox.messages.set_flags(leap_mailbox, [mail_id], tuple(flags), operation, observer) def mail(self, mail_id): return self.mailbox.mail(mail_id) def send(self, mail): - _from = self.user_email - _to = mail.get_to() - - self.smtp_client.sendmail(_from, _to, mail.to_smtp_format(_from=_from)) + self.mail_sender.sendmail(mail) def all_tags(self): return self.mailbox.all_tags() diff --git a/service/pixelated/adapter/pixelated_mail_sender.py b/service/pixelated/adapter/pixelated_mail_sender.py new file mode 100644 index 00000000..3ace6814 --- /dev/null +++ b/service/pixelated/adapter/pixelated_mail_sender.py @@ -0,0 +1,28 @@ +# +# 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 smtplib + + +class PixelatedMailSender(): + def __init__(self, account_email_address): + self.account_email_address = account_email_address + self.smtp_client = smtplib.SMTP('localhost', 4650) + + def sendmail(self, mail): + _from = self.account_email_address + _to = mail.get_to() + + self.smtp_client.sendmail(_from, _to, mail.to_smtp_format(_from=_from)) diff --git a/service/pixelated/adapter/pixelated_mailbox.py b/service/pixelated/adapter/pixelated_mailbox.py index 280e67c7..2f50c2b4 100644 --- a/service/pixelated/adapter/pixelated_mailbox.py +++ b/service/pixelated/adapter/pixelated_mailbox.py @@ -35,6 +35,9 @@ class PixelatedMailbox: mails = [PixelatedMail.from_leap_mail(mail) for mail in mails] return mails + def mails_by_tags(self, tags): + return [mail for mail in self.mails() if len(mail.tags.intersection(tags)) > 0] + def mail(self, mail_id): for message in self.leap_mailbox.messages: if message.getUID() == int(mail_id): @@ -56,3 +59,7 @@ class PixelatedMailbox: flags = tuple(current_flags.union(new_flags)) self.leap_mailbox.setFlags(flags) + + @classmethod + def create(cls, account, mailbox_name='INBOX'): + return PixelatedMailbox(account.getMailbox(mailbox_name)) diff --git a/service/pixelated/adapter/pixelated_mailboxes.py b/service/pixelated/adapter/pixelated_mailboxes.py new file mode 100644 index 00000000..1125c137 --- /dev/null +++ b/service/pixelated/adapter/pixelated_mailboxes.py @@ -0,0 +1,28 @@ +from pixelated.adapter.tag import Tag +from pixelated.adapter.pixelated_mailbox import PixelatedMailbox + + +class PixelatedMailBoxes(): + def __init__(self, account): + self.account = account + self.mailbox_name = 'INBOX' + + def inbox(self): + return PixelatedMailbox.create(self.account) + + @property + def mailboxes(self): + return [PixelatedMailbox.create(self.account, leap_mailbox_name) for leap_mailbox_name in + self.account.mailboxes] + + def mails_by_tag(self, query_tags): + tags = map(Tag, query_tags) + + mails = [] + for mailbox in self.mailboxes: + mails.extend(mailbox.mails_by_tags(tags)) + + return mails + + def leap_inbox_mailbox(self): + return self.account.getMailbox(self.mailbox_name) diff --git a/service/pixelated/bitmask_libraries/session.py b/service/pixelated/bitmask_libraries/session.py index bb9bd3fe..09229e17 100644 --- a/service/pixelated/bitmask_libraries/session.py +++ b/service/pixelated/bitmask_libraries/session.py @@ -21,16 +21,31 @@ from leap.mail.imap.account import SoledadBackedAccount import sys from leap.mail.imap.memorystore import MemoryStore from leap.mail.imap.soledadstore import SoledadStore +from pixelated.bitmask_libraries.config import LeapConfig +from pixelated.bitmask_libraries.provider import LeapProvider from twisted.internet import reactor from .nicknym import NickNym -from .auth import LeapAuthenticator +from .auth import LeapAuthenticator, LeapCredentials from .soledad import SoledadSessionFactory, SoledadSession from .smtp import LeapSmtp SESSIONS = {} +def open(username, password, server_name): + try: + certs_home = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..", "certificates")) + + config = LeapConfig(certs_home=certs_home) + provider = LeapProvider(server_name, config) + session = LeapSessionFactory(provider).create(LeapCredentials(username, password)) + return session + except: + traceback.print_exc(file=sys.stdout) + raise + + class LeapSession(object): """ A LEAP session. @@ -118,6 +133,9 @@ class LeapSessionFactory(object): incoming_mail_fetcher = self._create_incoming_mail_fetcher(nicknym, soledad, account, auth) + smtp = LeapSmtp(self._provider, nicknym.keymanager, auth) + smtp.start() + return LeapSession(self._provider, auth, soledad, nicknym, account, incoming_mail_fetcher) def _lookup_session(self, key): diff --git a/service/pixelated/search_query.py b/service/pixelated/search_query.py index e2860cac..278e1f2f 100644 --- a/service/pixelated/search_query.py +++ b/service/pixelated/search_query.py @@ -22,6 +22,7 @@ def compile(query): sanitized_query = re.sub(r"['\"]", "", query.encode('utf8')) scanner = StringScanner(sanitized_query) first_token = True + while not scanner.is_eos: token = scanner.scan(_next_token()) diff --git a/service/pixelated/user_agent.py b/service/pixelated/user_agent.py index cee360cb..13dd767c 100644 --- a/service/pixelated/user_agent.py +++ b/service/pixelated/user_agent.py @@ -14,20 +14,22 @@ # You should have received a copy of the GNU Affero General Public License # along with Pixelated. If not, see . import json -import os -import datetime -import dateutil.parser as dateparser +import os from flask import Flask from flask import request from flask import Response - +from pixelated.adapter.pixelated_mail_sender import PixelatedMailSender +from pixelated.adapter.pixelated_mailboxes import PixelatedMailBoxes import pixelated.reactor_manager as reactor_manager import pixelated.search_query as search_query -from pixelated.adapter.mail_service import MailService, open_leap_session +import pixelated.bitmask_libraries.session as LeapSession +from pixelated.adapter.mail_service import MailService from pixelated.adapter.pixelated_mail import PixelatedMail + static_folder = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..", "web-ui", "app")) + # this is a workaround for packaging if not os.path.exists(static_folder): static_folder = os.path.abspath(os.path.join(os.path.abspath(__file__), "..", "..", "..", "web-ui", "app")) @@ -73,10 +75,6 @@ def mails(): if "inbox" in query['tags']: mails = [mail for mail in mails if not mail.has_tag('trash')] - mails = sorted(mails, key=lambda mail: mail.date, reverse=True) - - mails = [mail.as_dict() for mail in mails] - response = { "stats": { "total": len(mails), @@ -84,7 +82,7 @@ def mails(): "starred": 0, "replied": 0 }, - "mails": mails + "mails": [mail.as_dict() for mail in mails] } return respond_json(response) @@ -141,10 +139,15 @@ def setup(): debug_enabled = os.environ.get('DEBUG', False) reactor_manager.start_reactor(logging=debug_enabled) app.config.from_pyfile(os.path.join(os.environ['HOME'], '.pixelated')) - leap_session = open_leap_session(app.config['LEAP_USERNAME'], app.config['LEAP_PASSWORD'], app.config['LEAP_SERVER_NAME']) - mail_service = MailService(leap_session) + + leap_session = LeapSession.open(app.config['LEAP_USERNAME'], app.config['LEAP_PASSWORD'], + app.config['LEAP_SERVER_NAME']) + pixelated_mailboxes = PixelatedMailBoxes(leap_session.account) + pixelated_mail_sender = PixelatedMailSender(leap_session.account_email()) + global mail_service - mail_service.start() + mail_service = MailService(pixelated_mailboxes, pixelated_mail_sender) + app.run(host=app.config['HOST'], debug=debug_enabled, port=app.config['PORT'], use_reloader=False) -- cgit v1.2.3