Spiga

Script para hacer Mailing en Python

July 30, 11 by admin

Mucho 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 :D , 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()

This entry no have comments... but you can be first.

Leave a Reply

Add Music To Your Comment

Clear All

Selected Songs (0):