summaryrefslogtreecommitdiff
path: root/src/leap/mail/imap/fetch.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/leap/mail/imap/fetch.py')
-rw-r--r--src/leap/mail/imap/fetch.py128
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")