diff options
Diffstat (limited to 'src/leap/mail/imap/service/imap-server.tac')
-rw-r--r-- | src/leap/mail/imap/service/imap-server.tac | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/src/leap/mail/imap/service/imap-server.tac b/src/leap/mail/imap/service/imap-server.tac new file mode 100644 index 0000000..1a4661b --- /dev/null +++ b/src/leap/mail/imap/service/imap-server.tac @@ -0,0 +1,178 @@ +import ConfigParser +import os + +from xdg import BaseDirectory + +from twisted.application import internet, service +from twisted.internet.protocol import ServerFactory +from twisted.mail import imap4 +from twisted.python import log + +from leap.common.check import leap_assert, leap_assert_type +from leap.mail.imap.server import SoledadBackedAccount +from leap.mail.imap.fetch import LeapIncomingMail +from leap.soledad import Soledad + +# Some constants +# XXX Should be passed to initializer too. + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +IMAP_PORT = 9930 +# The port in which imap service will run + +INCOMING_CHECK_PERIOD = 10 +# The period between succesive checks of the incoming mail +# queue (in seconds) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + +class LeapIMAPServer(imap4.IMAP4Server): + """ + An IMAP4 Server with mailboxes backed by soledad + """ + def __init__(self, *args, **kwargs): + # pop extraneous arguments + soledad = kwargs.pop('soledad', None) + user = kwargs.pop('user', None) + leap_assert(soledad, "need a soledad instance") + leap_assert_type(soledad, Soledad) + leap_assert(user, "need a user in the initialization") + + # initialize imap server! + imap4.IMAP4Server.__init__(self, *args, **kwargs) + + # we should initialize the account here, + # but we move it to the factory so we can + # populate the test account properly (and only once + # per session) + + # theAccount = SoledadBackedAccount( + # user, soledad=soledad) + + # --------------------------------- + # XXX pre-populate acct for tests!! + # populate_test_account(theAccount) + # --------------------------------- + #self.theAccount = theAccount + + def lineReceived(self, line): + log.msg('rcv: %s' % line) + imap4.IMAP4Server.lineReceived(self, line) + + def authenticateLogin(self, username, password): + # all is allowed so far. use realm instead + return imap4.IAccount, self.theAccount, lambda: None + + +class IMAPAuthRealm(object): + """ + Dummy authentication realm. Do not use in production! + """ + theAccount = None + + def requestAvatar(self, avatarId, mind, *interfaces): + return imap4.IAccount, self.theAccount, lambda: None + + +class LeapIMAPFactory(ServerFactory): + """ + Factory for a IMAP4 server with soledad remote sync and gpg-decryption + capabilities. + """ + + def __init__(self, user, soledad): + self._user = user + self._soledad = soledad + + theAccount = SoledadBackedAccount( + user, soledad=soledad) + self.theAccount = theAccount + + def buildProtocol(self, addr): + "Return a protocol suitable for the job." + imapProtocol = LeapIMAPServer( + user=self._user, + soledad=self._soledad) + imapProtocol.theAccount = self.theAccount + imapProtocol.factory = self + return imapProtocol + + +def initialize_soledad_mailbox(user_uuid, soledad_pass, server_url, + server_pemfile, token): + """ + Initializes soledad by hand + + :param user_uuid: + :param soledad_pass: + :param server_url: + :param server_pemfile: + :param token: + + :rtype: Soledad instance + """ + + 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-mailbox.db" % user_uuid) + + _soledad = Soledad( + user_uuid, + soledad_pass, + secret_path, + soledad_path, + server_url, + server_pemfile, + token) + + return _soledad + + +####################################################################### +# XXX STUBBED! We need to get this in the instantiation from the client + +config = ConfigParser.ConfigParser() +config.read([os.path.expanduser('~/.config/leap/mail/mail.conf')]) + +userID = config.get('mail', 'address') +privkey = open(os.path.expanduser('~/.config/leap/mail/privkey')).read() +nickserver_url = "" + +d = {} + +for key in ('uid', 'passphrase', 'server', 'pemfile', 'token'): + d[key] = config.get('mail', key) + +soledad = initialize_soledad_mailbox( + d['uid'], + d['passphrase'], + d['server'], + d['pemfile'], + d['token']) + +# import the private key ---- should sync it from remote! +from leap.common.keymanager.openpgp import OpenPGPScheme +opgp = OpenPGPScheme(soledad) +opgp.put_ascii_key(privkey) + +from leap.common.keymanager import KeyManager +keym = KeyManager(userID, nickserver_url, soledad, d['token']) + + +factory = LeapIMAPFactory(userID, soledad) + +application = service.Application("LEAP IMAP4 Local Service") +imapService = internet.TCPServer(IMAP_PORT, factory) +imapService.setServiceParent(application) + +fetcher = LeapIncomingMail( + keym, + soledad, + factory.theAccount) + + +internet.TimerService( + INCOMING_CHECK_PERIOD, + fetcher.fetch).setServiceParent(application) |