[admin/mail_invalide/,gen_confs/] Mise en place deconnexion pour mail invalide

Maintenant, quand on voit un mail invalide :
/usr/scripts/admin/mail_invalide/mail_invalide.py [mail]...
La personne est deconnectee au bout de 2 semaines si elle n'a pas change
son adresse mail.

 * Le script admin/mail_invalide/mail_invalide.py permet de generer les fiches,
et note l'adherent pour deconnexion 2 semaines plus tard (services_to_restart)
 * admin/mail_invalide/mail_invalide.tex est une fusion des deux
mail_invalide*.tex dans le dossier admin/src/
 * gen_confs/adherents.py s'occupe de marquer le mail comme invalide au bout de
2 semaines s'il n'a pas ete change (il met le flag mailInvalide=TRUE)
 * gen_confs/squid.py genere la liste des deconnectes pour Squid

darcs-hash:20091208003119-ddb99-74b4388950300879400250b9c40716013832d45e.gz
This commit is contained in:
Michel Blockelet 2009-12-08 01:31:19 +01:00
parent 6c68846b28
commit 0f9856085e
6 changed files with 287 additions and 159 deletions

246
admin/mail_invalide/mail_invalide.py Normal file → Executable file
View file

@ -1,161 +1,113 @@
#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-
#! /usr/bin/env python
# -*- coding: utf-8 -*-
import sys,os,string,time,locale
locale.setlocale(locale.LC_ALL,'')
sys.path.append("/usr/scripts/gestion")
from email_tools import format_sender
"""
Script de déconnexion pour mail invalide
# Import de la base de données
Copyright (C) 2009 Michel Blockelet
inspiré de fiche_deconnexion.py par :
Xavier Pessoles, Étienne Chové, Vincent Bernat, Nicolas Salles
Licence : GPL v2
"""
import commands, os, sys, time
sys.path.append('/usr/scripts/gestion')
from ldap_crans import crans_ldap
db = crans_ldap()
from config import upload
# logging tools
import syslog
def log(x):
syslog.openlog('GENERATE_MAIL_INVALIDE_NOTICE')
syslog.syslog(x)
syslog.closelog()
# Détermination de l'uid du cableur
uid = os.getenv('SUDO_UID')
if not uid :
print "Impossible de déterminer l'utilisateur"
sys.exit(1)
cableur = db.search('uidNumber=%s' % os.getenv('SUDO_UID'),'w')['adherent'][0]
sys.path.append('/usr/scripts/lib')
import utils.exceptions
os.chdir("/usr/scripts/admin/mail_invalide")
SRC = "/usr/scripts/admin/src"
# Nom des fichiers
headers = SRC + "/mail_invalide_debut.tex"
texsrc = SRC + "/mail_invalide_texte.tex"
pdf = time.strftime("mail_invalide-%d-%m-%Y_%Hh%M.pdf",time.localtime(time.time()))
# Fichiers temporaires à supprimer à la fin
mailtex = "mailtmp.tex"
barcode = "barcode.eps"
# Détection d'un manquement d'argument
if len(sys.argv) == 1 :
sys.exit("Erreur: aucune adresse mail fournie")
# On prend la liste des adresses mails données en argument
adresses = sys.argv
# On vire pour celà l'appel au script
adresses.pop(0)
if len(adresses) == 1 :
text = "Bonjour\n\n \
Voici la fiche d'avertissement à remettre à l'adhérent concerné pour\n \
l'informer que l'adresse mail qu'il a fourni n'est pas valide.\n\n \
Il faut donc imprimer la feuille et la mettre dans sa boîte aux\n \
lettres.\n\n"
else :
text = "Bonjour\n\n \
Voici les fiches d'avertissement à remettre aux adhérents concernés\n \
pour les informer que l'adresse mail qu'ils ont fourni n'est pas valide.\n\n \
Il faut donc imprimer les feuilles et les mettre dans les boîtes aux\n \
lettres correspondantes.\n\n"
text += "-- \nUn script exécuté par %s\n\n" % cableur.Nom().encode('iso8859-1')
text += os.popen("/usr/games/fortune",'r').read()
os.system("cp %s %s" % (headers, mailtex))
file = open(mailtex,'r+')
file.read()
chbres = []
for adresse in adresses :
os.system("barcode -n -E -b %s%s -o %s" % (adresse,time.strftime("%Y%m%d-%H%M",time.localtime()),barcode))
data = db.search("mail=%s" % adresse,'w')
try :
adherent = data['adherent'][0]
prenom = adherent.prenom().encode('iso8859-15')
nom = adherent.nom().encode('iso8859-15')
chbre = adherent.chbre()
# L'adhérent a une adresse mail invalide
adherent.mail_invalide(True)
adherent._save()
except :
print("Erreur : l'adresse < %s > n'a pas été trouvée dans la base" % adresse)
adresses.remove(adresse)
if len(adresses) == 0 :
sys.exit("Aucune adresse valide")
continue
chbres.append(chbre)
date = time.strftime("%A %d %B %Y",time.localtime(time.time()+15*24*3600))
if adresse == adresses[0] :
file.write("\\newcommand{\prenom}{%s}\n" % prenom)
file.write("\\newcommand{\\nom}{%s}\n" % nom)
file.write("\\newcommand{\chambre}{%s}\n" % chbre)
file.write("\\newcommand{\email}{\url{%s}}\n" % adresse)
file.write("\\newcommand{\deconnexion}{%s}\n" % date)
else :
file.write("\\renewcommand{\prenom}{%s}\n" % prenom)
file.write("\\renewcommand{\\nom}{%s}\n" % nom)
file.write("\\renewcommand{\chambre}{%s}\n" % chbre)
file.write("\\renewcommand{\email}{\url{%s}}\n" % adresse)
file.write("\\renewcommand{\deconnexion}{%s}\n" % date)
tex_src = open(texsrc, 'r')
file.write(tex_src.read())
tex_src.close()
if adresse != adresses[len(adresses)-1] :
file.write('\\newpage')
else :
file.write('\end{document}')
file.close()
#os.system("latex %s" % mailtex)
os.system("latex \\\\nonstopmode\\\\input %s 1> /dev/null" % mailtex)
os.system("dvips %s 2> /dev/null" % mailtex.replace('.tex','.dvi'))
os.system("ps2pdf %s %s" % (mailtex.replace('.tex','.ps'),pdf))
import locale
locale.setlocale(locale.LC_TIME, 'fr_FR.UTF-8')
# Génération du mail avec la pièce jointe
import smtplib
help = """Script de déconnexion pour mail invalide.
Une fiche sera générée pour chaque adhérent.
Chaque adhérent sera déconnecté 2 semaines plus tard si son adresse mail
n'a pas changé.
# Here are the email pacakge modules we'll need
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart
from email.Encoders import encode_base64
Usage: mail_invalide.py [adresse mail]..."""
msg = MIMEMultipart()
msg['Subject'] = "Fiche(s) d'avertissement de mail invalide - %s" % time.strftime("%d/%m/%Y",time.localtime(time.time()))
msg['From'] = format_sender(u"%s <%s>" % (cableur.Nom(), cableur.mail()))
msg['To'] = format_sender(u"Câbleurs <respbats@crans.org>")
msg['Cc'] = format_sender(u"Disconnect Team <disconnect@crans.org>")
# msg.preamble = text
# Guarantees the message ends in a newline
# msg.epilogue = ''
fp = open(pdf, 'rb')
img = MIMEBase('application','pdf')
img.set_payload(fp.read())
fp.close()
encode_base64(img) # Ils auraient pu soigner...
img.add_header('Content-Disposition', 'attachment', filename=pdf)
text = MIMEText(text, 'plain', 'iso-8859-1')
msg.attach(text)
msg.attach(img)
def generate_ps(proprio):
"""On génère la feuille d'avertissement et on retourne son emplacement."""
barcode = "/usr/scripts/admin/mail_invalide/barcode.eps"
try:
log('Generate invalid mail notice for %s' % proprio.Nom())
# Dossier de génération du ps
dossier = '/usr/scripts/admin/mail_invalide'
while (1 == 1):
print "Mail formaté, prêt à l'envoi."
print " [Envoyer, Abandonner]"
r = sys.stdin.readline().strip()
if (r == "e" or r == "E"):
# Send the email via our own SMTP server.
s = smtplib.SMTP()
s.connect()
s.sendmail(msg['From'], (msg['To'],msg['Cc']), msg.as_string())
s.close()
print "Mail envoyé !"
break
if (r == "a" or r == "A"):
print "Abandon"
os.system("rm -f %s" % pdf)
break
# Base pour le nom du fichier
fichier = time.strftime('%Y-%m-%d-%H-%M') + '-mail-%s' % (proprio.Nom().
lower().replace(' ', '-'))
os.system("rm -f %s %s" % (mailtex.replace(".tex",".*"),barcode))
# Création du fichier tex
format_date = '%A %d %B %Y'
template = file('%s/mail_invalide.tex' % dossier).read()
template = template.replace('~prenom~', proprio.prenom().encode('utf-8'))
template = template.replace('~nom~', proprio.nom().encode('utf-8'))
template = template.replace('~chambre~', proprio.chbre().encode('utf-8'))
template = template.replace('~mail~', proprio.email().encode('utf-8'))
template = template.replace('~fin~',
time.strftime(format_date, time.localtime(time.time()+14*86400)))
file('%s/%s.tex' % (dossier, fichier), 'w').write(template)
# Compilation du fichier latex
commands.getstatusoutput('PATH="/bin:/usr/bin" cd %(dossier)s && barcode -n -E -b %(adresse)s%(date)s -o %(barcode)s && latex --interaction=nonstopmode %(base)s.tex && dvips %(base)s.dvi && rm -f %(base)s.dvi %(base)s.aux %(base)s.log %(base)s.tex %(barcode)s'%{'dossier': dossier, 'adresse': adresse, 'date': time.strftime("%Y%m%d-%H%M"), 'base': fichier, 'barcode': barcode})
return '%s/%s.ps' % (dossier, fichier)
except Exception, e:
log('Erreur lors de la génération du ps : ')
log(str(e))
log("Values : adherent:%s" % proprio.Nom())
log(utils.exceptions.formatExc())
raise e
if __name__ == "__main__":
if '--help' in sys.argv or '-h' in sys.argv or len(sys.argv) < 2:
print help
sys.exit(0)
db = crans_ldap()
a_imprimer = []
a_verifier = []
for adresse in sys.argv[1:]:
print " * Recherche de %s ..." % adresse
res = db.search("mail=%s" % adresse, 'w')['adherent']
if len(res) == 0:
print "*** Erreur : aucun résultat pour %s" % adresse
a_verifier.append(adresse)
elif len(res) > 1:
print "*** Erreur : plusieurs résultats pour %s :" % adresse
for adh in res:
print adh.Nom()
a_verifier.append(adresse)
else:
print "Génération de la fiche pour %s :" % res[0].Nom().encode('utf-8')
fiche = generate_ps(res[0])
print fiche
a_imprimer.append(fiche)
db.services_to_restart('mail_invalide_expire', ['%s$%s' % (res[0].id(), res[0].mail())], time.time()+14*86400)
if len(a_verifier) + len(a_imprimer) > 0:
print ''
print '***** Résultats *****'
if len(a_verifier) > 0:
print ' * Adresses mail à vérifier :'
print ','.join(a_verifier)
if len(a_imprimer) > 0:
print ' * Fiches à imprimer :'
for fiche in a_imprimer:
print fiche

