summaryrefslogtreecommitdiff
path: root/src/leap/mail/imap/fetch.py
diff options
context:
space:
mode:
authorKali Kaneko <kali@leap.se>2013-04-15 16:22:39 +0900
committerKali Kaneko <kali@leap.se>2013-05-17 03:31:57 +0900
commit33289c373e4fdbb506b8486c73e5ff1a7837882f (patch)
treef648b86e8fab406cec81fb61d373d03944072f36 /src/leap/mail/imap/fetch.py
parent8fb5895c46282aa913d2cf3c31f3c526174b3f3b (diff)
Functional SoledadBackedAccount and LeapMailboxes
The imap service is launched from the tac file, and still needs some information to be provided in separate config files that stub much of the initialization parameters. working fetch and store methods. tested with offlineimap and thunderbird. several mailboxes might be broken.
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")