diff options
Diffstat (limited to 'src/leap/mail/imap/fetch.py')
-rw-r--r-- | src/leap/mail/imap/fetch.py | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/leap/mail/imap/fetch.py b/src/leap/mail/imap/fetch.py new file mode 100644 index 0000000..adf5787 --- /dev/null +++ b/src/leap/mail/imap/fetch.py @@ -0,0 +1,128 @@ +import json +import os +#import hmac + +from xdg import BaseDirectory + +from twisted.python import log + +from leap.common.check import leap_assert +from leap.soledad import Soledad + +from leap.common.keymanager import openpgp + + +class LeapIncomingMail(object): + """ + Fetches mail from the incoming queue. + """ + def __init__(self, keymanager, user_uuid, soledad_pass, server_url, + server_pemfile, token, imap_account, + **kwargs): + """ + Initialize LeapIMAP. + + :param user: The user adress in the form C{user@provider}. + :type user: str + + :param soledad_pass: The password for the local database replica. + :type soledad_pass: str + + :param server_url: The URL of the remote server to sync against. + :type couch_url: str + + :param server_pemfile: The pemfile for the remote sync server TLS + handshake. + :type server_pemfile: str + + :param token: a session token valid for this user. + :type token: str + + :param imap_account: a SoledadBackedAccount instance to which + the incoming mail will be saved to + + :param **kwargs: Used to pass arguments to Soledad instance. Maybe + Soledad instantiation could be factored out from here, and maybe + we should have a standard for all client code. + """ + leap_assert(user_uuid, "need an user uuid to initialize") + + self._keymanager = keymanager + self._user_uuid = user_uuid + self._server_url = server_url + self._soledad_pass = soledad_pass + + base_config = BaseDirectory.xdg_config_home + secret_path = os.path.join( + base_config, "leap", "soledad", "%s.secret" % user_uuid) + soledad_path = os.path.join( + base_config, "leap", "soledad", "%s-incoming.u1db" % user_uuid) + + self.imapAccount = imap_account + self._soledad = Soledad( + user_uuid, + soledad_pass, + secret_path, + soledad_path, + server_url, + server_pemfile, + token, + bootstrap=True) + + self._pkey = self._keymanager.get_all_keys_in_local_db( + private=True).pop() + log.msg('fetcher got soledad instance') + + def fetch(self): + """ + Get new mail by syncing database, store it in the INBOX for the + user account, and remove from the incoming db. + """ + self._soledad.sync() + + #log.msg('getting all docs') + gen, doclist = self._soledad.get_all_docs() + #log.msg("there are %s docs" % (len(doclist),)) + + if doclist: + inbox = self.imapAccount.getMailbox('inbox') + + #import ipdb; ipdb.set_trace() + + key = self._pkey + for doc in doclist: + keys = doc.content.keys() + if '_enc_scheme' in keys and '_enc_json' in keys: + + # XXX should check for _enc_scheme == "pubkey" || "none" + # that is what incoming mail uses. + + encdata = doc.content['_enc_json'] + decrdata = openpgp.decrypt_asym( + encdata, key, + passphrase=self._soledad_pass) + if decrdata: + self.process_decrypted(doc, decrdata, inbox) + # XXX launch sync callback + + def process_decrypted(self, doc, data, inbox): + """ + Process a successfully decrypted message + """ + log.msg("processing message!") + msg = json.loads(data) + if not isinstance(msg, dict): + return False + if not msg.get('incoming', False): + return False + # ok, this is an incoming message + rawmsg = msg.get('content', None) + if not rawmsg: + return False + log.msg("we got raw message") + + # add to inbox and delete from soledad + inbox.addMessage(rawmsg, ("\\Recent",)) + log.msg("added msg") + self._soledad.delete_doc(doc) + log.msg("deleted doc") |