Factorisation. Preparation de l'envoi des mails.

darcs-hash:20060507164909-68412-59836281afda0c54b73d318d9318e071a0b52246.gz
This commit is contained in:
glondu 2006-05-07 18:49:09 +02:00
parent 89d16d3eb5
commit 018f2d59c4

View file

@ -2,7 +2,7 @@
# -*- coding: iso-8859-15 -*-
"""
Repère les comptes inactifs en parsant les logs de derniere connexion
Repère les comptes inactifs en parsant les logs de dernière connexion
de sshd et dovecot.
"""
@ -13,19 +13,37 @@ de sshd et dovecot.
import sys, os, sre, time, cPickle
from time import mktime, time, localtime, strptime, strftime
from socket import gethostname
from smtplib import SMTP
host = gethostname()
mail_address = u'disconnect@crans.org'
mail_sender = u"Comptes inactifs <disconnect@crans.org>"
template_path = '/usr/scripts/templates/comptes_inactifs.%d'
sys.path.append('/usr/scripts/gestion')
from affich_tools import tableau
from email_tools import send_email
from email_tools import send_email, parse_mail_template
from ldap_crans import crans_ldap
from config import ann_scol
db = crans_ldap()
def nb_mails_non_lus(login):
"""
Renvoie le nombre de mails non lus de login, ou None si impossible à
déterminer.
"""
try:
maildir = '/var/mail/%s/new' % login
if os.path.isdir(maildir):
return len(os.listdir(maildir))
else:
return 0
except:
# Arrive quand le script n'a pas les bons droits pour lire /var/mail
return None
class ComptesInactifs:
re = sre.compile(r'^(\w+\s+\d+\s+\d+:\d+:\d+).*(?:'
r'dovecot.*Login: user=<|'
@ -49,7 +67,7 @@ class ComptesInactifs:
f.write('%s %d\n' % (host, os.getpid()))
f.close()
# A partir de la, on a le lock
# À partir de là, on a le lock
if os.path.isfile(filename):
self.dic = cPickle.load(file(filename))
else:
@ -62,22 +80,22 @@ class ComptesInactifs:
def update(self, login, timestamp):
"""
Met a jour l'entree correspondant au login donnee, ainsi que
l'entree '!', qui correspond a la plus vieille entree.
Met à jour l'entrée correspondant au login donné, ainsi que
l'entrée '!', qui correspond à la plus vieille entrée.
"""
dic = self.dic
timestamp = int(timestamp)
# Mise a jour de l'entree la plus vieille
# Mise à jour de l'entrée la plus vieille
if not dic.has_key('!') or timestamp < dic['!']:
dic['!'] = timestamp
# Mise a jour de l'entree correspondant au login
# Mise à jour de l'entrée correspondant au login
if not dic.has_key(login) or timestamp > dic[login]:
dic[login] = timestamp
def update_from_syslog(self, loglines):
""" Met a jour le dico avec les lignes de syslog donnees """
""" Met à jour le dico avec les lignes de syslog données """
annee = localtime(time())[0]
now = time() + 600
nombre = 0
@ -95,9 +113,9 @@ class ComptesInactifs:
print '%d ligne(s) pertinente(s)' % nombre
def do_log(self):
""" Lit des lignes de log sur l'entree std et met a jour le dico """
""" Lit des lignes de log sur l'entrée std et met à jour le dico """
self.update_from_syslog(sys.stdin)
print 'Lecture des logs terminee'
print 'Lecture des logs terminée'
def do_dump(self):
""" Affiche le contenu du dico """
@ -110,18 +128,28 @@ class ComptesInactifs:
def get_idle_accounts(self, since=32*24*3600):
"""
Renvoie la liste de ceux qui ne se sont pas connectes depuis
since secondes, par defaut un mois (32 jours, pour etre sur).
Renvoie la liste des couples (login, objet Adherent) de ceux qui
ne se sont pas connectés depuis since secondes, par défaut un mois
(32 jours, pour etre sûr).
"""
oldest = self.dic.get('!', int(time()))
limit = int(time()) - since
liste = [a
for a in os.listdir('/home')
if os.path.isdir('/var/mail/' + a)
and self.dic.get(a, oldest) < limit]
liste = []
for x in os.listdir('/home'):
if os.path.isdir('/var/mail/' + x) and self.dic.get(x, oldest) < limit:
a = db.search('uid=%s' % x)['adherent']
if a:
liste.append((x, a[0]))
else:
print 'uid=%s introuvable' % x
liste.sort()
return liste
def do_summary(self):
"""
Envoie à disconnect un résume des comptes inactifs depuis plus d'un
mois.
"""
modele = u"""*Membres inscrits ne s'étant pas connectés depuis plus d'un mois*
%(inscrits)s
@ -141,32 +169,18 @@ L'analyse des logs remonte au %(oldest)s.
--
comptes_inactifs.py
"""
liste = []
for x in self.get_idle_accounts():
a = db.search('uid=%s' % x)['adherent']
if a:
liste.append((x, a[0]))
else:
print 'uid=%s introuvable' % x
liste.sort()
inscrits = []
anciens = []
for (x, a) in liste:
for (x, a) in self.get_idle_accounts():
date = self.dic.get(x)
if date:
date = strftime(u'%d/%m/%Y %H:%M', localtime(date))
else:
date = u'Jamais'
forward = os.path.isfile('/home/%s/.forward' % x) and u'X' or u''
try:
maildir = '/var/mail/%s/new' % x
mail = os.path.isdir(maildir) and os.listdir(maildir) and u'X' or u''
except:
# Arrive quand le script n'a pas les bons droits pour lire
# /var/mail
mail = u'?'
mail = nb_mails_non_lus(x)
mail = mail == None and u'?' or mail > 0 and u'X' or u' '
ligne = (a.id(), x, a.Nom(), date, forward, mail)
if ann_scol in a.paiement():
inscrits.append(ligne)
@ -189,6 +203,22 @@ comptes_inactifs.py
u'Comptes inactifs',
modele % locals())
def do_spam(self):
""" Envoie un mail explicatif aux possesseurs de compte inactif """
# Nombre de personnes concernées, en expansant de droite à gauche :
# inscrit/ancien, avec/sans procmail, avec/sans mail non lu
# Voir aussi template_path
stats = [0, 0, 0, 0, 0, 0, 0, 0]
# On factorise la connexion
smtp = SMTP()
smtp.connect()
for (x, a) in self.get_idle_accounts():
pass
smtp.quit()
if __name__ == '__main__':
args = sys.argv[1:]
@ -199,7 +229,7 @@ if __name__ == '__main__':
commande = args[0]
if commande not in ('log', 'dump', 'summary'):
sys.stderr.write("Commande incorrecte : %s\n" % args[1])
sys.stderr.write("Commande incorrecte : %s\n" % commande)
sys.exit(1)
ci_db = ComptesInactifs('/usr/scripts/var/comptes_inactifs.dict')