View file

@ -0,0 +1,140 @@
\documentclass[11pt,a4paper,oneside]{article}
\usepackage{aeguill}
\usepackage{fancyhdr}
\usepackage{url}
\usepackage{vmargin}
\usepackage{ifthen}
\usepackage{pstricks}
\usepackage{multicol}
\usepackage{alltt}
\usepackage[dvips]{eso-pic,graphicx}
%\usepackage[dvips]{color}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[french]{babel}
\newboolean{mailcrans}
\setpapersize{A4}
\setmarginsrb{18mm}{14mm}{18mm}{14mm}{\headheight}{12pt}{\footheight}{20pt}
\pagestyle{fancy}
\renewcommand{\headrulewidth}{0.8pt}
\renewcommand{\footrulewidth}{0.2pt}
\lhead{\textbf{Notification d'adresse mail invalide}}
\rhead{\textbf{CR@NS}}
\cfoot{\textbf{CR@NS}}
%Define snow flakes
\newcommand{\flakepart}{%
\pspolygon(0,0)(0.5,1)(0.5,3)(1.9,4.4)(1.2,5.1)(0.5,4.4)(0.5,5.7)(-0.5,5.7)(-0.5,4.4)(-1.2,5.1)(-1.9,4.4)(-0.5,3)(-0.5,1)}
\newcommand{\snowflake}[1]{%
\psset{unit=#1}%
\multips{0}(0,0){1}{\flakepart}%
\multips{60}(0,0){1}{\flakepart}%
\multips{120}(0,0){1}{\flakepart}%
\multips{180}(0,0){1}{\flakepart}%
\multips{240}(0,0){1}{\flakepart}%
\multips{300}(0,0){1}{\flakepart}%
}
\newcommand{\multiflake}{%
\rput(0.0 ,1.6){\snowflake{0.06}}%
\rput(0.2 ,0.0){\snowflake{0.06}}%
\rput(0.5 ,0.6){\snowflake{0.04}}%
\rput(0.1 ,1 ){\snowflake{0.04}}%
\rput(0.8 ,1.4){\snowflake{0.06}}%
}
\begin{document}
{\setlength{\unitlength}{1in}
\begin{picture}(0,0)
\put(-0.3,-2.3){\includegraphics[width=3cm]{/usr/scripts/admin/src/logo.eps}}
\put(6,-3){\resizebox{1cm}{7cm}{\rotatebox{90}{\includegraphics[width=7cm]{barcode.eps}}}}
\psset{linecolor=lightgray}
\put(-0.4,-0.6){\multiflake}
\end{picture}}
\begin{center}
\begin{minipage}[c]{0.9\textwidth}
\begin{center}
\begin{tabular}[c]{c}
\hline
\vspace{0.1cm} \\
\Huge{\textbf{Notification d'adresse mail}} \\
\Huge{\textbf{invalide}}\\
\vspace{0.1cm} \\
\hline
\end{tabular}
\end{center}
\end{minipage}
\end{center}
\vspace{0.2cm}
\begin{center}
\begin{minipage}[c]{0.5\textwidth}
\textbf{Nom} \dotfill{} ~nom~ \\
\textbf{Prénom} \dotfill{} ~prenom~ \\
\textbf{Chambre} \dotfill{} ~chambre~ \\
\textbf{Email} \dotfill{} ~mail~ \\
\end{minipage}
\end{center}
\vspace{0.5cm}
\noindent\begin{center}
\noindent\fcolorbox[gray]{0}{0.85}{%
\begin{minipage}[t]{0.7\textwidth}%
\begin{center}
\large Nous t'informons que l'adresse mail que tu as fournie lors de
ton adhésion est invalide au jour d'aujourd'hui.
\end{center}
\end{minipage}}
\end{center}
\vspace{0.8cm}
Un mail a été envoyé à l'adresse mail que nous connaissons, à savoir :
~mail~\ et un message nous est revenu. Donc le message ne t'a pas été
délivré.
\vspace{0.3cm}
Dans le cadre du fonctionnement de l'association, il est nécessaire
de pouvoir joindre les adhérents par mail afin d'obtenir des réponses rapides
aux questions que peuvent se poser les membres actifs quant à ton utilisation
du réseau. D'autre part un mail est un moyen simple et rapide pour te
communiquer des informations sur l'association quand le besoin s'en fait
sentir.
\vspace{0.3cm}
Plusieurs raisons peuvent expliquer des dysfonctionnements dans la réception
du mail. On peut compter dans la liste :
\begin{itemize}
\item L'adresse email n'existe pas
\item La boîte aux lettres de destination est pleine donc le mail a été rejeté
\item Une erreur de recopie s'est produite au moment de ton inscription.
\end{itemize}
\vspace{0.3cm}
Pour corriger cela, il te faut nous indiquer une adresse mail pour laquelle
ce problème ne se posera plus.
Tu peux venir à la Kfet pour rencontrer un des nombreux membres actifs en
permanence ou bien envoyer un mail à \emph{cableurs@crans.org}.
\vspace{1cm}
\noindent\begin{center}
\noindent\fcolorbox[gray]{0}{0.85}{
\begin{minipage}[t]{0.7\textwidth}
\begin{center}
\large Dans le cas où tu ne réagirais pas avant le ~fin~, ta connexion
au réseau sera supprimée.
\end{center}
\end{minipage}}
\end{center}
\vspace{0.3cm}
\end{document}

View file

@ -199,6 +199,26 @@ class mail_ajout_droits:
traceback.print_exc()
class mail_invalide_expire:
# Passage d'un mail en invalide 2 semaines après notification
debug = True
def __init__(self, args):
self.args = args
def reconfigure(self):
cprint(u'Passage en mail invalide', 'gras')
db = crans_ldap()
for arg in self.args:
aid, old_mail = arg.split('$')
adhl = db.search("aid=%s" % aid, 'w')['adherent']
if len(adhl) > 0:
adh = adhl[0]
if adh.mail() == old_mail:
adh.mail_invalide(True)
adh.save()
class ML_ens:
debug = True

View file

@ -165,6 +165,10 @@ class rouge(base_reconfigure):
from adherents import mail_valide
self._do(mail_valide(args))
def mail_invalide_expire(self, args):
from adherents import mail_invalide_expire
self._do(mail_invalide_expire(args))
def mail_ajout_droits(self, args):
from adherents import mail_ajout_droits
self._do(mail_ajout_droits(args))
@ -242,6 +246,10 @@ class sable(base_reconfigure):
from gen_confs.squid import squid_chbre
self._do(squid_chbre())
def bl_mail_invalide(self):
from gen_confs.squid import squid_mail
self._do(squid_mail())
def blacklist_virus(self):
from gen_confs.squid import squid_virus
self._do(squid_virus())

View file

@ -57,48 +57,53 @@ class squid(gen_config) :
fic.close()
class squid_upload(squid) :
""" Genère le fichier blacklist-upload pour squid """
""" Génère le fichier blacklist-upload pour squid """
FICHIER = "/etc/squid3/blacklist_upload"
chaine = "upload"
class squid_p2p(squid) :
""" Genère le fichier blacklist-p2p pour squid """
""" Génère le fichier blacklist-p2p pour squid """
FICHIER = "/etc/squid3/blacklist_p2p"
chaine = "p2p"
class squid_autodisc_upload(squid) :
""" Genère le fichier blacklist-autodiscupload pour squid """
""" Génère le fichier blacklist-autodiscupload pour squid """
FICHIER = "/etc/squid3/blacklist_autodisc_upload"
chaine = "autodisc_upload"
class squid_autodisc_p2p(squid) :
""" Genère le fichier blacklist-autodisc-p2p pour squid """
""" Génère le fichier blacklist-autodisc-p2p pour squid """
FICHIER = "/etc/squid3/blacklist_autodisc_p2p"
chaine = "autodisc_p2p"
class squid_virus(squid) :
""" Genère le fichier blacklist-virus pour squid """
""" Génère le fichier blacklist-virus pour squid """
FICHIER = "/etc/squid3/blacklist_virus"
chaine = "virus"
class squid_warez(squid) :
""" Genère le fichier blacklist-warez pour squid """
""" Génère le fichier blacklist-warez pour squid """
FICHIER = "/etc/squid3/blacklist_warez"
chaine = "warez"
class squid_bloq(squid) :
""" Genère le fichier blacklist-bloq pour squid """
""" Génère le fichier blacklist-bloq pour squid """
FICHIER = "/etc/squid3/blacklist_bloq"
chaine = "bloq"
class squid_carte(squid) :
""" Genère le fichier blacklist-carte pour squid """
""" Génère le fichier blacklist-carte pour squid """
actif = bl_carte_et_actif
if not actif : restart_cmd = ''
FICHIER = "/etc/squid3/blacklist_carte_et"
chaine = "carteEtudiant!=%i"%ann_scol
class squid_chbre(squid) :
""" Genère le fichier blacklist-chbre pour squid """
""" Génère le fichier blacklist-chbre pour squid """
FICHIER = "/etc/squid3/blacklist_chbre"
chaine = "chbre=????"
class squid_mail(squid) :
""" Génère le fichier blacklist-mail pour squid """
FICHIER = "/etc/squid3/blacklist_mail"
chaine = "mailInvalide=TRUE&uid!=*"

View file

@ -489,7 +489,7 @@ class CransLdap:
Si new commence par '-', on supprime le service si son start
est dans le futur.
Si new commence par '--', on supprime le service de condition.
Si new commence par '--', on supprime le service sans condition.
"""
if new: new = preattr(new)[1]
@ -2032,6 +2032,9 @@ class Adherent(BaseProprietaire):
elif valeur != None:
raise ValueError, u"mail_invalide prend un booléen comme argument"
# on met à jour la blackliste sur sable
self.services_to_restart('bl_mail_invalide')
# renvoie la valeur trouvée dans la base
return bool(self._data.get('mailInvalide', []))