I set up a Mailman mailing list. I want archives. I want these archives to look like other dynamic parts of the site (brought to you by Ruby on Rails). And I want to integrate a couple years’ worth of Topica messages.
At I first, I figured I’d use MHonArc or something similar. Mailman’s external interface is lightly documented, but simple and capable once you figure it out. Looking at the Python code helps in /usr/mailman/Mailman.
I decided to use Rails in the end. Maybe not the best choice, but I like keeping all my UI code in once place as much as possible.
I have an ActionMailer subclass with a delivery method:
class MailingListMailer < ActionMailer::Base
def receive(email)
post = Post.new()
post.subject = email.subject
post.body = email.body
post.sender = email.friendly_from
post.date = email.date
post.save!
end
end
class Post << ActionRecord::Base ....
I added an entry to PUBLIC_EXTERNAL_ARCHIVER in Mailman's mm_cfg.py file. On Suse 10, it's in /usr/lib/mailman/Mailman. I've add backslash line breaks for legibility here.
PUBLIC_EXTERNAL_ARCHIVER = '/srv/www/rails/obra/current/script/runner \
-e "production" "MailingListMailer.receive(STDIN.read)" \
>> /srv/www/rails/obra/shared/log/production.log'
I made several mistakes:
- You need to restart Mailman for it to pickup your changes: /usr/lib/mailman/bin/mailmanctl restart
- The apostrophes need to be around your command: '/srv/www ... production.log' Otherwise, you are trying to execute Python code, not assign a string variable.
- Leave out -e "production" and Rails will execute in its development environment.
- Ensure your logs are writeable by the mailman user, or nothing will work very well.
A typical Mailman error message in /var/lib/mailman/logs/error is "external archiver non-zero exit status: 127." Not very helpful. My shell foo isn't up to the task of redirecting standard error and standard out from the PUBLIC_EXTERNAL_ARCHIVER command. I got better info with Mailman calling a Bash script that then called the Rails runner. I validated that things worked at each small step, and I had to take baby steps because I kept putting a single quote where I needed a double quote, etc.:
- Unit test for the ActionMailer
- Run the ActionMailer in irb
- Run the runner: sudo -u mailman /srv/www/rails/obra/current/script/runner -e "production" "MailingListMailer.receive(STDIN.read)"
- Write a shell script to call the runner
Of course, it's helpful the public Mailman pages point to my new Rails-based archive. Here's how I do it. In Mailman/mm_cfg.py:
PUBLIC_ARCHIVE_URL = 'http://%(hostname)s/mailing_lists/%(listname)s/posts'
I like the end result, and it's easy to do once you know how to do it. Next step is to see if Rails can sew a header and footer onto the Mailman list info pages. I am keeping the gnu, of course.