Cómo enviar correos electrónicos con Gmail usando Python

Hay bastantes formas de enviar correo electrónico con Python, ya sea a través de una biblioteca de terceros como con boto y SES, o a través de un protocolo de correo electrónico como SMTP....

Hay bastantes formas de enviar correo electrónico con Python, ya sea a través de una biblioteca de terceros como con Boto y SES, o a través de un protocolo de correo electrónico como SMTP. Si bien el tema del uso de Python para enviar correos electrónicos puede parecer que se ha hecho hasta el cansancio, hay tantas formas diferentes de hacerlo y tantos problemas que pueden surgir. Pensé que sería útil escribir un tutorial sobre cómo enviar correos electrónicos con Gmail como proveedor usando Python.

El protocolo SMTP

Puede que esto no sea una sorpresa, pero, por supuesto, Python ya tiene una biblioteca que te permite conectarte a un servidor SMTP, como el que usa Gmail. Esta biblioteca se llama, como era de esperar, smtplib y viene incluida con Python.

SMTP (Protocolo simple de transferencia de correo) es un protocolo de nivel de aplicación (además de TCP) que se utiliza para comunicarse con servidores de correo de servicios externos, como un cliente de correo electrónico en su teléfono. SMTP es solo un protocolo de entrega, por lo que en realidad no puede recuperar correo electrónico con él, solo puede enviar correo electrónico, que es en lo que nos centraremos en este artículo. Si desea recuperar el correo electrónico en su lugar, querrá consultar el protocolo [IMAP] (https://en.wikipedia.org/wiki/Internet_Message_Access_Protocol) (Protocolo de acceso a mensajes de Internet).

Debo señalar que muchos servicios de correo electrónico, como Gmail, no suelen utilizar SMTP en sus servidores de correo internos. Por lo general, SMTP solo se proporciona como una interfaz externa para su servicio a través del servidor smtp.gmail.com. Esto está destinado principalmente a ser utilizado por clientes de correo electrónico en su teléfono o computadora (como Outlook, Thunderbird, etc.).

Abriendo la conexión

Como ya se mencionó, Python viene convenientemente con smtplib, que maneja todas las diferentes partes del protocolo, como la conexión, la autenticación, la validación y, por supuesto, el envío de correos electrónicos.

Usando esta biblioteca, hay algunas formas diferentes de crear una conexión con su servidor de correo. En esta sección, nos centraremos en crear una conexión simple e insegura (que rara vez, o nunca, debe usarse). Esta conexión no está encriptada y su valor predeterminado es el puerto 25. Sin embargo, el protocolo para el envío de correo en realidad usa el 587, que es el que usaremos.

Estas conexiones son realmente sencillas de crear con smtplib. La versión sin cifrar se puede crear con:

1
2
3
4
5
6
7
import smtplib

try:
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.ehlo()
except:
    print 'Something went wrong...'

Y eso es. Realmente no hay mucho más que pasar la dirección del servidor, el puerto y llamar a .helo(), que lo identifica en el servidor SMTP. Con este objeto servidor ahora puede enviar correos electrónicos a través de una conexión no segura.

Nota: es posible que aún no esté listo para enviar correos electrónicos. Gmail impone algunas restricciones a las conexiones SMTP como esta. Consulte la sección "Autenticación con Gmail" a continuación para obtener más información.

Uso de una conexión segura

Cuando una conexión SMTP está protegida a través de TLS/SSL, se realiza a través del puerto 465 y normalmente se denomina SMTPS. No hace falta decir que siempre debe usar una conexión segura.

Hay algunas formas diferentes de proteger sus conexiones SMTP en la biblioteca smtplib. La primera forma es crear primero una conexión insegura y luego actualizar a TLS. Esto se hace usando el método .starttls().

1
2
3
4
5
6
7
8
9
import smtplib

try:
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.ehlo()
    server.starttls()
    # ...send emails
except:
    print 'Something went wrong...'

Tenga en cuenta que si bien esto es muy similar a la conexión insegura anterior que creamos, todo lo que es diferente es que estamos usando el método .starttls() para actualizar la conexión a segura.

Su otra opción es crear una conexión SSL desde el principio. En este caso, querrá usar el método .SMTP_SSL() en su lugar:

1
2
3
4
5
6
7
8
import smtplib

try:
    server_ssl = smtplib.SMTP_SSL('smtp.gmail.com', 465)
    server_ssl.ehlo()   # optional
    # ...send emails
except:
    print 'Something went wrong...'

Entre otras pequeñas diferencias, usamos el puerto SMTPS (465) de inmediato, aunque puede dejar el parámetro del puerto fuera de esto y smtplib se establecerá de forma predeterminada en 465 de todos modos.

Ahora que tenemos nuestra conexión, vamos a crear un correo electrónico.

Creando el correo electrónico

Los correos electrónicos, en esencia, son solo cadenas de texto conectadas por caracteres de nueva línea. La mayoría de los correos electrónicos tendrán al menos los campos "De", "Para", "Asunto" y un cuerpo. Aquí hay un ejemplo simple:

1
2
3
4
5
6
7
From: [correo electrónico protegido]
To: [correo electrónico protegido], [correo electrónico protegido]
Subject: OMG Super Important Message

Hey, what's up?

- You

Como puede ver, cada línea contiene un nuevo campo con sus datos. Sin protocolo binario, sin XML, sin JSON, solo cadenas separadas por líneas.

Una forma sencilla de parametrizar estos campos es usar formato de cadena en Python:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
sent_from = '[correo electrónico protegido]'
to = ['[correo electrónico protegido]', '[correo electrónico protegido]']
subject = 'OMG Super Important Message'
body = 'Hey, what's up?\n\n- You'

email_text = """\
From: %s
To: %s
Subject: %s

%s
""" % (sent_from, ", ".join(to), subject, body)

Ahora todo lo que tiene que hacer es pasar la cadena email_text a smtplib, que mostraremos en la siguiente sección, y estará listo para comenzar.

Autenticación con Gmail

Hay algunos pasos que debe seguir antes de poder enviar correos electrónicos a través de Gmail con SMTP, y tiene que ver con la autenticación. Si utiliza Gmail como proveedor, deberá indicarle a Google que le permita conectarse a través de SMTP, que se considera un método "menos seguro".

Realmente no puede culpar a Google por configurarlo de esta manera, ya que su aplicación (o alguna otra aplicación de terceros) necesitará tener su contraseña de texto sin formato para que esto funcione, lo que definitivamente no es lo ideal. No es como el protocolo OAuth donde se emite un token revocable, por lo que tienen que encontrar otra forma de garantizar que ninguna parte no autorizada acceda a sus datos.

Para muchos otros proveedores de correo electrónico, no necesitará realizar ninguno de los pasos adicionales que describo aquí.

Primero, querrá permitir que aplicaciones menos seguras accedan a su cuenta. Para obtener instrucciones detalladas sobre cómo hacer esto, debe consultar esta página:

Permitir que aplicaciones menos seguras accedan a su cuenta

Si tiene habilitada la verificación en dos pasos en su cuenta, deberá crear una contraseña específica de la aplicación para aplicaciones menos seguras como esta. En ese caso, deberá seguir las instrucciones aquí:

Inicie sesión con las contraseñas de la aplicación

Y finalmente, si todavía obtienes un SMTPAuthenticationError con un código de error de 534, entonces necesitarás hacer otro paso más para que esto funcione.

Captcha de desbloqueo de pantalla

No he tenido que hacer este último paso para mis propias cuentas, pero he leído que en realidad no funciona de inmediato. Aparentemente, después de habilitar aplicaciones menos seguras, es posible que deba esperar unos minutos antes de probar el enlace 'Mostrar Desbloquear Captcha'. Si se encuentra con este problema y encuentra una buena manera de solucionarlo, ¡háganoslo saber en los comentarios!

En cuanto al código real de Python, todo lo que necesita hacer es llamar al método login:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
import smtplib

gmail_user = '[correo electrónico protegido]'
gmail_password = '[correo electrónico protegido]!'

try:
    server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
    server.ehlo()
    server.login(gmail_user, gmail_password)
except:
    print 'Something went wrong...'

Envío del correo electrónico

Ahora que tiene su conexión SMTP configurada y autorizó su aplicación con Google, finalmente puede usar Python para enviar correos electrónicos con Gmail.

Usando la cadena de correo electrónico que construimos arriba, y el objeto servidor conectado/autenticado, necesitas llamar al método .sendmail(). Aquí está el código completo, incluidos los métodos para cerrar la conexión:

 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
import smtplib

gmail_user = '[correo electrónico protegido]'
gmail_password = '[correo electrónico protegido]!'

sent_from = gmail_user
to = ['[correo electrónico protegido]', '[correo electrónico protegido]']
subject = 'OMG Super Important Message'
body = 'Hey, what's up?\n\n- You'

email_text = """\
From: %s
To: %s
Subject: %s

%s
""" % (sent_from, ", ".join(to), subject, body)

try:
    server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
    server.ehlo()
    server.login(gmail_user, gmail_password)
    server.sendmail(sent_from, to, email_text)
    server.close()

    print 'Email sent!'
except:
    print 'Something went wrong...'

Conclusión

Además de los pasos de autorización específicos de Gmail (que involucran aplicaciones menos seguras, etc.), este código debería funcionar para casi cualquier otro proveedor de correo electrónico que admita el acceso SMTP, suponiendo que tenga la dirección del servidor y el puerto correctos. Si encuentra que otros proveedores imponen restricciones especiales en el acceso SMTP como lo hace Google, ¡háganoslo saber! Nos gustaría incluir tanta información como sea posible aquí.

¿Envía correos electrónicos mediante programación con SMTP? ¿Para qué tipo de aplicaciones lo usas? ¡Cuéntanos en los comentarios!

Recursos

Editar: Gracias a cropr (en los comentarios) por señalar que Gmail impone una serie de restricciones a las personas que envían correo electrónico con SMTP. Las cuentas gratuitas están limitadas a 500 correos electrónicos por día y tienen un límite de velocidad de aproximadamente 20 correos electrónicos por segundo.

Si cree que superará estos límites, puede configurar su propio servidor SMTP o utilizar servicios como AWS SES o Sendgrid.