[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [gettor/master] Check to see if email is from an autoresponder



commit 012ef1a4020c5d7b70f027a0184d32b440c7babb
Author: Cecylia Bocovich <cohosh@xxxxxxxxxxxxxx>
Date:   Mon May 25 11:06:57 2020 -0400

    Check to see if email is from an autoresponder
    
    This checks to see if an incoming request is from a known autoresponder.
    GetTor can get into infinite loops with itself or postmaster addresses
    (Bug #34286)
---
 gettor/parse/email.py          |  4 ++--
 gettor/utils/validate_email.py | 21 +++++++++++++++++++++
 tests/test_email_service.py    | 17 ++++++++++++++++-
 3 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/gettor/parse/email.py b/gettor/parse/email.py
index d37614d..41b34ce 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 0f18e3e..337849e 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 a41669f..47d7e5f 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@xxxxxxxxxxxxxx")
         request = ep.parse("From: MAILER-DAEMON@xxxxxxxxxxxxxx\n"
                 "Subject: Undelivered Mail Returned to Sender\r\n"
                 "To: gettor@xxxxxxxxxxxxxx\n osx en\n")
 
         self.assertEqual(request, {})
+        request = ep.parse("From: postmaster@xxxxxxxxxx\n"
+                "Subject: Undelivered Mail Returned to Sender\r\n"
+                "To: gettor@xxxxxxxxxxxxxx\n\n osx en\n")
+
+        self.assertEqual(request, {})
+        request = ep.parse("From: gettor@xxxxxxxxxxxxxx\n"
+                "Subject: links\r\n"
+                "To: gettor@xxxxxxxxxxxxxx\n\n osx en\n")
+
+        self.assertEqual(request, {})
+        request = ep.parse("From: gettor+en@xxxxxxxxxxxxxx\n"
+                "Subject: links\r\n"
+                "To: gettor@xxxxxxxxxxxxxx\n\n osx en\n")
+
+        self.assertEqual(request, {})
 
 if __name__ == "__main__":
     unittest.main()

_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits