Envoi de mail.
Plus de flexibilit. Par Stphane. darcs-hash:20051112202343-d1718-8362a0de7a93945ae9250cbabb102e33e02e2271.gz
This commit is contained in:
parent
2c8793825d
commit
d30c547306
1 changed files with 218 additions and 130 deletions
|
@ -4,15 +4,36 @@
|
|||
# Copyright (C) Stéphane Glondu
|
||||
# Licence : GPLv2
|
||||
|
||||
u"""Ce script permet au trésorier de contrôler plus facilement le travail
|
||||
des câbleurs.
|
||||
u"""Ce script permet au trésorier de repérer plus facilement les papiers que
|
||||
les câbleurs n'ont pas encore rendus.
|
||||
|
||||
Usage: %(prog)s {paiement|carte|mail}
|
||||
Utilisations possibles :
|
||||
* %(prog)s {paiement|carte|list} [--debug <adresse>]
|
||||
* %(prog)s mail <liste> [--debug <adresse>]
|
||||
|
||||
L'unique option est :
|
||||
--debug <adresse> envoyer tous les mails à l'<adresse> indiquée, plutôt
|
||||
qu'aux vrais destinataires
|
||||
|
||||
Les commandes sont :
|
||||
* paiement contrôle interactif des nouvelles (ré-)adhésions
|
||||
* carte contrôle interactif des nouvelles cartes d'étudiant
|
||||
* list affiche le récapitulatif des papiers manquants
|
||||
* mail <liste> envoyer les mails de rappel aux câbleurs dont le
|
||||
login est dans la <liste>, 'bureau' désignant le mail
|
||||
récapitulatif envoyé à bureau ; si la liste est vide
|
||||
tous les mails nécessaires seront envoyés
|
||||
|
||||
Le modèle du mail envoyé aux câbleurs est lu sur l'entrée standard (typiquement
|
||||
via une redirection). Les trois premières lignes doivent être :
|
||||
Encoding: <encodage du fichier>
|
||||
Subject: <sujet du mail>
|
||||
<ligne vide>
|
||||
Le reste est le corps du message. Il doit contenir une occurrence de '%%s' qui
|
||||
sera remplacée par la liste des papiers manquants.
|
||||
|
||||
Le mail récapitulatif envoyé à bureau est immuable."""
|
||||
|
||||
Les options sont :
|
||||
* paiement : contrôle interactif des nouvelles (ré-)adhésions
|
||||
* carte : contrôle interactif des nouvelles cartes d'étudiant
|
||||
* mails : envoyer les mails de rappel"""
|
||||
|
||||
import sys, os, re
|
||||
sys.path.append('/usr/scripts/gestion')
|
||||
|
@ -37,16 +58,26 @@ if u'Contr
|
|||
print u"Il faut être contrôleur pour exécuter ce script !"
|
||||
sys.exit(1)
|
||||
|
||||
# Lors des tests sur egon, on m'envoie tous les mails !
|
||||
# Lors des tests, on m'envoie tous les mails !
|
||||
from socket import gethostname
|
||||
testing = gethostname().split(".")[0] == 'egon'
|
||||
if testing:
|
||||
print coul(u'Mode testing !', 'violet')
|
||||
debug = False
|
||||
|
||||
if gethostname().split(".")[0] == 'egon':
|
||||
debug = 'glondu@crans.org'
|
||||
ann_scol = 2004
|
||||
|
||||
if __name__ == '__main__':
|
||||
if len(sys.argv) > 3 and sys.argv[-2] == '--debug':
|
||||
debug = sys.argv[-1]
|
||||
sys.argv.pop()
|
||||
sys.argv.pop()
|
||||
|
||||
if debug:
|
||||
print u'Mode debug, tous les mails seront envoyés à %s.' % debug
|
||||
|
||||
|
||||
def _controle_interactif_adherents(liste, quoi):
|
||||
u"""
|
||||
"""
|
||||
Contrôle interactif des adhérents de la liste (quoi = p ou c).
|
||||
Retourne (nb_OK, nb_pas_OK).
|
||||
"""
|
||||
|
@ -81,7 +112,7 @@ def _controle_interactif_adherents(liste, quoi):
|
|||
|
||||
|
||||
def _controle_interactif_clubs(liste):
|
||||
u"""
|
||||
"""
|
||||
Contrôle interactif des clubs de la liste (uniquement la charte).
|
||||
Retourne (nb_OK, nb_pas_OK).
|
||||
"""
|
||||
|
@ -114,7 +145,7 @@ def _controle_interactif_clubs(liste):
|
|||
|
||||
|
||||
def controle_interactif(quoi):
|
||||
u"""
|
||||
"""
|
||||
Procédure interactive de contrôle des paiements/chartes (quoi=p) et cartes (quoi=c).
|
||||
"""
|
||||
if quoi not in 'pc': raise ValueError
|
||||
|
@ -144,53 +175,58 @@ def controle_interactif(quoi):
|
|||
|
||||
|
||||
def formater_pour_cableur(liste):
|
||||
u"""
|
||||
"""
|
||||
Formate la liste d'adhérents ou de clubs avec les dates correspondantes.
|
||||
liste est une liste de couples (date, objet).
|
||||
"""
|
||||
lignes = [(u'id', u'Nom', u'Date Heure')]
|
||||
total = 0
|
||||
liste.sort(lambda x, y: cmp(x[1].nom(), y[1].nom()))
|
||||
|
||||
for date, a in liste:
|
||||
lignes.append((a.id(), a.Nom(), date))
|
||||
total += 1
|
||||
|
||||
return tableau([6, 40, 18], lignes)
|
||||
return tableau([6, 40, 18], lignes) + u'\nTotal : %d' % total
|
||||
|
||||
|
||||
def formater_pour_bureau(dico):
|
||||
u"""
|
||||
"""
|
||||
Formate la liste d'adhérents ou de clubs avec les câbleurs correspondantes
|
||||
pour le mail récapitulatif envoyé à bureau.
|
||||
"""
|
||||
lignes = [(u'id', u'Nom', u'Câbleur')]
|
||||
|
||||
total = 0
|
||||
for cableur in dico.keys():
|
||||
|
||||
liste = dico.keys()
|
||||
liste.sort()
|
||||
for cableur in liste:
|
||||
for date, a in dico[cableur]:
|
||||
lignes.append((a.id(), a.Nom(), cableur))
|
||||
total += 1
|
||||
|
||||
return tableau([6, 40, 17], lignes) + '\nTotal : %d' % total
|
||||
return tableau([6, 40, 18], lignes) + u'\nTotal : %d' % total
|
||||
|
||||
|
||||
def qui(historique, quoi):
|
||||
u"""
|
||||
"""
|
||||
Recherche le câbleur qui a effectué la dernière modification quoi
|
||||
dans l'historique, ou qui a inscrit l'adhérent.
|
||||
Retourne le couple (date_heure, nom_cableur).
|
||||
Retourne le couple (date, cableur) ou ('_inconnu_', '_inconnu_').
|
||||
"""
|
||||
regexp = re.compile(r'^([^,]*), ([^ :]*)')
|
||||
cableur = ('_inconnu_', '_inconnu_')
|
||||
|
||||
for ligne in historique:
|
||||
if quoi in ligne or 'inscription' in ligne:
|
||||
matched = regexp.match(ligne)
|
||||
matched = regexp.search(ligne)
|
||||
if matched: cableur = matched.group(1), matched.group(2)
|
||||
|
||||
return cableur
|
||||
|
||||
|
||||
def chercher_cableurs(liste, quoi):
|
||||
u"""
|
||||
"""
|
||||
Renvoie un dictionnaire cableur->adherents à partir de liste, quoi
|
||||
désigne le champ qui sera recherché dans l'historique.
|
||||
"""
|
||||
|
@ -204,128 +240,180 @@ def chercher_cableurs(liste, quoi):
|
|||
return resultat
|
||||
|
||||
|
||||
from smtplib import SMTP
|
||||
from email.MIMEText import MIMEText
|
||||
from email_tools import send_email, parse_mail_template
|
||||
|
||||
# Mise en application du mémorable cours de Fred sur les objets :-)
|
||||
|
||||
def envoyer_mails_rappel():
|
||||
u"""
|
||||
Envoyer les mails de rappel aux câbleurs avec bureau en cc,
|
||||
ainsi que le récapitulatif à bureau.
|
||||
"""
|
||||
# On recherche tous les câbleurs concernés
|
||||
class ControleMailer:
|
||||
|
||||
def __init__(self):
|
||||
# Recherche des câbleurs possédant des cotisations/chartes
|
||||
todo_list = db.search('paiement=%d&controle!=*p*' % ann_scol)
|
||||
paiements = chercher_cableurs(todo_list['adherent'], 'paiement')
|
||||
chartes = chercher_cableurs(todo_list['club'], 'paiement')
|
||||
cartes = chercher_cableurs(db.search('carteEtudiant=%d&controle!=*c*' % ann_scol)['adherent'], 'carteEtudiant')
|
||||
self._paiements = chercher_cableurs(todo_list['adherent'], 'paiement')
|
||||
self._chartes = chercher_cableurs(todo_list['club'], 'paiement')
|
||||
|
||||
# Méthode de Vince
|
||||
# Recherche des câbleurs possédant des cartes d'étudiant
|
||||
todo_list = db.search('carteEtudiant=%d&controle!=*c*' % ann_scol)
|
||||
self._cartes = chercher_cableurs(todo_list['adherent'], 'carteEtudiant')
|
||||
|
||||
# Récupère tous les câbleurs qui doivent quelque chose
|
||||
cableurs = {}
|
||||
for a in paiements.keys():
|
||||
for a in self._paiements.keys():
|
||||
if a != '_inconnu_': cableurs[a] = None
|
||||
for a in chartes.keys():
|
||||
for a in self._chartes.keys():
|
||||
if a != '_inconnu_': cableurs[a] = None
|
||||
for a in cartes.keys():
|
||||
for a in self._cartes.keys():
|
||||
if a != '_inconnu_': cableurs[a] = None
|
||||
self._cableurs = cableurs.keys()
|
||||
|
||||
# Squelette à modifier après
|
||||
msg_skeleton = u"""\
|
||||
Salut,
|
||||
|
||||
Tu me dois des papiers. J'ai mis l'aid ou le cid afin que tu puisses
|
||||
vérifier facilement dans la base.
|
||||
%s
|
||||
Peux-tu confirmer et donner ces papiers le plus rapidement possible à
|
||||
Florian, Augustin, les laisser au 2B ou directement me les donner ?
|
||||
|
||||
--
|
||||
Stéphane
|
||||
"""
|
||||
|
||||
# Vérification de l'alias pour l'envoi des mails
|
||||
# Vérification de l'alias pour l'expéditeur
|
||||
if u'tresorier' in cableur.alias():
|
||||
moi = (u'%s <tresorier@crans.org>' % cableur.Nom()).encode('utf8')
|
||||
self._sender = u'%s <tresorier@crans.org>' % cableur.Nom()
|
||||
else:
|
||||
moi = (u'%s <%s@crans.org>' % (cableur.Nom(), cableur.canonical_alias())).encode('utf8')
|
||||
self._sender = u'%s <%s@crans.org>' % (cableur.Nom(),
|
||||
cableur.cannonical_alias() or cableur.mail())
|
||||
|
||||
# On se connecte au serveur
|
||||
s = SMTP()
|
||||
s.connect()
|
||||
# Se connecte au serveur SMTP par défaut
|
||||
from smtplib import SMTP
|
||||
self._server = SMTP()
|
||||
self._server.connect()
|
||||
|
||||
# On envoie les mails
|
||||
def __del__(self):
|
||||
# Termine la connexion au serveur SMTP
|
||||
self._server.quit()
|
||||
|
||||
def recapitulatif(self):
|
||||
"""
|
||||
Renvoie le récapitulatif pour le bureau.
|
||||
"""
|
||||
msg = u''
|
||||
|
||||
if self._paiements:
|
||||
msg += u"Fiches d'adhésion et cotisations des adhérents :\n"
|
||||
msg += formater_pour_bureau(self._paiements) + '\n\n'
|
||||
|
||||
if self._chartes:
|
||||
msg += u"Chartes signées des clubs :\n"
|
||||
msg += formater_pour_bureau(self._chartes) + '\n\n'
|
||||
|
||||
if self._cartes:
|
||||
msg += u"Carte d'étudiant des adhérents :\n"
|
||||
msg += formater_pour_bureau(self._cartes) + '\n\n'
|
||||
|
||||
return msg
|
||||
|
||||
def mail_bureau(self):
|
||||
"""
|
||||
Envoie le mail récapitulatif à bureau (s'il y a qqch à envoyer).
|
||||
"""
|
||||
msg = self.recapitulatif()
|
||||
if msg:
|
||||
msg += u"-- \nScript exécuté par %s\n" % cableur.Nom()
|
||||
send_email(self._sender,
|
||||
u"Bureau <bureau@crans.org>",
|
||||
u"Récapitulatif des papiers manquants",
|
||||
msg,
|
||||
server = self._server,
|
||||
debug = debug)
|
||||
return coul(u'Mail envoyé à bureau avec succès !', 'vert')
|
||||
else:
|
||||
return coul(u'Tout est à jour, aucun mail envoyé.', 'vert')
|
||||
|
||||
def mail_cableurs(self, subject, body, liste=None):
|
||||
"""
|
||||
Envoie un mail aux câbleurs concernés qui figurent dans la liste.
|
||||
Si liste vaut None, envoie un mail à tous les câbleurs concernés.
|
||||
Les arguments subject, body permettent de personnaliser (un peu)
|
||||
le mail qui sera envoyé.
|
||||
"""
|
||||
nb = 0
|
||||
for c in cableurs.keys():
|
||||
if liste == None:
|
||||
liste = self._cableurs
|
||||
|
||||
for c in liste:
|
||||
msg = u''
|
||||
|
||||
if c in paiements.keys():
|
||||
msg += u"\nFiches d'adhésion et cotisations des adhérents :\n"
|
||||
msg += formater_pour_cableur(paiements[c]) + '\n'
|
||||
if self._paiements.has_key(c):
|
||||
msg += u"Fiches d'adhésion et cotisations des adhérents :\n"
|
||||
msg += formater_pour_cableur(self._paiements[c]) + '\n\n'
|
||||
|
||||
if c in chartes.keys():
|
||||
msg += u"\nChartes signées des clubs :\n"
|
||||
msg += formater_pour_cableur(chartes[c]) + '\n'
|
||||
if self._chartes.has_key(c):
|
||||
msg += u"Chartes signées des clubs :\n"
|
||||
msg += formater_pour_cableur(self._chartes[c]) + '\n\n'
|
||||
|
||||
if c in cartes.keys():
|
||||
msg += u"\nCarte d'étudiant des adhérents :\n"
|
||||
msg += formater_pour_cableur(cartes[c]) + '\n'
|
||||
if self._cartes.has_key(c):
|
||||
msg += u"Carte d'étudiant des adhérents :\n"
|
||||
msg += formater_pour_cableur(self._cartes[c]) + '\n\n'
|
||||
|
||||
mail = MIMEText((msg_skeleton % msg).encode('utf8'), _charset='UTF-8')
|
||||
mail['Subject'] = u'Papiers manquants'.encode('utf8')
|
||||
mail['From'] = moi
|
||||
adresse_cableur = '%s@crans.org' % c
|
||||
mail['To'] = adresse_cableur
|
||||
mail['Cc'] = 'Bureau <bureau@crans.org>'
|
||||
if testing:
|
||||
recipients = ['glondu@crans.org']
|
||||
else:
|
||||
recipients = [adresse_cableur, 'bureau@crans.org']
|
||||
s.sendmail(moi, recipients, mail.as_string())
|
||||
if msg:
|
||||
send_email(self._sender,
|
||||
"%s@crans.org" % c,
|
||||
subject,
|
||||
body % msg,
|
||||
server = self._server,
|
||||
cc = u'Bureau <bureau@crans.org>',
|
||||
debug = debug)
|
||||
nb += 1
|
||||
|
||||
# On envoie le mail récapitulatif sur bureau
|
||||
if paiements or chartes or cartes:
|
||||
msg = u''
|
||||
|
||||
msg += u"\nFiches d'adhésion et cotisations des adhérents :\n"
|
||||
msg += formater_pour_bureau(paiements) + '\n'
|
||||
|
||||
msg += u"\nChartes signées des clubs :\n"
|
||||
msg += formater_pour_bureau(chartes) + '\n'
|
||||
|
||||
msg += u"\nCarte d'étudiant des adhérents :\n"
|
||||
msg += formater_pour_bureau(cartes) + '\n'
|
||||
|
||||
msg += u"\n-- \nScript exécuté par %s\n" % cableur.Nom()
|
||||
mail = MIMEText(msg.encode('utf8'), _charset='utf8')
|
||||
mail['Subject'] = u'Récapitulatif des papiers manquants'.encode('utf8')
|
||||
mail['From'] = moi
|
||||
mail['To'] = 'Bureau <bureau@crans.org>'
|
||||
if testing:
|
||||
recipients = ['glondu@crans.org']
|
||||
else:
|
||||
recipients = ['bureau@crans.org']
|
||||
s.sendmail(moi, recipients, mail.as_string())
|
||||
nb += 1
|
||||
|
||||
s.close()
|
||||
print coul(u"%d mail(s) envoyé(s) avec succès !" % nb, "vert")
|
||||
return coul(u'%d mail(s) envoyé(s) aux câbleurs avec succès !' % nb, 'vert')
|
||||
|
||||
|
||||
def __usage():
|
||||
u""" Comment ça marche ? """
|
||||
def __usage(message=None):
|
||||
""" Comment ça marche ? """
|
||||
print __doc__ % { 'prog': sys.argv[0] }
|
||||
if message:
|
||||
print message
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == '__main__' :
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == 'paiement':
|
||||
|
||||
if len(sys.argv) <= 1:
|
||||
__usage()
|
||||
|
||||
elif sys.argv[1] == 'paiement':
|
||||
if len(sys.argv) != 2:
|
||||
__usage(u'Mauvaise utilisation de paiement')
|
||||
controle_interactif('p')
|
||||
|
||||
elif sys.argv[1] == 'carte':
|
||||
if len(sys.argv) != 2:
|
||||
__usage(u'Mauvaise utilisation de carte')
|
||||
controle_interactif('c')
|
||||
|
||||
elif sys.argv[1] == 'list':
|
||||
if len(sys.argv) != 2:
|
||||
__usage(u'Mauvaise utilisation de list')
|
||||
print ControleMailer().recapitulatif(),
|
||||
|
||||
elif sys.argv[1] == 'mail':
|
||||
envoyer_mails_rappel()
|
||||
mailer = ControleMailer()
|
||||
cableurs = sys.argv[2:]
|
||||
if cableurs:
|
||||
bureau = False
|
||||
if 'bureau' in cableurs:
|
||||
cableurs.remove('bureau')
|
||||
bureau = True
|
||||
else:
|
||||
__usage()
|
||||
bureau = True
|
||||
cableurs = mailer._cableurs
|
||||
if cableurs:
|
||||
print u'Des mails vont être envoyés aux câbleurs, lecture du modèle...'
|
||||
subject, body = parse_mail_template(sys.stdin)
|
||||
try:
|
||||
body % u''
|
||||
except TypeError:
|
||||
print u"Le format du modèle n'est pas correct, arrêt."
|
||||
sys.exit(1)
|
||||
print u'Modèle OK, on envoie les mails...'
|
||||
print mailer.mail_cableurs(subject, body, cableurs)
|
||||
if bureau:
|
||||
print mailer.mail_bureau()
|
||||
|
||||
else:
|
||||
__usage()
|
||||
__usage(u'Commande inconnue : %s' % sys.argv[1])
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
# pydoc n'aime pas l'unicode :-(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue