diff options
-rw-r--r-- | changes/feature_3464-make-smtprelay-emit-signals | 1 | ||||
-rw-r--r-- | src/leap/mail/smtp/__init__.py | 7 | ||||
-rw-r--r-- | src/leap/mail/smtp/smtprelay.py | 42 |
3 files changed, 34 insertions, 16 deletions
diff --git a/changes/feature_3464-make-smtprelay-emit-signals b/changes/feature_3464-make-smtprelay-emit-signals new file mode 100644 index 0000000..987b0e3 --- /dev/null +++ b/changes/feature_3464-make-smtprelay-emit-signals @@ -0,0 +1 @@ + o Emit signals to notify UI for SMTP relay events. Closes #3464. 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 5f73be7..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 @@ -67,8 +68,8 @@ def assert_config_structure(config): { HOST_KEY: '<str>', PORT_KEY: <int>, - USERNAME_KEY: '<str>', - PASSWORD_KEY: '<str>', + CERT_KEY: '<str>', + KEY_KEY: '<str>', ENCRYPTED_ONLY_KEY: <bool>, } @@ -107,8 +108,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 +187,8 @@ class SMTPDelivery(object): { HOST_KEY: '<str>', PORT_KEY: <int>, - USERNAME_KEY: '<str>', - PASSWORD_KEY: '<str>', + CERT_KEY: '<str>', + KEY_KEY: '<str>', ENCRYPTED_ONLY_KEY: <bool>, } @type config: dict @@ -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) @@ -321,8 +325,8 @@ class EncryptedMessage(object): { HOST_KEY: '<str>', PORT_KEY: <int>, - USERNAME_KEY: '<str>', - PASSWORD_KEY: '<str>', + CERT_KEY: '<str>', + KEY_KEY: '<str>', ENCRYPTED_ONLY_KEY: <bool>, } @type config: dict @@ -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): """ @@ -416,17 +423,16 @@ 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), 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) |