summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcotton1998-10-12 15:59:01 +0000
committercotton1998-10-12 15:59:01 +0000
commit9950422e4337975279b02660e0a599cba8baca3c (patch)
treedd4b633e7a3394490bb54287032f27aca3bcad3d
parent18680acd0a330b6d743816e74fbd65de1fc91455 (diff)
downloadmailman-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.in6
-rw-r--r--Mailman/MailList.py23
-rw-r--r--Mailman/Utils.py60
-rw-r--r--Mailman/versions.py2
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']: