diff --git a/gettor/parse/email.py b/gettor/parse/email.py index d37614d807e9054774dc56e2237d1e77bfeb2739..41b34ce11e9c2bd8250cfdbdc007a42ea1fdd1b0 100644 --- a/gettor/parse/email.py +++ b/gettor/parse/email.py @@ -86,8 +86,8 @@ class EmailParser(object): ) # Add a check for auto-generated mail-daemon emails - if "mailer-daemon@" in norm_addr.lower(): - raise AddressError("Received mail from Mail Delivery System {}" + if validate_email.autoresponder(norm_addr): + raise AddressError("Received mail from a known autoresponder {}" .format(msg['From'])) return True diff --git a/gettor/utils/validate_email.py b/gettor/utils/validate_email.py index 0f18e3e9dc4f4598c0096a76af43e5a8638e323a..337849ea0537379a9d9b5d8381447d8c6c312e54 100644 --- a/gettor/utils/validate_email.py +++ b/gettor/utils/validate_email.py @@ -96,6 +96,13 @@ MX_DNS_CACHE = {} MX_CHECK_CACHE = {} +# List of known autoresponder email patterns +autoresponders = [ + r'mailer-daemon@.*', + r'postmaster@.*', + r'gettor.*@torproject.org' +] + def get_mx_ip(hostname): if hostname not in MX_DNS_CACHE: try: @@ -176,6 +183,20 @@ def validate_email(email, check_mx=False, verify=False, debug=False, smtp_timeou return None return True +def autoresponder(from_addr): + """ + We sometimes receive messages from autoresponders like Mail Deliver System + or postmaster due to bounced messages. This can send GetTor into an infinite + loop with the autoresponder (or itself). + + Returns true if the email address matches a known autoresponder pattern. + """ + for pattern in autoresponders: + if re.match(pattern, from_addr.lower()) is not None: + return True + + return False + if __name__ == "__main__": import time while True: diff --git a/tests/test_email_service.py b/tests/test_email_service.py index a41669f63b3b92c878de80a3a22b5b8207c1ff0c..47d7e5fb50392cb3da4e444c3fc65371c9102862 100644 --- a/tests/test_email_service.py +++ b/tests/test_email_service.py @@ -289,13 +289,28 @@ class EmailServiceTests(unittest.TestCase): ">\n") self.assertEqual(request["command"], "help") - def test_bounce(self): + def test_from_autoresponder(self): ep = conftests.EmailParser(self.settings, "gettor@torproject.org") request = ep.parse("From: MAILER-DAEMON@mx1.riseup.net\n" "Subject: Undelivered Mail Returned to Sender\r\n" "To: gettor@torproject.org\n osx en\n") self.assertEqual(request, {}) + request = ep.parse("From: postmaster@example.sk\n" + "Subject: Undelivered Mail Returned to Sender\r\n" + "To: gettor@torproject.org\n\n osx en\n") + + self.assertEqual(request, {}) + request = ep.parse("From: gettor@torproject.org\n" + "Subject: links\r\n" + "To: gettor@torproject.org\n\n osx en\n") + + self.assertEqual(request, {}) + request = ep.parse("From: gettor+en@torproject.org\n" + "Subject: links\r\n" + "To: gettor@torproject.org\n\n osx en\n") + + self.assertEqual(request, {}) if __name__ == "__main__": unittest.main()