From 83ccba79682e01922a071dc49d93a97353fb14e8 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 11 Nov 2013 13:43:30 -0200 Subject: remove print --- mail/src/leap/mail/imap/server.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mail/src/leap/mail/imap/server.py b/mail/src/leap/mail/imap/server.py index 7a9f8107..11f3ccf9 100644 --- a/mail/src/leap/mail/imap/server.py +++ b/mail/src/leap/mail/imap/server.py @@ -1153,7 +1153,6 @@ class SoledadMailbox(WithMsgFields): # the server itself is a listener to the mailbox. # so we can notify it (and should!) after chanes in flags # and number of messages. - print "emptying the listeners" map(lambda i: self.listeners.remove(i), self.listeners) def addListener(self, listener): -- cgit v1.2.3 From b54aae4b24a6f57e2f0d779dc13d097a89f42402 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 11 Nov 2013 13:44:54 -0200 Subject: add a fqdn as the local domain, always --- mail/src/leap/mail/smtp/gateway.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/mail/src/leap/mail/smtp/gateway.py b/mail/src/leap/mail/smtp/gateway.py index 06405b4e..6367c0df 100644 --- a/mail/src/leap/mail/smtp/gateway.py +++ b/mail/src/leap/mail/smtp/gateway.py @@ -71,6 +71,8 @@ generator.Generator = RFC3156CompliantGenerator # Helper utilities # +LOCAL_FQDN = "bitmask.local" + def validate_address(address): """ Validate C{address} as defined in RFC 2822. @@ -96,10 +98,18 @@ def validate_address(address): # SMTPFactory # +class SMTPHeloLocalhost(smtp.SMTP): + + def __init__(self, *args): + smtp.SMTP.__init__(self, *args) + self.host = LOCAL_FQDN + + class SMTPFactory(ServerFactory): """ Factory for an SMTP server with encrypted gatewaying capabilities. """ + domain = LOCAL_FQDN def __init__(self, userid, keymanager, host, port, cert, key, encrypted_only): @@ -152,7 +162,7 @@ class SMTPFactory(ServerFactory): @return: The protocol. @rtype: SMTPDelivery """ - smtpProtocol = smtp.SMTP(SMTPDelivery( + smtpProtocol = SMTPHeloLocalhost(SMTPDelivery( self._userid, self._km, self._host, self._port, self._cert, self._key, self._encrypted_only)) smtpProtocol.factory = self @@ -451,8 +461,10 @@ class EncryptedMessage(object): self._user.dest.addrstr, StringIO(msg), d, + heloFallback=True, requireAuthentication=False, requireTransportSecurity=True) + factory.domain = LOCAL_FQDN signal(proto.SMTP_SEND_MESSAGE_START, self._user.dest.addrstr) reactor.connectSSL( self._host, self._port, factory, -- cgit v1.2.3 From 6c25d79fa94aab81f3ee9e106e4ba0964797238d Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 11 Nov 2013 13:45:14 -0200 Subject: refactor callbacks so we properly catch remote errors --- mail/src/leap/mail/smtp/gateway.py | 49 ++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 13 deletions(-) diff --git a/mail/src/leap/mail/smtp/gateway.py b/mail/src/leap/mail/smtp/gateway.py index 6367c0df..7e9e4203 100644 --- a/mail/src/leap/mail/smtp/gateway.py +++ b/mail/src/leap/mail/smtp/gateway.py @@ -14,7 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - """ LEAP SMTP encrypted gateway. @@ -32,7 +31,6 @@ The following classes comprise the SMTP gateway service: """ - import re from StringIO import StringIO from email.Header import Header @@ -46,6 +44,7 @@ from twisted.mail import smtp from twisted.internet.protocol import ServerFactory from twisted.internet import reactor, ssl from twisted.internet import defer +from twisted.internet.threads import deferToThread from twisted.python import log from leap.common.check import leap_assert, leap_assert_type @@ -415,6 +414,15 @@ class EncryptedMessage(object): # unexpected loss of connection; don't save self.lines = [] + def sendQueued(self, r): + """ + Callback for the queued message. + + @param r: The result from the last previous callback in the chain. + @type r: anything + """ + log.msg(r) + def sendSuccess(self, r): """ Callback for a successful send. @@ -425,33 +433,51 @@ class EncryptedMessage(object): log.msg(r) signal(proto.SMTP_SEND_MESSAGE_SUCCESS, self._user.dest.addrstr) - def sendError(self, e): + def sendError(self, failure): """ Callback for an unsuccessfull send. :param e: The result from the last errback. :type e: anything """ - log.msg(e) - log.err() signal(proto.SMTP_SEND_MESSAGE_ERROR, self._user.dest.addrstr) + err = failure.value + log.err(err) + raise err def sendMessage(self): """ - Send the message. - - This method will prepare the message (headers and possibly encrypted - body) and send it using the ESMTPSenderFactory. - + Sends the message. @return: A deferred with callbacks for error and success of this message send. @rtype: twisted.internet.defer.Deferred """ + # FIXME this should not be blocking the main ui, since it returns + # a deferred and it has its own cb set. ???! + d = deferToThread(self._sendMessage) + d.addCallbacks(self._route_msg, self.sendError) + d.addCallbacks(self.sendQueued, self.sendError) + return d + + def _sendMessage(self): + """ + Send the message. + + This method will prepare the message (headers and possibly encrypted + body) + """ msg = self._msg.as_string(False) + return msg + def _route_msg(self, msg): + """ + Sends the msg using the ESMTPSenderFactory. + """ log.msg("Connecting to SMTP server %s:%s" % (self._host, self._port)) + # we construct a defer to pass to the ESMTPSenderFactory d = defer.Deferred() + d.addCallbacks(self.sendSuccess, self.sendError) # we don't pass an ssl context factory to the ESMTPSenderFactory # because ssl will be handled by reactor.connectSSL() below. factory = smtp.ESMTPSenderFactory( @@ -469,9 +495,6 @@ class EncryptedMessage(object): reactor.connectSSL( self._host, self._port, factory, contextFactory=SSLContextFactory(self._cert, self._key)) - d.addCallback(self.sendSuccess) - d.addErrback(self.sendError) - return d # # encryption methods -- cgit v1.2.3 From 444ee04cef46cfb115b70cc51a5b46bf0abd43b5 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 11 Nov 2013 13:46:09 -0200 Subject: add changes --- mail/changes/bug_4441_fix-fqdn | 1 + 1 file changed, 1 insertion(+) create mode 100644 mail/changes/bug_4441_fix-fqdn diff --git a/mail/changes/bug_4441_fix-fqdn b/mail/changes/bug_4441_fix-fqdn new file mode 100644 index 00000000..e758d65e --- /dev/null +++ b/mail/changes/bug_4441_fix-fqdn @@ -0,0 +1 @@ + o Identify ourselves with a fqdn, always. Closes: #4441 -- cgit v1.2.3 From bad92bb10d89bc39582aaca1b68ab9486c3f3053 Mon Sep 17 00:00:00 2001 From: Kali Kaneko Date: Mon, 11 Nov 2013 18:01:13 -0200 Subject: use deferToThread in the sendMail. Closes: #3937 --- mail/changes/bug_3937_fix_ui_freeze | 1 + mail/src/leap/mail/smtp/gateway.py | 80 +++++++++++++++++++++---------------- 2 files changed, 47 insertions(+), 34 deletions(-) create mode 100644 mail/changes/bug_3937_fix_ui_freeze diff --git a/mail/changes/bug_3937_fix_ui_freeze b/mail/changes/bug_3937_fix_ui_freeze new file mode 100644 index 00000000..b91938c5 --- /dev/null +++ b/mail/changes/bug_3937_fix_ui_freeze @@ -0,0 +1 @@ + o Uses deferToThread for sendMail. Closes #3937 diff --git a/mail/src/leap/mail/smtp/gateway.py b/mail/src/leap/mail/smtp/gateway.py index 7e9e4203..f6366afa 100644 --- a/mail/src/leap/mail/smtp/gateway.py +++ b/mail/src/leap/mail/smtp/gateway.py @@ -72,6 +72,7 @@ generator.Generator = RFC3156CompliantGenerator LOCAL_FQDN = "bitmask.local" + def validate_address(address): """ Validate C{address} as defined in RFC 2822. @@ -98,6 +99,13 @@ def validate_address(address): # class SMTPHeloLocalhost(smtp.SMTP): + """ + An SMTP class that ensures a proper FQDN + for localhost. + + This avoids a problem in which unproperly configured providers + would complain about the helo not being a fqdn. + """ def __init__(self, *args): smtp.SMTP.__init__(self, *args) @@ -388,21 +396,14 @@ class EncryptedMessage(object): Handle end of message. This method will encrypt and send the message. + + :returns: a deferred """ log.msg("Message data complete.") self.lines.append('') # add a trailing newline - try: - self._maybe_encrypt_and_sign() - return self.sendMessage() - except KeyNotFound: - return None - - def parseMessage(self): - """ - Separate message headers from body. - """ - parser = Parser() - return parser.parsestr('\r\n'.join(self.lines)) + d = deferToThread(self._maybe_encrypt_and_sign) + d.addCallbacks(self.sendMessage, self.skipNoKeyErrBack) + return d def connectionLost(self): """ @@ -414,12 +415,34 @@ class EncryptedMessage(object): # unexpected loss of connection; don't save self.lines = [] + # ends IMessage implementation + + def skipNoKeyErrBack(self, failure): + """ + Errback that ignores a KeyNotFound + + :param failure: the failure + :type Failure: Failure + """ + err = failure.value + if failure.check(KeyNotFound): + pass + else: + raise err + + def parseMessage(self): + """ + Separate message headers from body. + """ + parser = Parser() + return parser.parsestr('\r\n'.join(self.lines)) + def sendQueued(self, r): """ Callback for the queued message. - @param r: The result from the last previous callback in the chain. - @type r: anything + :param r: The result from the last previous callback in the chain. + :type r: anything """ log.msg(r) @@ -445,35 +468,24 @@ class EncryptedMessage(object): log.err(err) raise err - def sendMessage(self): + def sendMessage(self, *args): """ Sends the message. - @return: A deferred with callbacks for error and success of this - message send. - @rtype: twisted.internet.defer.Deferred - """ - # FIXME this should not be blocking the main ui, since it returns - # a deferred and it has its own cb set. ???! - d = deferToThread(self._sendMessage) - d.addCallbacks(self._route_msg, self.sendError) - d.addCallbacks(self.sendQueued, self.sendError) - return d - def _sendMessage(self): + :return: A deferred with callbacks for error and success of this + #message send. + :rtype: twisted.internet.defer.Deferred """ - Send the message. - - This method will prepare the message (headers and possibly encrypted - body) - """ - msg = self._msg.as_string(False) - return msg + d = deferToThread(self._route_msg) + d.addCallbacks(self.sendQueued, self.sendError) + return - def _route_msg(self, msg): + def _route_msg(self): """ Sends the msg using the ESMTPSenderFactory. """ log.msg("Connecting to SMTP server %s:%s" % (self._host, self._port)) + msg = self._msg.as_string(False) # we construct a defer to pass to the ESMTPSenderFactory d = defer.Deferred() -- cgit v1.2.3