From 33289c373e4fdbb506b8486c73e5ff1a7837882f Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 15 Apr 2013 16:22:39 +0900 Subject: 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. --- src/leap/mail/imap/fetch.py | 128 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/leap/mail/imap/fetch.py (limited to 'src/leap/mail/imap/fetch.py') 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") -- cgit v1.2.3 From 01a0bc796e0e12c0c4d9afd02a2c4e7ade166d11 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 20 May 2013 23:10:07 +0900 Subject: cleanup and complete docs --- src/leap/mail/imap/fetch.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src/leap/mail/imap/fetch.py') diff --git a/src/leap/mail/imap/fetch.py b/src/leap/mail/imap/fetch.py index adf5787..bcd8901 100644 --- a/src/leap/mail/imap/fetch.py +++ b/src/leap/mail/imap/fetch.py @@ -66,8 +66,7 @@ class LeapIncomingMail(object): soledad_path, server_url, server_pemfile, - token, - bootstrap=True) + token) self._pkey = self._keymanager.get_all_keys_in_local_db( private=True).pop() @@ -109,7 +108,7 @@ class LeapIncomingMail(object): """ Process a successfully decrypted message """ - log.msg("processing message!") + log.msg("processing incoming message!") msg = json.loads(data) if not isinstance(msg, dict): return False @@ -119,10 +118,10 @@ class LeapIncomingMail(object): rawmsg = msg.get('content', None) if not rawmsg: return False - log.msg("we got raw message") + #log.msg("we got raw message") # add to inbox and delete from soledad inbox.addMessage(rawmsg, ("\\Recent",)) - log.msg("added msg") + doc_id = doc.doc_id self._soledad.delete_doc(doc) - log.msg("deleted doc") + log.msg("deleted doc %s from incoming" % doc_id) -- cgit v1.2.3 From ffedb3b8e32c062604cc2f178213c82d90843788 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Tue, 21 May 2013 05:53:07 +0900 Subject: use the same soledad instance for incoming and mailbox --- src/leap/mail/imap/fetch.py | 70 +++++++++++---------------------------------- 1 file changed, 16 insertions(+), 54 deletions(-) (limited to 'src/leap/mail/imap/fetch.py') diff --git a/src/leap/mail/imap/fetch.py b/src/leap/mail/imap/fetch.py index bcd8901..60ae387 100644 --- a/src/leap/mail/imap/fetch.py +++ b/src/leap/mail/imap/fetch.py @@ -1,12 +1,8 @@ import json -import os -#import hmac - -from xdg import BaseDirectory from twisted.python import log -from leap.common.check import leap_assert +from leap.common.check import leap_assert, leap_assert_type from leap.soledad import Soledad from leap.common.keymanager import openpgp @@ -16,61 +12,30 @@ 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): + def __init__(self, keymanager, soledad, imap_account): + """ 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 keymanager: a keymanager instance + :type keymanager: keymanager.KeyManager - :param imap_account: a SoledadBackedAccount instance to which - the incoming mail will be saved to + :param soledad: a soledad instance + :type soledad: Soledad - :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. + :param imap_account: the account to fetch periodically + :type imap_account: SoledadBackedAccount """ - 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) + leap_assert(keymanager, "need a keymanager to initialize") + leap_assert_type(soledad, Soledad) + self._keymanager = keymanager + self._soledad = soledad self.imapAccount = imap_account - self._soledad = Soledad( - user_uuid, - soledad_pass, - secret_path, - soledad_path, - server_url, - server_pemfile, - token) self._pkey = self._keymanager.get_all_keys_in_local_db( private=True).pop() - log.msg('fetcher got soledad instance') def fetch(self): """ @@ -78,16 +43,12 @@ class LeapIncomingMail(object): 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() @@ -99,10 +60,11 @@ class LeapIncomingMail(object): encdata = doc.content['_enc_json'] decrdata = openpgp.decrypt_asym( encdata, key, - passphrase=self._soledad_pass) + # XXX get from public method instead + passphrase=self._soledad._passphrase) if decrdata: self.process_decrypted(doc, decrdata, inbox) - # XXX launch sync callback + # XXX launch sync callback / defer def process_decrypted(self, doc, data, inbox): """ -- cgit v1.2.3