From f26d4c395f56ae07d7341fd48f8e5b244db8328c Mon Sep 17 00:00:00 2001 From: drebs Date: Tue, 13 Aug 2013 22:55:46 -0300 Subject: Fix docstrings and comments. --- src/leap/mail/smtp/smtprelay.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/leap') diff --git a/src/leap/mail/smtp/smtprelay.py b/src/leap/mail/smtp/smtprelay.py index 5f73be7..0c29029 100644 --- a/src/leap/mail/smtp/smtprelay.py +++ b/src/leap/mail/smtp/smtprelay.py @@ -67,8 +67,8 @@ def assert_config_structure(config): { HOST_KEY: '', PORT_KEY: , - USERNAME_KEY: '', - PASSWORD_KEY: '', + CERT_KEY: '', + KEY_KEY: '', ENCRYPTED_ONLY_KEY: , } @@ -107,8 +107,8 @@ def validate_address(address): @raise smtp.SMTPBadRcpt: Raised if C{address} is invalid. """ leap_assert_type(address, str) - # the following parses the address as described in RFC 2822 and - # returns ('', '') if the parse fails. + # in the following, the address is parsed as described in RFC 2822 and + # ('', '') is returned if the parse fails. _, address = parseaddr(address) if address == '': raise smtp.SMTPBadRcpt(address) @@ -186,8 +186,8 @@ class SMTPDelivery(object): { HOST_KEY: '', PORT_KEY: , - USERNAME_KEY: '', - PASSWORD_KEY: '', + CERT_KEY: '', + KEY_KEY: '', ENCRYPTED_ONLY_KEY: , } @type config: dict @@ -321,8 +321,8 @@ class EncryptedMessage(object): { HOST_KEY: '', PORT_KEY: , - USERNAME_KEY: '', - PASSWORD_KEY: '', + CERT_KEY: '', + KEY_KEY: '', ENCRYPTED_ONLY_KEY: , } @type config: dict @@ -416,8 +416,8 @@ class EncryptedMessage(object): d = defer.Deferred() factory = smtp.ESMTPSenderFactory( - "", - "", + "", # username is blank because server does not use auth. + "", # password is blank because server does not use auth. self._fromAddress.addrstr, self._user.dest.addrstr, StringIO(msg), -- cgit v1.2.3 From c4aadb757e1434ae955e0de8ed024dca6aa4869d Mon Sep 17 00:00:00 2001 From: drebs Date: Wed, 14 Aug 2013 17:24:57 -0300 Subject: Make SMTP Relay emit signals. --- src/leap/mail/smtp/__init__.py | 7 ++++++- src/leap/mail/smtp/smtprelay.py | 22 +++++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'src/leap') diff --git a/src/leap/mail/smtp/__init__.py b/src/leap/mail/smtp/__init__.py index 3b4d9d6..1139afa 100644 --- a/src/leap/mail/smtp/__init__.py +++ b/src/leap/mail/smtp/__init__.py @@ -22,6 +22,7 @@ SMTP relay helper function. from twisted.internet import reactor +from leap.common.events import proto, signal from leap.mail.smtp.smtprelay import SMTPFactory @@ -70,4 +71,8 @@ def setup_smtp_relay(port, keymanager, smtp_host, smtp_port, # configure the use of this service with twistd factory = SMTPFactory(keymanager, config) - reactor.listenTCP(port, factory) + try: + reactor.listenTCP(port, factory) + signal(proto.SMTP_SERVICE_STARTED, str(smtp_port)) + except CannotListenError: + signal(proto.SMTP_SERVICE_FAILED_TO_START, str(smtp_port)) diff --git a/src/leap/mail/smtp/smtprelay.py b/src/leap/mail/smtp/smtprelay.py index 0c29029..96eaa31 100644 --- a/src/leap/mail/smtp/smtprelay.py +++ b/src/leap/mail/smtp/smtprelay.py @@ -33,6 +33,7 @@ from email.parser import Parser from leap.common.check import leap_assert, leap_assert_type +from leap.common.events import proto, signal from leap.keymanager import KeyManager from leap.keymanager.openpgp import OpenPGPKey from leap.keymanager.errors import KeyNotFound @@ -250,13 +251,16 @@ class SMTPDelivery(object): try: address = validate_address(user.dest.addrstr) pubkey = self._km.get_key(address, OpenPGPKey) - log.msg("Accepting mail for %s..." % user.dest) + log.msg("Accepting mail for %s..." % user.dest.addrstr) + signal(proto.SMTP_RECIPIENT_ACCEPTED_ENCRYPTED, user.dest.addrstr) except KeyNotFound: # if key was not found, check config to see if will send anyway. if self._config[ENCRYPTED_ONLY_KEY]: + signal(proto.SMTP_RECIPIENT_REJECTED, user.dest.addrstr) raise smtp.SMTPBadRcpt(user.dest.addrstr) log.msg("Warning: will send an unencrypted message (because " "encrypted_only' is set to False).") + signal(proto.SMTP_RECIPIENT_ACCEPTED_UNENCRYPTED, user.dest.addrstr) return lambda: EncryptedMessage( self._origin, user, self._km, self._config) @@ -376,6 +380,7 @@ class EncryptedMessage(object): """ log.msg("Connection lost unexpectedly!") log.err() + signal(proto.SMTP_CONNECTION_LOST, self._user.dest.addrstr) # unexpected loss of connection; don't save self.lines = [] @@ -387,6 +392,7 @@ class EncryptedMessage(object): @type r: anything """ log.msg(r) + signal(proto.SMTP_SEND_MESSAGE_SUCCESS, self._user.dest.addrstr) def sendError(self, e): """ @@ -397,6 +403,7 @@ class EncryptedMessage(object): """ log.msg(e) log.err() + signal(proto.SMTP_SEND_MESSAGE_ERROR, self._user.dest.addrstr) def sendMessage(self): """ @@ -424,9 +431,8 @@ class EncryptedMessage(object): d, contextFactory=CtxFactory(self._config[CERT_KEY], self._config[KEY_KEY]), - requireAuthentication=False, - ) - + requireAuthentication=False) + signal(proto.SMTP_SEND_MESSAGE_START, self._user.dest.addrstr) reactor.connectTCP( self._config[HOST_KEY], self._config[PORT_KEY], @@ -496,10 +502,16 @@ class EncryptedMessage(object): # try to get the recipient pubkey pubkey = self._km.get_key(to_address, OpenPGPKey) log.msg("Will encrypt the message to %s." % pubkey.fingerprint) + signal(proto.SMTP_START_ENCRYPT_AND_SIGN, + "%s,%s" % (self._fromAddress.addrstr, to_address)) self._encrypt_and_sign_payload_rec(self._message, pubkey, signkey) + signal(proto.SMTP_END_ENCRYPT_AND_SIGN, + "%s,%s" % (self._fromAddress.addrstr, to_address)) except KeyNotFound: # at this point we _can_ send unencrypted mail, because if the # configuration said the opposite the address would have been # rejected in SMTPDelivery.validateTo(). - self._sign_payload_rec(self._message, signkey) log.msg('Will send unencrypted message to %s.' % to_address) + signal(proto.SMTP_START_SIGN, self._fromAddress.addrstr) + self._sign_payload_rec(self._message, signkey) + signal(proto.SMTP_END_SIGN, self._fromAddress.addrstr) -- cgit v1.2.3 From fd48fff2676cb063663532f240197e9626d64363 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Fri, 16 Aug 2013 18:35:21 +0200 Subject: add imap events --- src/leap/mail/imap/fetch.py | 60 +++++++++++++++++++++++++++++++++----- src/leap/mail/imap/service/imap.py | 34 ++++++++++++++------- 2 files changed, 75 insertions(+), 19 deletions(-) (limited to 'src/leap') diff --git a/src/leap/mail/imap/fetch.py b/src/leap/mail/imap/fetch.py index 9b76592..267af38 100644 --- a/src/leap/mail/imap/fetch.py +++ b/src/leap/mail/imap/fetch.py @@ -1,15 +1,43 @@ +# -*- coding: utf-8 -*- +# fetch.py +# Copyright (C) 2013 LEAP +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +""" +Incoming mail fetcher. +""" import logging import json import ssl +import time from twisted.python import log from twisted.internet import defer from twisted.internet.task import LoopingCall from twisted.internet.threads import deferToThread +from leap.common import events as leap_events from leap.common.check import leap_assert, leap_assert_type from leap.soledad import Soledad +from leap.common.events.events_pb2 import IMAP_FETCHED_INCOMING +from leap.common.events.events_pb2 import IMAP_MSG_PROCESSING +from leap.common.events.events_pb2 import IMAP_MSG_DECRYPTED +from leap.common.events.events_pb2 import IMAP_MSG_SAVED_LOCALLY +from leap.common.events.events_pb2 import IMAP_MSG_DELETED_INCOMING + + logger = logging.getLogger(__name__) @@ -100,8 +128,12 @@ class LeapIncomingMail(object): try: self._soledad.sync() + fetched_ts = time.mktime(time.gmtime()) doclist = self._soledad.get_from_index("just-mail", "*") - log.msg("there are %s mails" % (len(doclist),)) + num_mails = len(doclist) + log.msg("there are %s mails" % (num_mails,)) + leap_events.signal( + IMAP_FETCHED_INCOMING, str(num_mails), str(fetched_ts)) return doclist except ssl.SSLError as exc: logger.warning('SSL Error while syncing soledad: %r' % (exc,)) @@ -117,8 +149,12 @@ class LeapIncomingMail(object): if not doclist: logger.debug("no docs found") return - for doc in doclist: - logger.debug("processing doc: %s" % doc) + num_mails = len(doclist) + for index, doc in enumerate(doclist): + logger.debug("processing doc %d of %d: %s" % ( + index, num_mails, doc)) + leap_events.signal( + IMAP_MSG_PROCESSING, str(index), str(num_mails)) keys = doc.content.keys() if self.ENC_SCHEME_KEY in keys and self.ENC_JSON_KEY in keys: @@ -133,11 +169,17 @@ class LeapIncomingMail(object): def _decrypt_msg(self, doc, encdata): log.msg('decrypting msg') key = self._pkey - decrdata = (self._keymanager.decrypt( - encdata, key, - # XXX get from public method instead - passphrase=self._soledad._passphrase)) - + try: + decrdata = (self._keymanager.decrypt( + encdata, key, + # XXX get from public method instead + passphrase=self._soledad._passphrase)) + ok = True + except Exception as exc: + logger.warning("Error while decrypting msg: %r" % (exc,)) + decrdata = "" + ok = False + leap_events.signal(IMAP_MSG_DECRYPTED, ok) # XXX TODO: defer this properly return self._process_decrypted(doc, decrdata) @@ -183,8 +225,10 @@ class LeapIncomingMail(object): rawmsg = rawmsg.replace(pgp_message, decrdata) # add to inbox and delete from soledad self._inbox.addMessage(rawmsg, (self.RECENT_FLAG,)) + leap_events.signal(IMAP_MSG_SAVED_LOCALLY) doc_id = doc.doc_id self._soledad.delete_doc(doc) log.msg("deleted doc %s from incoming" % doc_id) + leap_events.signal(IMAP_MSG_DELETED_INCOMING) except Exception as e: logger.error("Problem processing incoming mail: %r" % (e,)) diff --git a/src/leap/mail/imap/service/imap.py b/src/leap/mail/imap/service/imap.py index 1a8c15c..380324c 100644 --- a/src/leap/mail/imap/service/imap.py +++ b/src/leap/mail/imap/service/imap.py @@ -27,6 +27,7 @@ from twisted.internet.protocol import ServerFactory from twisted.mail import imap4 from twisted.python import log +from leap.common import events as leap_events from leap.common.check import leap_assert, leap_assert_type from leap.keymanager import KeyManager from leap.mail.imap.server import SoledadBackedAccount @@ -42,6 +43,10 @@ INCOMING_CHECK_PERIOD = 5 # The period between succesive checks of the incoming mail # queue (in seconds) +from leap.common.events.events_pb2 import IMAP_SERVICE_STARTED +from leap.common.events.events_pb2 import IMAP_SERVICE_FAILED_TO_START +from leap.common.events.events_pb2 import IMAP_CLIENT_LOGIN + class LeapIMAPServer(imap4.IMAP4Server): """ @@ -84,6 +89,7 @@ class LeapIMAPServer(imap4.IMAP4Server): def authenticateLogin(self, username, password): # all is allowed so far. use realm instead + leap_events.signal(IMAP_CLIENT_LOGIN, True) return imap4.IAccount, self.theAccount, lambda: None @@ -150,15 +156,21 @@ def run_service(*args, **kwargs): factory = LeapIMAPFactory(uuid, soledad) from twisted.internet import reactor - reactor.listenTCP(port, factory) - - fetcher = LeapIncomingMail( - keymanager, - soledad, - factory.theAccount, - check_period) - - fetcher.start_loop() - logger.debug("IMAP4 Server is RUNNING in port %s" % (port,)) - return fetcher + try: + reactor.listenTCP(port, factory) + fetcher = LeapIncomingMail( + keymanager, + soledad, + factory.theAccount, + check_period) + except Exception as exc: + # XXX cannot listen? + logger.error("Error launching IMAP service: %r" % (exc,)) + leap_events.signal(IMAP_SERVICE_FAILED_TO_START, str(port)) + return + else: + fetcher.start_loop() + logger.debug("IMAP4 Server is RUNNING in port %s" % (port,)) + leap_events.signal(IMAP_SERVICE_STARTED, str(port)) + return fetcher -- cgit v1.2.3