Skip to content

Instantly share code, notes, and snippets.

@gronke
Last active September 9, 2022 07:40
Show Gist options
  • Save gronke/0dc3635d7c5de73ba6c967c04c3e72df to your computer and use it in GitHub Desktop.
Save gronke/0dc3635d7c5de73ba6c967c04c3e72df to your computer and use it in GitHub Desktop.
Mailman 2.1.23 helper to re-generate virtual-mailman

Mailman 2.1.23 Helper to (re-)generate virtual-mailman file

A Mailman helper that re-generates the virtual-mailman file without creating or removing lists.

Usage

# Install Helper
cp index_virtual.py /usr/lib/mailman/bin/index_virtual

# Delete old virtual-mailman file
rm /var/lib/mailman/data/virtual-mailman

# Generate new virtual-mailman file for all lists
/usr/lib/mailman/bin/index_virtual -a
#! /usr/bin/python2
import os
import sys
import paths
import getopt
import errno
import time
from Mailman import mm_cfg
#from Mailman import MailList
from Mailman import MailList
from Mailman import Utils
from Mailman import i18n
from Mailman import Errors
from Mailman.MTA.Utils import makealiases
_ = i18n._
C_ = i18n.C_
VIRTFILE = os.path.join(mm_cfg.DATA_DIR, 'virtual-mailman')
def usage(code, msg=''):
if code:
fd = sys.stderr
else:
fd = sys.stdout
print >> fd, C_(__doc__)
if msg:
print >> fd, msg
sys.exit(code)
def _isvirtual(mlist):
return (mlist and mlist.host_name.lower() in
[d.lower() for d in mm_cfg.POSTFIX_STYLE_VIRTUAL_DOMAINS])
def _addvirtual(mlist, fp):
listname = mlist.internal_name()
fieldsz = len(listname) + len('-unsubscribe')
hostname = mlist.host_name
# Set up the mailman-loop address
loopaddr = Utils.get_site_email(mlist.host_name, extra='loop')
loopdest = Utils.ParseEmail(loopaddr)[0]
# And the site list posting address.
siteaddr = Utils.get_site_email(mlist.host_name)
sitedest = Utils.ParseEmail(siteaddr)[0]
if mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN:
loopdest += '@' + mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN
sitedest += '@' + mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN
# If the site list's host_name is a virtual domain, adding it to the
# SITE ADDRESSES will duplicate the list posting entry, so comment it.
if _isvirtual(MailList.MailList(mm_cfg.MAILMAN_SITE_LIST, lock=False)):
siteaddr = '#' + siteaddr
# Seek to the end of the text file, but if it's empty write the standard
# disclaimer, and the loop catch address and site address.
fp.seek(0, 2)
if not fp.tell():
print >> fp, """\
# This file is generated by Mailman, and is kept in sync with the binary hash
# file virtual-mailman.db. YOU SHOULD NOT MANUALLY EDIT THIS FILE unless you
# know what you're doing, and can keep the two files properly in sync. If you
# screw it up, you're on your own.
#
# Note that you should already have this virtual domain set up properly in
# your Postfix installation. See README.POSTFIX for details.
# LOOP ADDRESSES START
%s\t%s
# LOOP ADDRESSES END
# We also add the site list address in each virtual domain as that address
# is exposed on admin and listinfo overviews.
# SITE ADDRESSES START
%s\t%s
# SITE ADDRESSES END
""" % (loopaddr, loopdest, siteaddr, sitedest)
# The text file entries get a little extra info
print >> fp, '# STANZA START:', listname
print >> fp, '# CREATED:', time.ctime(time.time())
# Now add all the standard alias entries
for k, v in makealiases(listname):
fqdnaddr = '%s@%s' % (k, hostname)
if mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN:
localaddr = '%s@%s' % (k, mm_cfg.VIRTUAL_MAILMAN_LOCAL_DOMAIN)
else:
localaddr = k
# Format the text file nicely
print >> fp, fqdnaddr, ((fieldsz - len(k)) * ' '), localaddr
# Finish the text file stanza
print >> fp, '# STANZA END:', listname
print >> fp
def _do_create(mlist, textfile, func):
# Crack open the plain text file
try:
fp = open(textfile, 'r+')
except IOError, e:
if e.errno <> errno.ENOENT: raise
omask = os.umask(007)
try:
fp = open(textfile, 'w+')
finally:
os.umask(omask)
try:
func(mlist, fp)
finally:
fp.close()
def main():
try:
opts, args = getopt.getopt(
sys.argv[1:], 'a',
['all'])
except getopt.error, msg:
usage(1, msg)
listnames = {}
for opt, arg in opts:
if opt in ('-h', '--help'):
usage(0)
elif opt in ('-a', '--all'):
for name in Utils.list_names():
listnames[name] = 1;
if not listnames:
if args and args[0]:
listnames[args[0]] = 1
else:
print >> sys.stderr, C_('Nothing to do.')
sys.exit(0)
for listname in listnames.keys():
try:
mlist = MailList.MailList(listname, lock=0)
except Errors.MMListError:
usage(1, C_('No such list: %(listname)s'))
_do_create(mlist, VIRTFILE, _addvirtual)
print listname
if __name__ == '__main__':
main()
Copyright (C) 2001-2016 by the Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
USA.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment