From 80f0e428065f84292f20954845500028a77a96e0 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 --- src/leap/mail/smtp/gateway.py | 49 +++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 13 deletions(-) (limited to 'src/leap') diff --git a/src/leap/mail/smtp/gateway.py b/src/leap/mail/smtp/gateway.py index 6367c0d..7e9e420 100644 --- a/src/leap/mail/smtp/gateway.py +++ b/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