]> gitweb.pimeys.fr Git - scripts-20-100.git/commitdiff
[mailman] Méta-script pour parser les mails et batch-exterminer
authorVincent Le Gallic <legallic@crans.org>
Fri, 4 Oct 2013 23:38:32 +0000 (01:38 +0200)
committerVincent Le Gallic <legallic@crans.org>
Fri, 4 Oct 2013 23:38:32 +0000 (01:38 +0200)
mailman_bad_guys.py
mailman_search_and_destroy.py [new file with mode: 0755]

index eba0821a2a0ce3e83f16608d79d39c74907025a7..3b817ee9a8eea5cfef66f792c0e88500ec0f5adb 100755 (executable)
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 # -*- coding:utf-8 -*-
 
+## TODO : Supprimer aussi les modérateurs/administrateurs
 """Pour trouver dans quelle(s) ML(s) est quelqu'un et l'en virer.
    
    À exécuter sur redisdead.
@@ -54,8 +55,8 @@ def exterminate(mail, ml):
     l.Save()
     l.Unlock()
 
-if __name__ == "__main__":
-    bad_guy = sys.argv[1].decode("utf-8").lower()
+def exterminate_this_guy(bad_guy):
+    """Trouve les MLs auxquelles est abonné ``bad_guy`` et l'en supprime en demandant confirmation."""
     mls = get_mls_from_mail(bad_guy)
     mls.sort()
     if mls:
@@ -66,3 +67,6 @@ if __name__ == "__main__":
                 exterminate(bad_guy, n)
     else:
         print("No mailing list found")
+
+if __name__ == "__main__":
+    bad_guy = sys.argv[1].decode("utf-8").lower()
diff --git a/mailman_search_and_destroy.py b/mailman_search_and_destroy.py
new file mode 100755 (executable)
index 0000000..0c6b82b
--- /dev/null
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+# -*- encoding: utf-8 -*-
+
+## TODO : Les alias (matcher Original-recipient ET Final-recipient ?)
+
+""" Pour récupérer les adresses mails des badguys à virer des MLs
+    (On considère que les mails son non lus)
+    On appelle ensuite mailman_bad_guys dessus """
+
+import os
+import re
+
+#import mailman_bad_guys
+
+#: Regexp permettant de vérifier que ce fichier est bien un mail d'erreur
+delivery_pattern = ur'Content-Type: multipart/report; report-type=delivery-status;'
+delivery_regex = re.compile(delivery_pattern)
+
+#: Regexp qui matche très exactement une adresse mail
+#: (oui, bon, c'est pas très RFC-compliant)
+justmail_pattern = ur"[^\s\n]+@[^\s\n]+"
+
+#: Regexp permettant de trouver la ligne contenant le mail invalide et un peu de contexte
+find_context_pattern = ur"(?P<context>Final-Recipient: rfc822; ?(?P<mail>%s)(?:.*\n){5})" % (justmail_pattern,)
+find_context_regex = re.compile(find_context_pattern)
+
+#: Dossier contenant les mails d'erreur de mailman
+mailman_problems_dir = os.path.expanduser(u"~/Mail/.Cr@ns.Problems.4-Human-made.Mailman/cur/")
+
+def list_files(where=mailman_problems_dir):
+    """Récupère la liste des noms de fichiers contenant a priori des échecs mailman."""
+    files = [mailman_problems_dir + f for f in os.listdir(mailman_problems_dir) if f.endswith(":2,a")]
+    return files
+
+def get_context_and_mail(text):
+    """Récupère l'adresse mail qui a causé un échec et quelques lignes de contexte."""
+    results = [m.groupdict() for m in find_context_regex.finditer(text)]
+    return results
+
+def files_to_mails(files):
+    """Trouve tous les mails des bad guys."""
+    bad_guys = []
+    for mailfile in files:
+        mail = open(mailfile).read().decode("utf-8")
+        # On regarde si il s'agit bien d'un échec
+        isdelivery = len(delivery_regex.findall(mail)) > 0
+        if isdelivery:
+            results = get_context_and_mail(mail)
+            if results:
+                [result] = results
+                bad_guys.append(result)
+            else:
+                ans = raw_input("Headers not found. Show mail ? ")
+                if not ans in "nN":
+                    print mail
+    return bad_guys
+
+def serial_exterminate(bad_guys):
+    """Extermine tout le monde, en demandant confirmation."""
+    import mailman_bad_guys
+    infos = mailman_bad_guys.get_all()
+    for bad_guy in bad_guys:
+        print bad_guy["context"]
+        mailman_bad_guys.exterminate_this_guy(bad_guy["mail"], infos)
+        print "\n\n\n"
+
+def do_all():
+    """Fait le boulot."""
+    files = list_files()
+    bad_guys = files_to_mails(files)
+    serial_exterminate(bad_guys)
+
+if __name__ == "__main__":
+    do_all()