Script para hacer Mailing en Python
July 30, 11 by adminMucho tiempo después vuelvo a compartir algo a través de este triste Blog, justo el día antes de irme de vacaciones, y con la intención de una vez que vuelva de las mismas dedicarle un poco más de tiempo, ya que me voy haciendo mayor y los escasos 140 caracteres de twitter se me empiezan a quedar cortos.
El tema es que hace unos días me puse manos a la obra a instalar una herramienta para hacer mailing y mientras buscaba pensaba en lo fácil que sería programarlo con Python, así que después de no encontrar nada que mereciera la pena, me puse a tirar lineas y en apenas un par de horas ya lo tenía, Python es maravilloso
, así que con una sonrisa que aún dura, os dejo el código por si sirviera a alguien de ayuda en un futuro, y una buena manera de tenerlo yo siempre a mano.
Decir que el envío lo hago a través de Gmail de una cuenta legítima para evitar que sea catalogado como SPAM y el envío se hace cada 5 segundos para evitar que Gmail nos bloquee. Así que no está preparado para enviar grandes volúmenes.
init.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | #!/usr/bin/python #Script for Mailing import sqlite3 import urllib import smtplib import sys import time from GmailMail import GmailMail def initDb(): conn = sqlite3.connect('db.sqlite') c = conn.cursor() # Drop and Create table try: c.execute('''DROP table user''') except: print "No existe tabla user previamente" c.execute('''create table user (id integer, name text, surname text, email text, send integer)''') # Insert a row of data fd = open("datos.txt") i=0 for line in fd: datos = line.split("\t") c.execute("insert into user values ("+str(i)+", '" + datos[0]+ "' , '" + datos[1] + "', '" + datos[2] +"',0)") conn.commit() print str(i) + ": " + datos[0] + " " + datos[2] i = i+1 fd.close() conn.close() def connDB(): return sqlite3.connect('db.sqlite') def closeDB(conn): conn.close() def getAllDB(conn): c = conn.cursor() c.execute('''select * from user WHERE send=0''') arr = c return arr def updateRegister(id,conn): c = conn.cursor() c.execute("UPDATE user SET send=1 WHERE id="+str(id)) conn.commit() def composeContent(): f = open("email.txt") content=f.read().decode("utf8") f.close() return content def sendDB(subject, content, search): conn = connDB() try: m = GmailMail("usuario@gmail.com", "password") except: print "Error SMTP", sys.exc_info() raise c=getAllDB(conn) for row in c: print "Durmiendo cinco segundo para no saturar Gmail" time.sleep(5) try: content=composeContent() email=row[3] content = content.replace(search, row[1]) m.send(email, subject, content) updateRegister(row[0], conn) print str(row[0]) + " Enviado email a " + row[1] + " email : " + email except: print "Error id: " + str(row[0]), sys.exc_info() closeDB(conn) if __name__ == '__main__': if sys.argv[1]=="initDb": initDb() if sys.argv[1]=="run": subject=u"Asunto del email" search="$nombre" sendDB(subject, "", search) else: print """ [+] initDb: Vuelca el contenido del fichero datos.txt a db.sqlite [+] run: Empieza el envio de mailing """ |
datos.txt
nombre1 ape1 email
nombre2 ape2 email
email.txt
Estimado $nombre:
bla bla bla
bla bla bla
bla bla blas
GmailMail.py, por no complicarme con la codificación al final opté por esta clase que robé de internet.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | #!/usr/bin/env python # requires Python >= 2.5 import smtplib from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase from email.mime.text import MIMEText from email.mime.audio import MIMEAudio from email.mime.image import MIMEImage from email.encoders import encode_base64 from mimetypes import guess_type from os.path import basename class GmailMail(): def __init__(self, gmail_user, gmail_pwd): """ Prepares an instance with basic authentication """ self.gmail_user = gmail_user self.gmail_pwd = gmail_pwd def getAttachment(self, path, charset='ASCII'): contentType, encoding = guess_type(path) if contentType is None or encoding is not None: contentType = 'application/octet-stream' mainType, subType = contentType.split('/', 1) _file = open(path, 'rb') if mainType == 'text': attachment = MIMEText(_file.read(), subType, charset) elif mainType == 'message': attachment = email.message_from_file(_file) elif mainType == 'image': attachment = MIMEImage(_file.read(), _subType=subType) elif mainType == 'audio': attachment = MIMEAudio(_file.read(), _subType=subType) else: attachment = MIMEBase(mainType, subType) attachment.set_payload(_file.read()) encode_base64(attachment) _file.close() attachment.add_header('Content-Disposition', 'attachment', filename=basename(path)) return attachment def send(self, to, subject, text=u"", html=None, attachments=None, charset="iso-8859-15"): """ Sends an email through Gmail using the authentication given to this instance. If given, attachments must be a list of paths pointing to the files we want to include. This script does not embed inline content (multipart/related) """ if charset in ['utf8','utf-8']: #bug? from email.charset import add_charset, SHORTEST add_charset('utf-8', SHORTEST, None, None) if isinstance(text, unicode): text = text.encode(charset, 'replace') if isinstance(html, unicode): html = html.encode(charset, 'replace') if attachments is None: attachments = [] if text: plain_part = MIMEText(text, 'plain', charset) if html: html_part = MIMEText(html, 'html', charset) is_alternative = html and text layers = [] if attachments or is_alternative: msg = MIMEMultipart() #mixed msg.set_charset(charset) msg.preamble = 'This is a multi-part message in MIME format.' msg.epilogue = '' layers.append(msg) if is_alternative: msgAlternative = MIMEMultipart('alternative') msg.attach(msgAlternative) layers.append(msgAlternative) if text: layers[-1].attach(plain_part) if html: layers[-1].attach(html_part) elif text: msg = plain_part else: #html only msg = html_part for path in attachments: msg.attach(self.getAttachment(path, charset)) msg['From'] = self.gmail_user msg['To'] = to msg['Subject'] = subject mailServer = smtplib.SMTP("smtp.gmail.com", 587) mailServer.ehlo() mailServer.starttls() mailServer.ehlo() mailServer.login(self.gmail_user, self.gmail_pwd) mailServer.sendmail(self.gmail_user, to, msg.as_string()) # Should be mailServer.quit(), but that crashes... mailServer.close() |

