[Tutor] Program review

Ricardo Aráoz ricaraoz at gmail.com
Sat Jan 5 20:17:48 CET 2008


Ok, here is a corrected new version, I hope.

Kent, the fact that Mensaje.__init__ reads the message configuration is
by design (it's a feature, not a bug ;c) ). The class is meant to be
instantiated for using only once and with only one configuration and one
message so including the configuration in the __init__ method kind of
stresses that fact. What's more, I've been thinking of reading both
files in the __init__ method so that the object is created ready to do
it's intended job. Anyway, I guess it's a matter of personal taste in
this case.

Here's the code :

#!/usr/bin/env python

import time
import smtplib
import email
import ConfigParser
import logging

class Mensaje(object) :
    def __init__(self) :
        cfg = ConfigParser.ConfigParser()
        try :
            cfg.readfp(open('config.cfg'))
        except Exception, e :
            logging.error('No pude leer "config.cfg" : %s', e.strerror)

        self.direcciones = cfg.get('Archivos', 'Direcciones')
        self.excluidas = cfg.get('Archivos', 'Excluir')
        self.cuantos = cfg.getint('Correo', 'MailsPorVez')
        self.intervalo = cfg.getint('Correo', 'IntervaloEnSegundos')

        try :
            htmlFile = open(cfg.get('Archivos', 'Mensaje'))
            self.html = htmlFile.read()
            htmlFile.close()
        except Exception, e :
            logging.error('No pude leer "%s" : %s',
                            cfg.get('Archivos', 'Mensaje'),
                            e.strerror)

        self.De = cfg.get('Encabezados', 'De')
        self.Para = ''
        self.Encabezado = cfg.get('Encabezados', 'Encabezado')
        self.ResponderA = cfg.get('Encabezados', 'ResponderA')
        self.Servidor = cfg.get('Correo', 'Servidor')
        self.Usuario = cfg.get('Correo', 'Usuario')
        self.Contra = cfg.get('Correo', 'Contrasenia')

class Correo(object) :
    def __init__(self, mensaje) :
        self.messg = email.MIMEMultipart.MIMEMultipart()
        self.messg['From'] = mensaje.De
        self.messg['To'] = mensaje.Para
        self.messg['Subject'] = mensaje.Encabezado
        self.messg['Reply-To'] = mensaje.ResponderA
        self.messg.preamble = 'This is a multi-part message in MIME format'
        self.messg.attach(email.MIMEText.MIMEText(mensaje.html, 'html'))

        self.Servidor = mensaje.Servidor
        self.Conexion = smtplib.SMTP()
        self.Usuario = mensaje.Usuario
        self.Contra = mensaje.Contra

    def connect(self) :
        try :
            self.Conexion.connect(self.Servidor)
            self.Conexion.set_debuglevel(False)
            self.Conexion.ehlo()
            self.Conexion.starttls()
            self.Conexion.ehlo()
            self.Conexion.login(self.Usuario, self.Contra)
            return True
        except :
            logging.error('No me pude conectar al Servidor')
            return False

    def disconnect(self) :
        self.Conexion.close()

    def enviar(self, addr) :
        self.messg.replace_header('To', addr)
        try :
            self.Conexion.sendmail(self.messg['From'],
                                    self.messg['To'],
                                    self.messg.as_string())
            logging.info('Enviado a : %s', self.messg['To'])
        except SMTPRecipientsRefused :
            logging.error('El destinatario fue rechazado por el servidor')
        except SMTPHeloError :
            logging.error('El servidor no respondio apropiadamente')
        except SMTPSenderRefused :
            logging.error('El From: fue rechazado por el servidor')
        except SMTPDataError :
            logging.error('El servidor respondio con un error desconocido')

def procesar(mensaje):
    try :
        try :
            fIncl = open(mensaje.direcciones)
        except Exception, e :
            logging.error('Error!!! No pude abrir "%s" : %s',
                            mensaje.direcciones,
                            e.strerror)
            raise
        try :
            fExcl = open(mensaje.excluidas)
        except Exception, e :
            logging.error('No pude abrir "%s" : %s',
                            mensaje.excluidas,
                            e.strerror)
            fIncl.close()
            raise
    except : pass
    else :
        mails = enumerate(
                        set(addr.strip() for addr in fIncl)
                        - set(excl.strip() for excl in fExcl))
        fIncl.close()
        fExcl.close()
        miCorreo = Correo(mensaje)
        miCorreo.connect()
        empiezo = time.clock()
        for nro, addr in mails :
            if nro%mensaje.cuantos == 0 and nro > 0 :
                miCorreo.disconnect()
                time.sleep(mensaje.intervalo - (time.clock() - empiezo))
                if not miCorreo.connect() :
                    logging.info('Terminando')
                    return
                empiezo = time.clock()
            miCorreo.enviar(addr)
        miCorreo.disconnect()


if __name__ == '__main__' :
    logging.basicConfig(level=logging.INFO,
                        format='%(asctime)s %(levelname)-8s %(message)s',
                        datefmt='%a, %d %b %Y %H:%M:%S',

filename=time.strftime('informe-%Y-%m-%d-%H-%M-%S.log'),
                        filemode='w')
    procesar(Mensaje())
--------------------------------------------------------------------------------------------


More information about the Tutor mailing list