diff options
Diffstat (limited to 'src/leap/mail/smtp')
-rw-r--r-- | src/leap/mail/smtp/__init__.py | 2 | ||||
-rw-r--r-- | src/leap/mail/smtp/gateway.py | 46 | ||||
-rw-r--r-- | src/leap/mail/smtp/tests/test_gateway.py | 25 |
3 files changed, 45 insertions, 28 deletions
diff --git a/src/leap/mail/smtp/__init__.py b/src/leap/mail/smtp/__init__.py index 72b26ed..24402b4 100644 --- a/src/leap/mail/smtp/__init__.py +++ b/src/leap/mail/smtp/__init__.py @@ -22,7 +22,7 @@ import logging from twisted.internet import reactor from twisted.internet.error import CannotListenError -from leap.mail.service import OutgoingMail +from leap.mail.outgoing.service import OutgoingMail logger = logging.getLogger(__name__) diff --git a/src/leap/mail/smtp/gateway.py b/src/leap/mail/smtp/gateway.py index b022091..1a187cf 100644 --- a/src/leap/mail/smtp/gateway.py +++ b/src/leap/mail/smtp/gateway.py @@ -48,7 +48,6 @@ from leap.mail.smtp.rfc3156 import ( RFC3156CompliantGenerator, ) -from leap.mail.service import OutgoingMail # replace email generator with a RFC 3156 compliant one. from email import generator @@ -94,7 +93,7 @@ class SMTPFactory(ServerFactory): mail or not. :type encrypted_only: bool :param outgoing_mail: The outgoing mail to send the message - :type outgoing_mail: leap.mail.service.OutgoingMail + :type outgoing_mail: leap.mail.outgoing.service.OutgoingMail """ leap_assert_type(encrypted_only, bool) @@ -142,7 +141,7 @@ class SMTPDelivery(object): mail or not. :type encrypted_only: bool :param outgoing_mail: The outgoing mail to send the message - :type outgoing_mail: leap.mail.service.OutgoingMail + :type outgoing_mail: leap.mail.outgoing.service.OutgoingMail """ self._userid = userid self._outgoing_mail = outgoing_mail @@ -197,22 +196,31 @@ class SMTPDelivery(object): accepted. """ # try to find recipient's public key - try: - address = validate_address(user.dest.addrstr) - # verify if recipient key is available in keyring - self._km.get_key(address, OpenPGPKey) # might raise KeyNotFound + address = validate_address(user.dest.addrstr) + + # verify if recipient key is available in keyring + def found(_): 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._encrypted_only: - 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(user, self._outgoing_mail) + + def not_found(failure): + if failure.check(KeyNotFound): + # if key was not found, check config to see if will send anyway + if self._encrypted_only: + 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) + else: + return failure + + d = self._km.get_key(address, OpenPGPKey) # might raise KeyNotFound + d.addCallbacks(found, not_found) + d.addCallback(lambda _: EncryptedMessage(user, self._outgoing_mail)) + return d def validateFrom(self, helo, origin): """ @@ -258,7 +266,7 @@ class EncryptedMessage(object): :param user: The recipient of this message. :type user: twisted.mail.smtp.User :param outgoing_mail: The outgoing mail to send the message - :type outgoing_mail: leap.mail.service.OutgoingMail + :type outgoing_mail: leap.mail.outgoing.service.OutgoingMail """ # assert params leap_assert_type(user, smtp.User) @@ -298,4 +306,6 @@ class EncryptedMessage(object): log.err() signal(proto.SMTP_CONNECTION_LOST, self._user.dest.addrstr) # unexpected loss of connection; don't save + + self._lines = [] diff --git a/src/leap/mail/smtp/tests/test_gateway.py b/src/leap/mail/smtp/tests/test_gateway.py index aeace4a..8cbff8f 100644 --- a/src/leap/mail/smtp/tests/test_gateway.py +++ b/src/leap/mail/smtp/tests/test_gateway.py @@ -23,6 +23,7 @@ SMTP gateway tests. import re from datetime import datetime +from twisted.internet.defer import inlineCallbacks, fail from twisted.test import proto_helpers from mock import Mock @@ -34,7 +35,7 @@ from leap.mail.tests import ( ADDRESS, ADDRESS_2, ) -from leap.keymanager import openpgp +from leap.keymanager import openpgp, errors # some regexps @@ -87,7 +88,8 @@ class TestSmtpGateway(TestCaseWithKeyManager): proto = SMTPFactory( u'anotheruser@leap.se', self._km, - self._config['encrypted_only'], outgoing_mail=Mock()).buildProtocol(('127.0.0.1', 0)) + self._config['encrypted_only'], + outgoing_mail=Mock()).buildProtocol(('127.0.0.1', 0)) # snip... transport = proto_helpers.StringTransport() proto.makeConnection(transport) @@ -98,23 +100,26 @@ class TestSmtpGateway(TestCaseWithKeyManager): 'Did not get expected answer from gateway.') proto.setTimeout(None) + @inlineCallbacks def test_missing_key_rejects_address(self): """ Test if server rejects to send unencrypted when 'encrypted_only' is True. """ # remove key from key manager - pubkey = self._km.get_key(ADDRESS, openpgp.OpenPGPKey) + pubkey = yield self._km.get_key(ADDRESS, openpgp.OpenPGPKey) pgp = openpgp.OpenPGPScheme( self._soledad, gpgbinary=self.GPG_BINARY_PATH) - pgp.delete_key(pubkey) + yield pgp.delete_key(pubkey) # mock the key fetching - self._km.fetch_keys_from_server = Mock(return_value=[]) + self._km._fetch_keys_from_server = Mock( + return_value=fail(errors.KeyNotFound())) # prepare the SMTP factory proto = SMTPFactory( u'anotheruser@leap.se', self._km, - self._config['encrypted_only'], outgoing_mail=Mock()).buildProtocol(('127.0.0.1', 0)) + self._config['encrypted_only'], + outgoing_mail=Mock()).buildProtocol(('127.0.0.1', 0)) transport = proto_helpers.StringTransport() proto.makeConnection(transport) proto.lineReceived(self.EMAIL_DATA[0] + '\r\n') @@ -127,18 +132,20 @@ class TestSmtpGateway(TestCaseWithKeyManager): lines[-1], 'Address should have been rejecetd with appropriate message.') + @inlineCallbacks def test_missing_key_accepts_address(self): """ Test if server accepts to send unencrypted when 'encrypted_only' is False. """ # remove key from key manager - pubkey = self._km.get_key(ADDRESS, openpgp.OpenPGPKey) + pubkey = yield self._km.get_key(ADDRESS, openpgp.OpenPGPKey) pgp = openpgp.OpenPGPScheme( self._soledad, gpgbinary=self.GPG_BINARY_PATH) - pgp.delete_key(pubkey) + yield pgp.delete_key(pubkey) # mock the key fetching - self._km.fetch_keys_from_server = Mock(return_value=[]) + self._km._fetch_keys_from_server = Mock( + return_value=fail(errors.KeyNotFound())) # prepare the SMTP factory with encrypted only equal to false proto = SMTPFactory( u'anotheruser@leap.se', |