summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuben Pollan <meskio@sindominio.net>2016-04-07 19:22:31 +0200
committerRuben Pollan <meskio@sindominio.net>2016-04-14 20:05:02 +0200
commitdb3b1369ce12efea2c3d06d0671bfa655ef49571 (patch)
tree6d94e0648c9d22334a597b7d66559e1273cbed89 /src
parent8d45bc5b692801fc3df425d497a7210f84dae123 (diff)
[feature] Bounce stalled emails after a timeout.
* Resolves: #7998
Diffstat (limited to 'src')
-rw-r--r--src/leap/mx/mail_receiver.py34
1 files changed, 31 insertions, 3 deletions
diff --git a/src/leap/mx/mail_receiver.py b/src/leap/mx/mail_receiver.py
index 69079be..7c5a368 100644
--- a/src/leap/mx/mail_receiver.py
+++ b/src/leap/mx/mail_receiver.py
@@ -40,6 +40,7 @@ import signal
import json
import email.utils
+from datetime import datetime, timedelta
from email import message_from_string
from twisted.application.service import Service, IService
@@ -75,6 +76,11 @@ class MailReceiver(Service):
"""
RETRY_DIR_WATCH_DELAY = 60 * 5 # 5 minutes
+ """
+ Time delta to keep stalled emails
+ """
+ MAX_BOUNCE_DELTA = timedelta(days=5)
+
def __init__(self, users_cdb, directories, bounce_from,
bounce_subject):
"""
@@ -98,6 +104,7 @@ class MailReceiver(Service):
self._directories = directories
self._bounce_from = bounce_from
self._bounce_subject = bounce_subject
+ self._bounce_timestamp = {}
self._processing_skipped = False
def startService(self):
@@ -378,10 +385,31 @@ class MailReceiver(Service):
defer.returnValue(None)
log.msg("Encrypting message to %s's pubkey" % (uuid,))
- doc = yield self._encrypt_message(pubkey, mail_data)
+ try:
+ doc = yield self._encrypt_message(pubkey, mail_data)
+
+ yield self._export_message(uuid, doc)
+ yield self._remove(filepath)
+ except Exception as e:
+ yield self._bounce_with_timeout(filepath, msg, e)
+
+ @defer.inlineCallbacks
+ def _bounce_with_timeout(self, filepath, msg, error):
+ if filepath not in self._bounce_timestamp:
+ self._bounce_timestamp[filepath] = datetime.now()
+ log.msg("New stalled email {0!r}: {1!r}".format(filepath, error))
+ defer.returnValue(None)
- yield self._export_message(uuid, doc)
- yield self._remove(filepath)
+ current_delta = datetime.now() - self._bounce_timestamp[filepath]
+ if current_delta > self.MAX_BOUNCE_DELTA:
+ log.msg("Bouncing stalled email {0!r}: {1!r}"
+ .format(filepath, error))
+ bounce_reason = "There was a problem in the server and the " \
+ "email could not be delivered."
+ yield self._bounce_message(msg, filepath, bounce_reason)
+ else:
+ log.msg("Still stalled email {0!r} for the last {1}: {2!r}"
+ .format(filepath, str(current_delta), error))
@defer.inlineCallbacks
def _process_incoming_email(self, otherself, filepath, mask):