From 66839f191708a0725c8d9841d5266ad13af8ee81 Mon Sep 17 00:00:00 2001 From: Duda Dornelles Date: Mon, 22 Dec 2014 09:35:01 -0200 Subject: refactoring package structure --- service/pixelated/adapter/services/__init__.py | 15 ++++ .../pixelated/adapter/services/draft_service.py | 34 +++++++++ service/pixelated/adapter/services/mail_sender.py | 38 +++++++++ service/pixelated/adapter/services/mail_service.py | 89 ++++++++++++++++++++++ service/pixelated/adapter/services/mailbox.py | 51 +++++++++++++ service/pixelated/adapter/services/mailboxes.py | 68 +++++++++++++++++ service/pixelated/adapter/services/tag_service.py | 26 +++++++ 7 files changed, 321 insertions(+) create mode 100644 service/pixelated/adapter/services/__init__.py create mode 100644 service/pixelated/adapter/services/draft_service.py create mode 100644 service/pixelated/adapter/services/mail_sender.py create mode 100644 service/pixelated/adapter/services/mail_service.py create mode 100644 service/pixelated/adapter/services/mailbox.py create mode 100644 service/pixelated/adapter/services/mailboxes.py create mode 100644 service/pixelated/adapter/services/tag_service.py (limited to 'service/pixelated/adapter/services') diff --git a/service/pixelated/adapter/services/__init__.py b/service/pixelated/adapter/services/__init__.py new file mode 100644 index 00000000..2756a319 --- /dev/null +++ b/service/pixelated/adapter/services/__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/adapter/services/draft_service.py b/service/pixelated/adapter/services/draft_service.py new file mode 100644 index 00000000..ddb86c5c --- /dev/null +++ b/service/pixelated/adapter/services/draft_service.py @@ -0,0 +1,34 @@ +# +# 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 . + + +class DraftService(object): + __slots__ = '_mailboxes' + + def __init__(self, mailboxes): + self._mailboxes = mailboxes + + def create_draft(self, input_mail): + self._drafts().add(input_mail) + return input_mail + + def update_draft(self, ident, input_mail): + new_mail = self.create_draft(input_mail) + self._drafts().remove(ident) + return new_mail + + def _drafts(self): + return self._mailboxes.drafts() diff --git a/service/pixelated/adapter/services/mail_sender.py b/service/pixelated/adapter/services/mail_sender.py new file mode 100644 index 00000000..50c17ba5 --- /dev/null +++ b/service/pixelated/adapter/services/mail_sender.py @@ -0,0 +1,38 @@ +# +# 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 StringIO import StringIO + +from twisted.internet.defer import Deferred +from twisted.mail.smtp import SMTPSenderFactory +from twisted.internet import reactor +from pixelated.support.functional import flatten + + +class MailSender(): + def __init__(self, account_email_address, smtp_client=None): + self.account_email_address = account_email_address + + def sendmail(self, mail): + recipients = flatten([mail.to, mail.cc, mail.bcc]) + + resultDeferred = Deferred() + senderFactory = SMTPSenderFactory( + fromEmail=self.account_email_address, + toEmail=recipients, + file=StringIO(mail.to_smtp_format()), + deferred=resultDeferred) + + return reactor.connectTCP('localhost', 4650, senderFactory) diff --git a/service/pixelated/adapter/services/mail_service.py b/service/pixelated/adapter/services/mail_service.py new file mode 100644 index 00000000..722b9a29 --- /dev/null +++ b/service/pixelated/adapter/services/mail_service.py @@ -0,0 +1,89 @@ +# +# 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 . + + +class MailService: + __slots__ = ['leap_session', 'account', 'mailbox_name'] + + def __init__(self, mailboxes, mail_sender, tag_service, soledad_querier): + self.tag_service = tag_service + self.mailboxes = mailboxes + self.querier = soledad_querier + self.mail_sender = mail_sender + + def all_mails(self): + return self.querier.all_mails() + + def mails(self, ids): + return self.querier.mails(ids) + + def update_tags(self, mail_id, new_tags): + reserved_words = self.tag_service.extract_reserved(new_tags) + if len(reserved_words): + raise ValueError('None of the following words can be used as tags: ' + ' '.join(reserved_words)) + mail = self.mail(mail_id) + mail.update_tags(set(new_tags)) + return mail + + def mail(self, mail_id): + return self.mailboxes.mail(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) + + def thread(self, thread_id): + raise NotImplementedError() + + def mark_as_read(self, mail_id): + return self.mail(mail_id).mark_as_read() + + def mark_as_unread(self, mail_id): + return self.mail(mail_id).mark_as_unread() + + def tags_for_thread(self, thread): + raise NotImplementedError() + + def add_tag_to_thread(self, thread_id, tag): + raise NotImplementedError() + + def remove_tag_from_thread(self, thread_id, tag): + raise NotImplementedError() + + def delete_mail(self, mail_id): + return self.mailboxes.move_to_trash(mail_id) + + def delete_permanent(self, mail_id): + mail = self.mail(mail_id) + self.querier.remove_mail(mail) + + def save_draft(self, draft): + raise NotImplementedError() + + def draft_reply_for(self, mail_id): + raise NotImplementedError() + + def all_contacts(self, query): + raise NotImplementedError() + + 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/adapter/services/mailbox.py b/service/pixelated/adapter/services/mailbox.py new file mode 100644 index 00000000..fbdbfc30 --- /dev/null +++ b/service/pixelated/adapter/services/mailbox.py @@ -0,0 +1,51 @@ +# +# 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 . + + +class Mailbox: + + def __init__(self, mailbox_name, querier): + self.mailbox_name = mailbox_name + self.mailbox_tag = mailbox_name.lower() + self.querier = querier + + def mails(self): + _mails = self.querier.all_mails_by_mailbox(self.mailbox_name) + + result = [] + for mail in _mails: + result.append(mail) + return result + + def mails_by_tags(self, tags): + if 'all' in tags or self.mailbox_tag in tags: + return self.mails() + return [mail for mail in self.mails() if len(mail.tags.intersection(tags)) > 0] + + def mail(self, mail_id): + return self.querier.mail(mail_id) + + def add(self, mail): + return self.querier.create_mail(mail, self.mailbox_name) + + def remove(self, ident): + mail = self.querier.mail(ident) + mail.remove_all_tags() + self.querier.remove_mail(mail) + + @classmethod + def create(cls, mailbox_name, soledad_querier): + return Mailbox(mailbox_name, soledad_querier) diff --git a/service/pixelated/adapter/services/mailboxes.py b/service/pixelated/adapter/services/mailboxes.py new file mode 100644 index 00000000..56304dd6 --- /dev/null +++ b/service/pixelated/adapter/services/mailboxes.py @@ -0,0 +1,68 @@ +# +# 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 pixelated.adapter.services.mailbox import Mailbox +from pixelated.adapter.listeners.mailbox_indexer_listener import MailboxIndexerListener + + +class Mailboxes(): + + def __init__(self, account, soledad_querier): + self.account = account + self.querier = soledad_querier + for mailbox_name in account.mailboxes: + MailboxIndexerListener.listen(self.account, mailbox_name, soledad_querier) + + def _create_or_get(self, mailbox_name): + mailbox_name = mailbox_name.upper() + if mailbox_name not in self.account.mailboxes: + self.account.addMailbox(mailbox_name) + MailboxIndexerListener.listen(self.account, mailbox_name, self.querier) + return Mailbox.create(mailbox_name, self.querier) + + def inbox(self): + return self._create_or_get('INBOX') + + def drafts(self): + return self._create_or_get('DRAFTS') + + def trash(self): + return self._create_or_get('TRASH') + + def sent(self): + return self._create_or_get('SENT') + + def mailboxes(self): + return [self._create_or_get(leap_mailbox_name) for leap_mailbox_name in self.account.mailboxes] + + def mails_by_tag(self, query_tags): + mails = [] + for mailbox in self.mailboxes(): + mails.extend(mailbox.mails_by_tags(query_tags)) + + return mails + + def move_to_trash(self, mail_id): + mail = self.querier.mail(mail_id) + mail.remove_all_tags() + mail.set_mailbox(self.trash().mailbox_name) + mail.save() + return mail + + def mail(self, mail_id): + for mailbox in self.mailboxes(): + mail = mailbox.mail(mail_id) + if mail: + return mail diff --git a/service/pixelated/adapter/services/tag_service.py b/service/pixelated/adapter/services/tag_service.py new file mode 100644 index 00000000..c723b04c --- /dev/null +++ b/service/pixelated/adapter/services/tag_service.py @@ -0,0 +1,26 @@ +# +# 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 pixelated.adapter.model.tag import Tag + + +class TagService: + + instance = None + SPECIAL_TAGS = {Tag('inbox', True), Tag('sent', True), Tag('drafts', True), Tag('trash', True)} + + @classmethod + def extract_reserved(cls, tags): + return {tag.name for tag in cls.SPECIAL_TAGS if tag.name in tags} -- cgit v1.2.3