diff options
author | Ruben Pollan <meskio@sindominio.net> | 2016-04-07 19:22:31 +0200 |
---|---|---|
committer | Ruben Pollan <meskio@sindominio.net> | 2016-04-14 20:05:02 +0200 |
commit | db3b1369ce12efea2c3d06d0671bfa655ef49571 (patch) | |
tree | 6d94e0648c9d22334a597b7d66559e1273cbed89 | |
parent | 8d45bc5b692801fc3df425d497a7210f84dae123 (diff) |
[feature] Bounce stalled emails after a timeout.
* Resolves: #7998
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | changes/next-changelog.txt | 2 | ||||
-rw-r--r-- | src/leap/mx/mail_receiver.py | 34 |
3 files changed, 41 insertions, 3 deletions
@@ -33,6 +33,14 @@ $ python setup.py install $ twistd -ny pkg/mx.tac ~~~ +### Stalled emails + +In case of problems with couchdb and other unknown sources emails can get +stalled in the spool. There is a bouncing mechanism for long stalled emails, +after 5 days the email will get bounced. The timestamp of stalled emails is +hold in memory, restarting leap-mx will erase all timestamps and the stalled +timeout will be reset. + ## Hacking Please see the doc/DESIGN docs. diff --git a/changes/next-changelog.txt b/changes/next-changelog.txt index f34adbd..65ed19c 100644 --- a/changes/next-changelog.txt +++ b/changes/next-changelog.txt @@ -12,6 +12,8 @@ Features ~~~~~~~~ - `#4285 <https://leap.se/code/issues/4285>`_: Add postfix lookup against couchdb for client smtp fingerprint - `#5959 <https://leap.se/code/issues/5959>`_: Make alias resolver to return *uuid@deliver.local* +- `#7998 <https://leap.se/code/issues/7998>`_: Bounce stalled emails after a timeout. + - `#1234 <https://leap.se/code/issues/1234>`_: Description of the new feature corresponding with issue #1234. - New feature without related issue number. 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): |