From 05170d82b349644c8524454ebd67885773e875d1 Mon Sep 17 00:00:00 2001 From: chove Date: Sat, 29 Apr 2006 13:26:34 +0200 Subject: [PATCH] import initial darcs-hash:20060429112634-4ec08-45633df0c09789fa4ccafa4e05dc10fb3ace0677.gz --- gestion/config_mail.py | 283 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100755 gestion/config_mail.py diff --git a/gestion/config_mail.py b/gestion/config_mail.py new file mode 100755 index 00000000..33852f6b --- /dev/null +++ b/gestion/config_mail.py @@ -0,0 +1,283 @@ +#! /usr/bin/env python +# -*- coding: iso8859-15 -*- +############################################################################### +# config_mail : gestion du .forward et .procmailrc des adhérents +############################################################################### +# The authors of this code are +# Etienne Chové +# +# Copyright (C) 2006 Etienne Chové +# All rights reserved. +# +# 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 +############################################################################### + +############################################################################ +## Chaines de formatage pour le procmailrc + +""" +Script permetant de gérer sa configuration mail + +Usage : ConfigMail.py [--forward=(|)] [--spam=(accepte|marque|supprime)] +Retourne : + forward=(|) + spam=(accepte|marque|supprime) +""" + +procmail_warning = """################################################################ +# Ce fichier de configuration a été automatiquement généré par # +# l'intranet. # +# # +# ATTENTION : ne le modifiez que si vous savez ce que vous # +# faites !!! # +################################################################ + +""" + +procmail_mark = """# Passage des mails dans spamassassin +:0 Whbf +* < 256000 +| spamc + +# Serveur blacklisté +:0 +* ^X-Reject: 554 +* !^X-Spam-Status: Yes +{ + :0 Whf + * ^Subject:\/.* + | formail -i "Subject: *****SPAM***** $MATCH" +} + +""" + +procmail_delete_spam = """# Suppression des spams +:0 Whf +* ^Subject: *****SPAM***** +/dev/null + +""" + +procmail_forward = """# Redirection des mails +:0 +!%s +""" + +forward_procmail = '"|exec /usr/bin/procmail"\n' + +## +############################################################################ + + +from commands import getstatusoutput +import os, sys, pwd, getopt +home = pwd.getpwuid(os.getuid())[5] +import re + +class MailConfigError(ReferenceError): + pass + +############################################################################ +## Fonctions utiles + +def _IsMail(mail): + """ + Dit si la chaine fournie est une adresse mail valide + """ + + return bool(re.match('[a-z0-9_\.-]+@[a-z0-9_-]+(\.[a-z0-9_-]+)+',mail)) + +def _Clean(texte): + """ + Nettoie une chaine de caractère/liste en supprimant les lignes vides/commentés, + et retourne une liste + """ + + if type(texte) != list: + texte = texte.split('\n') + return [ x.strip() for x in texte if x.strip() and x[0]!='#' ] + +def _GetConfig(): + """ Retourne la configuration de l'utilisateur courant, + sous forme d'un dictionnaire + """ + + ## lecture du fichier .forward + try: + fic_forward = _Clean( open('%s/.forward'%home).readlines() ) + if len(fic_forward) != 1: + raise MailConfigError, 'Fichier forward trop long' + fic_forward = fic_forward[0] + except IOError: + return {'forward':'', 'spam':'accepte'} + + # forward simple + if _IsMail(fic_forward): + return {'forward':fic_forward, 'spam':'accepte'} + + # utilisation de procmail + if fic_forward != _Clean(forward_procmail)[0]: + raise MailConfigError, 'Fichier forward non compréhensible' + + ## lecture du .procmailrc + fic_procmail = _Clean( open('%s/.procmailrc'%home).readlines() ) + + # forward + if _IsMail( fic_procmail[-1][1:].strip() ) and fic_procmail[-2] == ":0" : + forward = fic_procmail[-1][1:].strip() + fic_procmail = fic_procmail[:-2] + else: + forward = '' + + # forward simple dans le procmailrc + if not fic_procmail: + return {'forward':forward, 'spam':'accepte'} + + # marquage des spams + tmp = _Clean( procmail_mark ) + if fic_procmail[:len(tmp)] != tmp: + raise MailConfigError, 'Fichier de procmail non compréhensible' + fic_procmail = fic_procmail[len(tmp):] + + # suppression des spams ? + if not fic_procmail: + return {'forward':forward, 'spam':'marque'} + elif fic_procmail == _Clean(procmail_delete_spam): + return {'forward':forward, 'spam':'supprime'} + else: + raise MailConfigError, 'Fichier de procmail non compréhensible' + +def _SetConfig(forward = None, spam= None): + """ Modifie la configuration de l'utilisateur courant """ + + # variable new_spam + if spam in ['accepte','supprime','marque']: + new_spam = spam + elif spam == None: + new_spam = _GetConfig()['spam'] + else: + raise ValueError, 'Valeur interdite pour le paramètre spam' + + # variable forward + if forward == None: + new_forward = _GetConfig()['forward'] + elif _IsMail(forward) or forward=='': + new_forward = forward + else: + raise ValueError, 'Adresse mail invalide' + + # génération des fichiers + if new_spam=='accepte': + # suppression du .procmailrc + try: + os.remove('%s/.procmailrc'%home) + except: + pass + # remplissage du .forward + if new_forward: + open('%s/.forward'%home,'w').write('%s\n'%new_forward) + else: + os.remove('%s/.forward'%home) + else: + # écriture du .procmailc + txt = procmail_warning + procmail_mark + if new_spam=='supprime': + txt += procmail_delete_spam + if new_forward: + txt += procmail_forward % new_forward + open('%s/.procmailrc'%home,'w').write(txt) + # écriture du .forward + open('%s/.forward'%home,'w').write(forward_procmail) + +def _Sudo(uid, forward=None, spam=None): + """ Execute le script pour un autre utilisateur """ + # construction de la ligne de commande + if __file__=='.pyc': + f = __file__[:-1] + else: + f = __file__ + c = "/usr/bin/sudo -u %s %s" % (uid, os.path.abspath(f)) + if forward!=None: + c += " --forward=%s" % forward + if spam!=None: + c += " --spam=%s" % spam + + # execution de la commande + print c + status, output = getstatusoutput(c) + + # code d'erreur + if status: + print "Erreur sudo" + sys.exit(status) + + # valeurs de retour + res = {} + for line in output.split('\n'): + line = line.split('=') + res[line[0]] = len(line)==2 and line[1] or '' + return res + +## +############################################################################ + +def MailConfig(uid=None, forward=None, spam=None): + """ Modifie ou retourne la configuration mail de l'utilisateur + + user = utilisateur à configurer, si None configure l'utilisateur courant + forward = adresse vers laquelle rediriger les mails, chaine vide si pas de redirection + spam = action à effectuer sur les spams (accepte, supprime, marque) + + Pour les champs forward et spam, la valeur None ne touche pas au champ. + + Retourne un dictionnaire { 'forward':'', 'spam':'' } + """ + + ## demande pour un autre utilisateur + if uid: + return _Sudo(uid=uid, forward=forward, spam=spam) + + ## nettoyage des variables + cfg = _GetConfig() + if forward == cfg['forward']: + forward = None + if spam == cfg['spam']: + spam = None + + ## modifications + if forward!=None or spam!=None: + _SetConfig(forward=forward, spam=spam) + + ## on renvoie la configuration + return _GetConfig() + +if __name__=="__main__": + ## parsage des arguments + forward = None + spam = None + opts, args = getopt.getopt(sys.argv[1:], "", ['forward=', 'spam=']) + for o, v in opts: + if o == "--forward": + forward = v + elif o == '--spam': + spam = v + + ## execution de MailConfig + res = MailConfig(forward=forward, spam=spam) + + ## affichage des résultats + for i in res.items(): + print "%s=%s" % i +