diff options
Diffstat (limited to 'service/pixelated')
-rw-r--r-- | service/pixelated/adapter/mailstore/leap_mailstore.py | 40 | ||||
-rw-r--r-- | service/pixelated/adapter/model/mail.py | 6 | ||||
-rw-r--r-- | service/pixelated/adapter/services/mail_service.py | 2 | ||||
-rw-r--r-- | service/pixelated/config/services.py | 2 | ||||
-rw-r--r-- | service/pixelated/resources/mail_resource.py | 13 | ||||
-rw-r--r-- | service/pixelated/resources/mails_resource.py | 2 | ||||
-rw-r--r-- | service/pixelated/support/replier.py | 32 |
7 files changed, 52 insertions, 45 deletions
diff --git a/service/pixelated/adapter/mailstore/leap_mailstore.py b/service/pixelated/adapter/mailstore/leap_mailstore.py index c2912bbe..cf8c8ed1 100644 --- a/service/pixelated/adapter/mailstore/leap_mailstore.py +++ b/service/pixelated/adapter/mailstore/leap_mailstore.py @@ -121,6 +121,9 @@ class LeapMail(Mail): return result + def remove_duplicates(self, values): + return list(set(values)) + def _decoded_header_utf_8(self, header_value): if isinstance(header_value, list): return self.remove_duplicates([self._decoded_header_utf_8(v) for v in header_value]) @@ -143,47 +146,12 @@ class LeapMail(Mail): 'body': self._body, 'security_casing': self.security_casing, 'textPlainBody': self._body, - 'replying': self._replying_dict(), 'mailbox': self._mailbox_name.lower(), 'attachments': [attachment.as_dict() for attachment in self._attachments] } - def _replying_dict(self): - result = {'single': None, 'all': {'to-field': [], 'cc-field': []}} - - sender_mail = self._decoded_header_utf_8(self.headers.get('Reply-To', self.headers.get('From'))) - # Issue #215: Fix for existing mails without any from address. - if sender_mail is None: - sender_mail = InputMail.FROM_EMAIL_ADDRESS - - recipients = self._reply_recipient('To') - recipients = self._decoded_header_utf_8(recipients) - recipients.append(sender_mail) - recipients = self.remove_duplicates(recipients) - ccs = self._decoded_header_utf_8(self._reply_recipient('Cc')) - - result['single'] = sender_mail - result['all']['to-field'] = self._remove_me(recipients) if len(recipients) > 1 else recipients - result['all']['cc-field'] = self._remove_me(ccs) if len(ccs) > 1 else ccs - return result - - def _remove_me(self, recipients): - return [recipient for recipient in recipients if not self._parsed_mail_matches(recipient, InputMail.FROM_EMAIL_ADDRESS)] - - def remove_duplicates(self, recipients): - return list(set(recipients)) - def _reply_recipient(self, kind): - recipients = self.headers.get(kind, []) - if not recipients: - recipients = [] - - return recipients - - def _parsed_mail_matches(self, to_parse, expected): - if InputMail.FROM_EMAIL_ADDRESS is None: - return False - return parseaddr(to_parse)[1] == expected + return self.headers.get(kind, []) @staticmethod def from_dict(mail_dict): diff --git a/service/pixelated/adapter/model/mail.py b/service/pixelated/adapter/model/mail.py index dd2f4c0d..76df076e 100644 --- a/service/pixelated/adapter/model/mail.py +++ b/service/pixelated/adapter/model/mail.py @@ -141,8 +141,6 @@ class Mail(object): class InputMail(Mail): - FROM_EMAIL_ADDRESS = None - def __init__(self): self._raw_message = None self._fd = None @@ -193,12 +191,12 @@ class InputMail(Mail): }) @staticmethod - def from_dict(mail_dict): + def from_dict(mail_dict, from_address): input_mail = InputMail() input_mail.headers = {key.capitalize(): value for key, value in mail_dict.get('header', {}).items()} input_mail.headers['Date'] = date.mail_date_now() - input_mail.headers['From'] = InputMail.FROM_EMAIL_ADDRESS + input_mail.headers['From'] = from_address input_mail.body = mail_dict.get('body', '') input_mail.tags = set(mail_dict.get('tags', [])) diff --git a/service/pixelated/adapter/services/mail_service.py b/service/pixelated/adapter/services/mail_service.py index 75c0808e..cf47bfa6 100644 --- a/service/pixelated/adapter/services/mail_service.py +++ b/service/pixelated/adapter/services/mail_service.py @@ -96,7 +96,7 @@ class MailService(object): @defer.inlineCallbacks def send_mail(self, content_dict): - mail = InputMail.from_dict(content_dict) + mail = InputMail.from_dict(content_dict, self.account_email) draft_id = content_dict.get('ident') yield self.mail_sender.sendmail(mail) diff --git a/service/pixelated/config/services.py b/service/pixelated/config/services.py index 114609e0..048d04a4 100644 --- a/service/pixelated/config/services.py +++ b/service/pixelated/config/services.py @@ -22,8 +22,6 @@ class Services(object): @defer.inlineCallbacks def setup(self, leap_home, leap_session): - InputMail.FROM_EMAIL_ADDRESS = leap_session.account_email() - search_index_storage_key = self.setup_search_index_storage_key(leap_session.soledad) yield self.setup_search_engine( leap_home, diff --git a/service/pixelated/resources/mail_resource.py b/service/pixelated/resources/mail_resource.py index 14cb047a..3d151777 100644 --- a/service/pixelated/resources/mail_resource.py +++ b/service/pixelated/resources/mail_resource.py @@ -1,5 +1,6 @@ import json from pixelated.resources import respond_json, respond_json_deferred +from pixelated.support import replier from twisted.web.resource import Resource from twisted.web.server import NOT_DONE_YET from twisted.python.log import err @@ -36,8 +37,18 @@ class Mail(Resource): self._mail_service = mail_service def render_GET(self, request): + def populate_reply(mail): + mail_dict = mail.as_dict() + current_user = self._mail_service.account_email + sender = mail.headers.get('Reply-to', mail.headers.get('From')) + to = mail.headers.get('To', []) + ccs = mail.headers.get('Cc', []) + mail_dict['replying'] = replier.generate_recipients(sender, to, ccs, current_user) + return mail_dict + d = self._mail_service.mail(self._mail_id) - d.addCallback(lambda mail: respond_json_deferred(mail.as_dict(), request)) + d.addCallback(lambda mail: populate_reply(mail)) + d.addCallback(lambda mail_dict: respond_json_deferred(mail_dict, request)) return NOT_DONE_YET def render_DELETE(self, request): diff --git a/service/pixelated/resources/mails_resource.py b/service/pixelated/resources/mails_resource.py index 3a5b6286..a2f07093 100644 --- a/service/pixelated/resources/mails_resource.py +++ b/service/pixelated/resources/mails_resource.py @@ -198,7 +198,7 @@ class MailsResource(Resource): content_dict = json.loads(request.content.read()) with_attachment_content = yield self._fetch_attachment_contents(content_dict) - _mail = InputMail.from_dict(with_attachment_content) + _mail = InputMail.from_dict(with_attachment_content, from_address=self._mail_service.account_email) draft_id = content_dict.get('ident') pixelated_mail = yield self._draft_service.process_draft(draft_id, _mail) diff --git a/service/pixelated/support/replier.py b/service/pixelated/support/replier.py new file mode 100644 index 00000000..0bcb1a27 --- /dev/null +++ b/service/pixelated/support/replier.py @@ -0,0 +1,32 @@ +from email.utils import parseaddr + + +def generate_recipients(sender, to, ccs, current_user): + result = {'single': None, 'all': {'to-field': [], 'cc-field': []}} + + to.append(sender) + to = remove_duplicates(to) + ccs = remove_duplicates(ccs) + + result['single'] = swap_recipient_if_needed(sender, remove_address(to, current_user), current_user) + result['all']['to-field'] = remove_address(to, current_user) if len(to) > 1 else to + result['all']['cc-field'] = remove_address(ccs, current_user) if len(ccs) > 1 else ccs + return result + + +def remove_duplicates(recipients): + return list(set(recipients)) + + +def remove_address(recipients, current_user): + return [recipient for recipient in recipients if not parsed_mail_matches(recipient, current_user)] + + +def parsed_mail_matches(to_parse, expected): + return parseaddr(to_parse)[1] == expected + + +def swap_recipient_if_needed(sender, recipients, current_user): + if len(recipients) == 1 and parsed_mail_matches(sender, current_user): + return recipients[0] + return sender |