[Tutor] Program review

Ricardo Aráoz ricaraoz at gmail.com
Sat Jan 5 00:47:01 CET 2008


Considering we are reviewing programs I'd like to submit one of mine and
I would be thankful for any critic/improvement you can suggest.
My ex needs to send mails to a long list of customers, problem is that
she can not send more than 70 every 10 minutes or her ISP will consider
her a spammer. So she spends hours sending these mails one by one.
This program was meant to help her with that. It takes a configuration
file which tells the program the name of a text file with an email
address per line for mail to be sent to, the name of another text file
with addresses to be ignored, and the name of an HTML file with the
message to be sent. Also how many messages every how many seconds to be
sent.

Procesar.py
-----------

#!/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(addr.strip() for addr in fIncl
                    if addr.strip() not in (excl.strip() for excl in fExcl))
        empiezo = time.clock()
        miCorreo = Correo(mensaje)
        miCorreo.connect()
        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()
        fIncl.close()
        fExcl.close()


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

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

----------------------------------------------------------------------------------------

config.cfg
----------

[Archivos]
; En Direcciones va el nombre del archivo de texto
;     que contiene las direcciones de mail una por renglon
; En Excluir va el nombre del archivo de texto
;     que contiene las direcciones a las que NO se les manda
;     mail, una por renglon
; En mensaje va el nombre del archivo html con el mensaje.
;     El mensaje lo creas en tu programa de mail y le das
;     "guardar como..." y lo guardas como "html"

Direcciones = mails.txt
Excluir = excluir.txt
Mensaje = mensaje.html


[Encabezados]

De = xxx at yyyyyyy.com
Encabezado = Prueba de Procesar
ResponderA = bbbbbbb at fffffff.com


[Correo]

Servidor = smtp.servidor.com
Usuario = nombreUsuario
Contrasenia = contrasenia

MailsPorVez = 10
IntervaloEnSegundos = 120

-------------------------------------------------------------------

TIA




More information about the Tutor mailing list