--- category: '' date: 2004/05/21 20:21 description: '' link: '' priority: '' slug: '28' tags: qmail title: Qmail Address Lister type: text updated: 2004/05/21 20:21 url_type: '' --- .. raw:: html

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 ;-)

#!/usr/bin/python

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