diff options
Diffstat (limited to 'service')
-rw-r--r-- | service/pixelated/adapter/pixelated_mail.py | 190 | ||||
-rw-r--r-- | service/pixelated/adapter/pixelated_mailbox.py | 18 | ||||
-rw-r--r-- | service/pixelated/user_agent.py | 26 |
3 files changed, 178 insertions, 56 deletions
diff --git a/service/pixelated/adapter/pixelated_mail.py b/service/pixelated/adapter/pixelated_mail.py index 43b03834..00974972 100644 --- a/service/pixelated/adapter/pixelated_mail.py +++ b/service/pixelated/adapter/pixelated_mail.py @@ -25,48 +25,178 @@ from email.MIMEText import MIMEText class PixelatedMail: - def __init__(self, fdoc, hdoc, bdoc): - self.fdoc = fdoc - self.hdoc = hdoc - self.bdoc = bdoc + def __init__(self, tag_service=TagService.get_instance()): + self.tag_service = tag_service + self.body = None + self.headers = {} + self.status = [] + self.security_casing = {} + self.tags = [] + self.mailbox_name = None + self.uid = None - @property - def body(self): - return self.bdoc.content['raw'] + @staticmethod + def from_leap_mail(leap_mail): + mail = PixelatedMail() + mail.leap_mail = leap_mail + mail.mailbox_name = leap_mail._mbox + mail.uid = leap_mail.getUID() + mail.body = leap_mail.bdoc.content['raw'] + mail.headers = mail._extract_headers() + mail.headers['date'] = PixelatedMail._get_date(mail.headers) + mail.status = set(mail._extract_status()) + mail.security_casing = {} + mail.tags = mail._extract_tags() + return mail @property - def headers(self): - _headers = {} - for header in ['From', 'Date', 'Subject', 'Cc', 'Bcc']: - _headers[header.lower()] = self.hdoc.content['headers'].get(header) - return _headers + def is_recent(self): + return Status('recent') in self.status - @property - def status(self): - return Status.from_flags(self.fdoc.content.get('flags')) + def set_from(self, _from): + self.headers['from'] = [_from] - @property - def security_casing(self): - return {} + def get_to(self): + return self.headers['to'] - @property - def tags(self): - mailbox_tag = self.hdoc.content.get('mbox', '').lower() - tags = self.hdoc.content['headers'].get('x-tags', '[]') - _tags = tags if type(tags) is list else json.loads(tags) # this should go away since they should always be json'ed - _tags.append(mailbox_tag) - return set(_tags) + def get_cc(self): + return self.headers['cc'] - @property - def ident(self): - return self.fdoc.content.get('chash') + def get_bcc(self): + return self.headers['bcc'] + + def _extract_status(self): + return Status.from_flags(self.leap_mail.getFlags()) + + def _split_recipients(self, header_type, temporary_headers): + if(temporary_headers.get(header_type) is not None): + recipients = temporary_headers[header_type].split(',') + temporary_headers[header_type] = map(lambda x: x.lstrip(), recipients) + + def _extract_headers(self): + temporary_headers = {} + for header, value in self.leap_mail.hdoc.content['headers'].items(): + temporary_headers[header.lower()] = value + + map(lambda x: self._split_recipients(x, temporary_headers), ['to', 'bcc', 'cc']) + + return temporary_headers + + def _extract_tags(self): + tags = self.headers.get('x-tags', '[]') + if type(tags) is list: + return set(tags) + return set(json.loads(tags)) + + def mark_as_deleted(self): + # self.remove_all_tags() + # self.leap_mail.setFlags((Status.PixelatedStatus.DELETED,), 1) + pass + + def remove_all_tags(self): + self.update_tags(set([])) + + def update_tags(self, tags): + old_tags = self.tags + self.tags = tags + removed = old_tags.difference(tags) + added = tags.difference(old_tags) + self._persist_mail_tags(tags) + self.tag_service.notify_tags_updated(added, removed, self.ident) + return self.tags + + def mark_as_read(self): + # self.leap_mail.setFlags((Status.PixelatedStatus.SEEN,), 1) + # self.status = self._extract_status() + # return self + pass + + def mark_as_not_recent(self): + # self.leap_mail.setFlags((Status.PixelatedStatus.RECENT,), -1) + # self.status = self._extract_status() + # return self + pass + + def _persist_mail_tags(self, current_tags): + # hdoc = self.leap_mail.hdoc + # hdoc.content['headers']['X-Tags'] = json.dumps(list(current_tags)) + # self.leap_mail._soledad.put_doc(hdoc) + pass + + def has_tag(self, tag): + return tag in self.tags + + def raw_message(self): + mime = MIMEMultipart() + for key, value in self.leap_mail.hdoc.content['headers'].items(): + mime[key] = value + mime.attach(MIMEText(self.leap_mail.bdoc.content['raw'], 'plain')) + return mime.as_string() def as_dict(self): + statuses = [status.name for status in self.status] return { 'header': self.headers, 'ident': self.ident, 'tags': list(self.tags), - 'status': [str(stat) for stat in self.status], + 'status': statuses, 'security_casing': self.security_casing, 'body': self.body - }
\ No newline at end of file + } + + def to_mime_multipart(self): + mime_multipart = MIMEMultipart() + + for header in ['To', 'Cc', 'Bcc']: + if self.headers[header.lower()]: + mime_multipart[header] = ", ".join(self.headers[header.lower()]) + + if self.headers['subject']: + mime_multipart['Subject'] = self.headers['subject'] + + mime_multipart['Date'] = self.headers['date'] + mime_multipart.attach(MIMEText(self.body, 'plain')) + return mime_multipart + + def to_smtp_format(self): + mime_multipart = self.to_mime_multipart() + mime_multipart['From'] = PixelatedMail.from_email_address + return mime_multipart.as_string() + + @staticmethod + def from_dict(mail_dict): + return from_dict(mail_dict) + + @classmethod + def _get_date(cls, headers): + date = headers.get('date', None) + if not date: + date = headers['received'].split(";")[-1].strip() + return dateparser.parse(date).isoformat() + + @staticmethod + def from_soledad(fdoc, hdoc, bdoc): + mail = PixelatedMail() + mail.body = bdoc.content['raw'] + _headers = {} + for header in ['From', 'Date', 'Subject', 'Cc', 'Bcc']: + _headers[header.lower()] = hdoc.content['headers'].get(header) + mail.headers = _headers + mail.status = Status.from_flags(fdoc.content.get('flags')) + mail.security_casing = {} + tags = hdoc.content['headers'].get('x-tags', '[]') + _tags = set(tags) if type(tags) is list else set(json.loads(tags)) # this should go away since they should always be json'ed + mail.tags = _tags + mail.ident = fdoc.content.get('chash') + return mail + + +def from_dict(mail_dict): + mail = PixelatedMail() + mail.headers = mail_dict.get('header', {}) + mail.headers['date'] = pixelated.support.date.iso_now() + mail.body = mail_dict.get('body', '') + mail._ident = mail_dict.get('ident', None) + mail.tags = set(mail_dict.get('tags', [])) + mail.status = set(mail_dict.get('status', [])) + return mail diff --git a/service/pixelated/adapter/pixelated_mailbox.py b/service/pixelated/adapter/pixelated_mailbox.py index 4d558ea3..167092d8 100644 --- a/service/pixelated/adapter/pixelated_mailbox.py +++ b/service/pixelated/adapter/pixelated_mailbox.py @@ -37,19 +37,25 @@ class PixelatedMailbox: return self.leap_mailbox.mbox def add_mailbox_tag_if_not_there(self, pixelated_mail): - if not pixelated_mail.has_tag(self.mailbox_tag) and pixelated_mail.is_recent: + if not pixelated_mail.has_tag(self.mailbox_tag): pixelated_mail.update_tags({self.mailbox_tag}.union(pixelated_mail.tags)) self.tag_service.notify_tags_updated({self.mailbox_tag}, [], pixelated_mail.ident) pixelated_mail.mark_as_not_recent() def mails(self): - mails = self.leap_mailbox.messages or [] + soledad = self.leap_mailbox._soledad + + fdocs_chash = [(fdoc, fdoc.content['chash']) for fdoc in soledad.get_from_index('by-type-and-mbox', 'flags', self.leap_mailbox.mbox)] + fdocs_hdocs = [(f[0], soledad.get_from_index('by-type-and-contenthash', 'head', f[1])[0]) for f in fdocs_chash] + fdocs_hdocs_phash = [(f[0], f[1], f[1].content.get('body')) for f in fdocs_hdocs] + fdocs_hdocs_bdocs = [(f[0], f[1], soledad.get_from_index('by-type-and-payloadhash', 'cnt', f[2])[0]) for f in fdocs_hdocs_phash] + + mails = [PixelatedMail.from_soledad(*raw_mail) for raw_mail in fdocs_hdocs_bdocs] + result = [] for mail in mails: - mail._collection = mails - pixelated_mail = PixelatedMail.from_leap_mail(mail) - self.add_mailbox_tag_if_not_there(pixelated_mail) - result.append(pixelated_mail) + self.add_mailbox_tag_if_not_there(mail) + result.append(mail) return result def mails_by_tags(self, tags): diff --git a/service/pixelated/user_agent.py b/service/pixelated/user_agent.py index 4c257925..7adff10b 100644 --- a/service/pixelated/user_agent.py +++ b/service/pixelated/user_agent.py @@ -78,33 +78,21 @@ def update_draft(): @app.route('/mails') def mails(): - # query = search_query.compile(request.args.get("q")) if request.args.get("q") else {'tags': {}} - # - # mails = mail_service.mails(query) - # - # if "inbox" in query['tags']: - # mails = [mail for mail in mails if not mail.has_tag('trash')] - query = search_query.compile(request.args.get("q")) if request.args.get("q") else {'tags': {}} - fdocs_chash = [(fdoc, fdoc.content['chash']) for fdoc in soledad.get_from_index('by-type', 'flags')] - fdocs_hdocs = [(f[0], soledad.get_from_index('by-type-and-contenthash', 'head', f[1])[0]) for f in fdocs_chash] - fdocs_hdocs_phash = [(f[0], f[1], f[1].content.get('body')) for f in fdocs_hdocs] - fdocs_hdocs_bdocs = [(f[0], f[1], soledad.get_from_index('by-type-and-payloadhash', 'cnt', f[2])[0]) for f in fdocs_hdocs_phash] - - - all_mails = [PixelatedMail(*raw_mail) for raw_mail in fdocs_hdocs_bdocs] + mails = mail_service.mails(query) - filtered_mails = [_mail for _mail in all_mails if set(query['tags']).intersection(_mail.tags)] + if "inbox" in query['tags']: + mails = [mail for mail in mails if not mail.has_tag('trash')] response = { "stats": { - "total": len(filtered_mails), + "total": len(mails), "read": 0, "starred": 0, "replied": 0 }, - "mails": [pixelated_mail.as_dict() for pixelated_mail in filtered_mails] + "mails": [mail.as_dict() for mail in mails] } return respond_json(response) @@ -183,9 +171,7 @@ def start_user_agent(debug_enabled): pixelated_mail_sender = PixelatedMailSender(leap_session.account_email()) global mail_service - #mail_service = MailService(pixelated_mailboxes, pixelated_mail_sender) - global soledad - soledad = leap_session.soledad_session.soledad + mail_service = MailService(pixelated_mailboxes, pixelated_mail_sender) app.run(host=app.config['HOST'], debug=debug_enabled, port=app.config['PORT'], use_reloader=False) |