summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/pixelated/adapter/pixelated_mail.py190
-rw-r--r--service/pixelated/adapter/pixelated_mailbox.py18
-rw-r--r--service/pixelated/user_agent.py26
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)