diff --git a/admin/mail_invalide/mail_invalide.py b/admin/mail_invalide/mail_invalide.py old mode 100644 new mode 100755 index b14f3037..ee93d39c --- a/admin/mail_invalide/mail_invalide.py +++ b/admin/mail_invalide/mail_invalide.py @@ -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 - -# 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 - -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 ") -msg['Cc'] = format_sender(u"Disconnect Team ") -# msg.preamble = text -# Guarantees the message ends in a newline -# msg.epilogue = '' +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é. -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) +Usage: mail_invalide.py [adresse mail]...""" -text = MIMEText(text, 'plain', 'iso-8859-1') -msg.attach(text) -msg.attach(img) -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 -os.system("rm -f %s %s" % (mailtex.replace(".tex",".*"),barcode)) +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' + + # Base pour le nom du fichier + fichier = time.strftime('%Y-%m-%d-%H-%M') + '-mail-%s' % (proprio.Nom(). + lower().replace(' ', '-')) + + # 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 diff --git a/admin/mail_invalide/mail_invalide.tex b/admin/mail_invalide/mail_invalide.tex new file mode 100644 index 00000000..72e83ab6 --- /dev/null +++ b/admin/mail_invalide/mail_invalide.tex @@ -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} diff --git a/gestion/gen_confs/adherents.py b/gestion/gen_confs/adherents.py index 66caa319..c6a48a23 100644 --- a/gestion/gen_confs/adherents.py +++ b/gestion/gen_confs/adherents.py @@ -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 diff --git a/gestion/gen_confs/generate.py b/gestion/gen_confs/generate.py index db838c89..134684e4 100644 --- a/gestion/gen_confs/generate.py +++ b/gestion/gen_confs/generate.py @@ -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()) diff --git a/gestion/gen_confs/squid.py b/gestion/gen_confs/squid.py index 2f782b49..59a0f2b3 100644 --- a/gestion/gen_confs/squid.py +++ b/gestion/gen_confs/squid.py @@ -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!=*" diff --git a/gestion/ldap_crans.py b/gestion/ldap_crans.py index a69f6259..0163e8f1 100644 --- a/gestion/ldap_crans.py +++ b/gestion/ldap_crans.py @@ -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', []))