summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mail/changes/bug_3937_fix_ui_freeze1
-rw-r--r--mail/src/leap/mail/smtp/gateway.py80
2 files changed, 47 insertions, 34 deletions
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()