Qmail Address Lister
What it does:
What does this proggie do? Well, it lists qmail's users, that's what!
Sometimes, for some reason, you will want a list of all valid addresses on a qmail system. This is not that. It stops too soon (see below), but it is close.
I wrote this to use with some squirrelmail plugin, so the output may not be what you expect, but it's easy to change.
It does, however, give you all first-level mail addresses (no sub-addresses like joe-spam@spamjoe.com), because there are potentially an infinite number of those. Also, it ignores aliases.
It tries to figure out if something is really wrong with your users, and warn you.
How this works:
Assuming you are using a "classical" multi-user qmail system, every domain listed in /var/qmail/control/locals is valid for all users. So, I get the list of users and cross it with that list, to get a bunch of addresses.
For each domain in /var/qmail/control/virtualdomains, there is a prefix. Usually (I assume this), that prefix will match a user's name, and all sub-addresses of that user, as defined in his .qmail-* files, are valid addresses for this domain.
So, I fetch that. For each domain (say, virtualdomain) I get the prefix (say pref), I read all .qmail files in /home/pref (say .qmail-ext) and add an address of the form p-ext@virtualdomain .
Keep in mind that .qmail files feeding programs or whatever will confuse the bejeezus out of this script. However, the net effect should simply be some weird address in the output, nothing else.
The code:
It is not meant to be fast, or short, but it is meant to be written clearly!
The variable names are in spanish for reason of lazyness ;-)
import os
import sys
import time
resultados=[]
#First, read all users of the system
users={}
for linea in open('/etc/passwd','r'):
data=linea.split(':')
login=data[0]
nombre=data[4]
home=data[5]
users[login]=(nombre,home)
# Now, read the list of virtual domains
virtuales={}
for linea in open('/var/qmail/control/virtualdomains','r'):
(dominio,usuario)=linea[:-1].split(':')
virtuales[dominio]=usuario
# Read the list of local domains
locals=[]
for linea in open('/var/qmail/control/locals','r'):
#Discar domains that are also in virtualdomains,
#Those, we handle different
dominio=linea[:-1]
locals.append(dominio)
# Now process the virtual domains.
for dominio in virtuales.keys():
usuario=virtuales[dominio]
try:
home=users[usuario][1]
except KeyError:
sys.stderr.write("WARNING: Usuer %s Doesn't exist, but he's the main user of a domain!\n"%usuario)
continue
#Open the user's home directory
try:
archivos=os.listdir(home)
except OSError:
sys.stderr.write("-----------------------------------------------------------------------------\n")
sys.stderr.write("ERROR: User %s exists, but has no home! (should be %s)\n"%(usuario,home))
sys.stderr.write("-----------------------------------------------------------------------------\n")
time.sleep(5)
continue
#Now take all .qmail-something on the user's home
#And for each, create the matching entry
for archivo in archivos:
if archivo[0:7]=='.qmail-':
for linea in open(home+'/'+archivo):
if linea[0]=='&':
username=linea[1:-1]
try:
resultados.append('%s,%s,%s@%s'%(username,users[username][0],username,dominio))
except KeyError:
sys.stderr.write("WARNING: user %s has an address on domain %s, but he doesn't exist!\n"
%(username,dominio))
continue
#All users have addresses on the locals domains (you shouldn't have many of these!)
for username in users.keys():
for local in locals:
resultados.append( '%s,%s,%s@%s'%(username,users[username][0],username,local) )
for item in resultados:
print item
Hi very nice article