[Mailman-Developers] Running Mailman via POP
amk at amk.ca
amk at amk.ca
Fri Sep 5 08:58:30 EDT 2003
Here's a little script I just wrote for having Mailman retrieve messages to
process via POP. This is useful in my current situation, where
reconfiguring the corporate mail server isn't an option. Instead I plan to
set up aliases directing mail to foo, foo-subscribe, foo-bounces, etc. into
a single 'mailman' mailbox. This script will run from cron, getting the
messages via POP, and passing them to the right command.
Does anyone have comments on this code? Especially any potential problems
with it...
In the next day or two I'll put this up on my web pages somewhere so it gets
Googled.
--amk
#
# Mailman via POP
#
import os, poplib, rfc822, cStringIO
# Configuration information
POP_HOST = 'pop.example.com'
POP_USER = 'mailman'
POP_PASSWORD = 'password'
MESSAGE_ID_FILE = '/tmp/message-ids'
# List of domains containing mailing list addresses.
# e.g. if this is ['x', 'y'], then foo at x and foo at y are both treated
# as an e-mail to the 'foo' mailing list.
LIST_DOMAINS = ['example.com', 'lists.example.com']
def process_message (list_name, script_name, msg_id, message):
print list_name, script_name, msg_id
# Check if list exists
if not os.path.exists('/home/mailman/lists/%s' % list_name):
# It must not be a list
return
# Check if this message has already been processed for this list.
try:
input = open(MESSAGE_ID_FILE, 'r')
except IOError:
pass
else:
for line in input:
sent_msg_id, sent_list = line.split()
if (msg_id == sent_msg_id and
sent_list == list_name):
print 'Already processed message %r -- skipping' % msg_id
input.close()
return
input.close()
# Try to open the message ID file for writing before doing anything
# further.
output = open(MESSAGE_ID_FILE, 'a')
# XXX process message
pipe = os.popen('/home/mailman/mail/mailman %s %s' %
(script_name, list_name), 'w')
pipe.write(message)
pipe.close()
output.write('%s %s\n' % (msg_id, list_name))
output.close()
def display_message(message, show_body=False):
print 'From:', message.getheader('From')
print 'Subject:', message.getheader('Subject')
print 'To:', message.getheader('To')
print 'Cc:', message.getheader('Cc')
print 'Message-ID:', message.getheader('Message-ID')
if show_body:
message.rewindbody()
print message.fp.read()
def main():
conn = poplib.POP3(POP_HOST)
conn.user(POP_USER)
conn.pass_(POP_PASSWORD)
count, size = conn.stat()
##print count, 'messages'
# Read the messages and figure out which lists they belong to
for i in range(1, count+1):
resp, lines, octets = conn.retr(i)
msg_text = '\n'.join(lines)
fp = cStringIO.StringIO(msg_text)
msg = rfc822.Message(fp)
lists = []
for human_name, email_addr in (msg.getaddrlist('to') +
msg.getaddrlist('cc')):
for domain in LIST_DOMAINS:
if email_addr.endswith('@'+domain):
index = email_addr.find('@')
list_name = email_addr[:index].lower()
# Remove suffixes
script_name = 'post'
for suffix in ['admin', 'bounces', 'confirm', 'join',
'leave', 'owner', 'request',
'subscribe', 'unsubscribe']:
if list_name.endswith('-'+suffix):
list_name = list_name.replace('-'+suffix, '')
script_name = suffix
if list_name not in lists:
lists.append(list_name)
if len(lists) == 0:
print 'Ignoring message:'
display_message(msg, show_body=True)
else:
message_id = msg.getheader('Message-ID')
for list in lists:
process_message(list, script_name, message_id, msg_text)
conn.dele(i)
conn.quit()
if __name__ == '__main__':
main()
More information about the Mailman-Developers
mailing list