diff options
| author | cotton | 1998-10-12 15:59:01 +0000 |
|---|---|---|
| committer | cotton | 1998-10-12 15:59:01 +0000 |
| commit | 9950422e4337975279b02660e0a599cba8baca3c (patch) | |
| tree | dd4b633e7a3394490bb54287032f27aca3bcad3d | |
| parent | 18680acd0a330b6d743816e74fbd65de1fc91455 (diff) | |
| download | mailman-9950422e4337975279b02660e0a599cba8baca3c.tar.gz mailman-9950422e4337975279b02660e0a599cba8baca3c.tar.zst mailman-9950422e4337975279b02660e0a599cba8baca3c.zip | |
added adminitrivia filter and an "administrivia" list attribute that
is editable via the admin cgi to turn the filter on and off.
I'm sure that the filter could catch more things, but it will have
less false positives than majordomo anway :)
a listing of the specific changes follows:
Defaults.py.in changed data file version and added
DEFAULT_ADMINISTRIVIA
Utils.py added a function IsAdministrivia(msg) that does the filtering
replaced re.sub with string.replace(much faster) in
(Un)ObscureEmail.
MailList.py: added the config info for the administrivia variable, and
made the post method check it if the list has the
variable set.
versions.py: make new lists have an administrivia variable
scott
| -rw-r--r-- | Mailman/Defaults.py.in | 6 | ||||
| -rw-r--r-- | Mailman/MailList.py | 23 | ||||
| -rw-r--r-- | Mailman/Utils.py | 60 | ||||
| -rw-r--r-- | Mailman/versions.py | 2 |
4 files changed, 84 insertions, 7 deletions
diff --git a/Mailman/Defaults.py.in b/Mailman/Defaults.py.in index 4307298c4..7dce4fce6 100644 --- a/Mailman/Defaults.py.in +++ b/Mailman/Defaults.py.in @@ -184,6 +184,8 @@ DEFAULT_AUTOMATIC_BOUNCE_ACTION = 1 # get in 1 hour. DEFAULT_MAX_POSTS_BETWEEN_BOUNCES = 5 +DEFAULT_ADMINISTRIVIA = 1 + # # how long the cookie authorizing administrative # changes via the admin cgi lasts @@ -195,6 +197,8 @@ ADMIN_COOKIE_LIFE = 60 * 20 # 20 minutes # ADMIN_MEMBER_CHUNKSIZE = 10 + + # These directories are used to find various important files in the Mailman # installation. PREFIX and EXEC_PREFIX are set by configure and should point # to the installation directory of the Mailman package. @@ -250,4 +254,4 @@ PRIVATE_ARCHIVE_FILE_DIR = os.path.join(PREFIX, 'archives/private') VERSION = '@VERSION@' # Data file version number -DATA_FILE_VERSION = 5 +DATA_FILE_VERSION = 6 diff --git a/Mailman/MailList.py b/Mailman/MailList.py index 82a12efd4..5aa8a2b90 100644 --- a/Mailman/MailList.py +++ b/Mailman/MailList.py @@ -278,6 +278,18 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, '"Reply-To" Munging Considered Harmful</a> for a general.' " discussion of this issue."), + ('administrivia', mm_cfg.Radio, ('No', 'Yes'), 0, + "check messages that are destined for the list for" + " adminsitrative request content?", + + "Administrivia tests will chech mail that is destined for the list " + " for adminstriative contect (like subscribe, unsubscribe, etc). " + " If the message looks like an adminitrative request, it will " + "be added to the administrative requests database and the administrator " + "will be notified. "), + + + ('reminders_to_admins', mm_cfg.Radio, ('No', 'Yes'), 0, 'Send password reminders to "-admin" address instead of' ' directly to user.', @@ -780,8 +792,8 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, def DeleteMember(self, name, whence=None): self.IsListInitialized() -# FindMatchingAddresses *should* never return more than 1 address. -# However, should log this, just to make sure. + # FindMatchingAddresses *should* never return more than 1 address. + # However, should log this, just to make sure. aliases = Utils.FindMatchingAddresses(name, self.members + self.digest_members) if not len(aliases): @@ -897,7 +909,7 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, return line return 0 -#msg should be an IncomingMessage object. + # msg should be an IncomingMessage object. def Post(self, msg, approved=0): self.IsListInitialized() # Be sure to ExtractApproval, whether or not flag is already set! @@ -953,6 +965,11 @@ class MailList(MailCommandHandler, HTMLFormatter, Deliverer, ListAdmin, self.AddRequest('post', Utils.SnarfMessage(msg), Errors.IMPLICIT_DEST_MSG, msg.getheader('subject')) + if self.administrivia and Utils.IsAdministrivia(msg): + self.AddRequest('post', Utils.SnarfMessage(msg), + 'possible administrivia to list', + msg.getheader("subject")) + if self.bounce_matching_headers: triggered = self.HasMatchingHeader(msg) if triggered: diff --git a/Mailman/Utils.py b/Mailman/Utils.py index 88f2ea5c7..b78731314 100644 --- a/Mailman/Utils.py +++ b/Mailman/Utils.py @@ -368,15 +368,16 @@ def ObscureEmail(addr, for_text=0): When for_text option is set (not default), make a sentence fragment instead of a token.""" if for_text: - return re.sub("@", " at ", addr) + return string.replace(addr, "@", " at ") else: - return re.sub("@", "__at__", addr) + return string.replace(addr, "@", "__at__") def UnobscureEmail(addr): """Invert ObscureEmail() conversion.""" # Contrived to act as an identity operation on already-unobscured # emails, so routines expecting obscured ones will accept both. - return re.sub("__at__", "@", addr) + return string.replace(addr, "__at__", "@") + def map_maillists(func, names=None, unlock=None, verbose=0): """Apply function (of one argument) to all list objs in turn. @@ -436,6 +437,59 @@ def maketext(templatefile, dict, raw=0): return wrap(template % dict) +# +# given an IncomingMessage object, +# test for administrivia (eg subscribe, unsubscribe, etc). +# the test must be a good guess -- messages that return true +# get sent to the list admin instead of the entire list. +# +def IsAdministrivia(msg): + lines = map(string.lower, msg.readlines()) + if len(lines) > 30: + return 0 + # + # check to see how many lines that actually have text in them there are + # + admin_data = {"subscribe": (0, 3), + "unsubscribe": (0, 1), + "who": (0,0), + "info": (0,0), + "lists": (0,0), + "set": (2, 3), + "help": (0,0), + "password": (2, 2), + "options": (0,0), + "remove": (0, 0)} + lines_with_text = 0 + for line in lines: + if string.strip(line): + lines_with_text = lines_with_text + 1 + if lines_with_text > 10: # we might want to change this to mm_cfg.DEFAULT_MAIL_COMMANDS_MAX_LINES. + return 0 + if admin_data.has_key(string.lower(string.strip(msg.body))): + return 1 + try: + if admin_data.has_key(string.lower(string.strip(msg["subject"]))): + return 1 + except KeyError: + pass + for line in lines[:5]: + if not string.strip(line): + return + words = string.split(line) + if admin_data.has_key(words[0]): + min_args, max_args = admin_data[words[0]] + if min_args <= len(words[1:]) <= max_args: + return 1 + return 0 + + + + + + + + diff --git a/Mailman/versions.py b/Mailman/versions.py index d030f2e3d..83de0fd92 100644 --- a/Mailman/versions.py +++ b/Mailman/versions.py @@ -70,6 +70,8 @@ def UpdateOldVars(l, stored_state): else: l.subscribe_policy = 2 # admin approval delattr(l, "open_subscribe") + if not hasattr(l, "administrivia"): + setatrr(l, "administrivia", mm_cfg.DEFAULT_ADMINISTRIVIA) # - dropped vars: # for a in ['archive_retain_text_copy', # 'archive_update_frequency']: |
