Petit serveur d’adresse mail de diffusion

Plop à tous … encore un truc useless à partager.

J’ai récemment dû intervenir dans une entreprise qui avait un serveur de mail qui ne supportait pas les listes de diffusion (service de base fournit par yahoo en fait, donc à part forwarder des mails sur une adresse, il est pas possible de faire grand chose).

Ne voulant pas perdre trop de temps à mettre en place des systèmes du genre mailman ou autre, pour créer une vingtaine d’alias pour deux adresses mails (style support@mondomaine.fr qui envoit un mail pour toute la team de support), j’ai décidé de coder un serveur de mail qui ne répondrait qu’à certaines adresses et renverrait le mail sur les adresses configurées pour cette adresse de diffusion.

Ecrire ce genre de truc en python est encore plus rapide que de chercher l’équivalent sur google 😉 d’où ma démarche.

La version de base fonctionne ainsi :
Pour la conf, il faut un fichier du genre à mettre dans le répertoire de l’executable :

mail_monadressedediffusion@mondomaine.fr.conf

qui contiendra la liste des adresses mails du genre :

monuser1@mondomaine.fr
monuser2@mondomaine.fr

Ainsi, tout les mails envoyés à « monadressedediffusion@mondomaine.fr » seront envoyés à « monuser1@mondomaine.fr » et « monuser2@mondomaine.fr ».

Bien entendu, si l’adresse mail sur lequel on chope le mail n’a pas de conf (mail_[adresse mail].conf), on n’envoi pas de mail, donc on termine pas en relais pour les méchants spammeurs (pour une utilisation en proxy local, on peut enlever cette partie du code …).

Comm d’hab’, le code est fournit à titre d’exemple « as his & for educational purpose only » comme dirait les anglais, à adapter à ses besoins 😉

#!/usr/bin/env python

from smtpd import PureProxy
import asyncore
import asynchat
import smtplib
import re
import sys
import os.path
import pwd
import grp

class mySMTP (PureProxy):
    def __init__(self,s,n):
        self.serv = n
        PureProxy.__init__(self,s,None)

    def process_message (self, peer, mailfrom, rcpttos, data):
        for rcpt in rcpttos:
                file="mail_"+rcpt+".conf"
                if os.path.exists(file):
                        f = open(file,'r')
                        rcpts = list()
                        for line in f:
                                line=line.strip("\n")
                                if line!=mailfrom:
                                        rcpts.append(line)
                        f.close()
                        if len(rcpts)>0:
                                smtpSender = smtplib.SMTP( self.serv[0], self.serv[1] )
                                smtpSender.sendmail( mailfrom, rcpts, data )
                                smtpSender.quit()
        return None

if __name__ == "__main__":
    if len(sys.argv)<2:
        print "Il manque des arguments : "+sys.argv[0]+" 'serveur smtp','port'"
        sys.exit(2)
    if os.getuid() == 0:
        running_uid = pwd.getpwnam("nobody")[2]
        running_gid = grp.getgrnam("nobody")[2]
        os.setgid(running_gid)
        os.setuid(running_uid)

    if len(sys.argv) == 3:
        serv = mySMTP (("0.0.0.0", 8025), (sys.argv[1],sys.argv[2]))
    try:
        asyncore.loop ()
    except KeyboardInterrupt:
        pass

Ce système n'agit qu'en proxy, il faudra donc lui fournir l'adresse d'un serveur smtp et son port en paramètre pour qu'il puisse forwarder les mails.