Versión: 2.x, 3.x
(Hay una versión más completa y actualizada de este mismo artículo para Python 3.6 o superior: Enviar correo electrónico en HTML y con adjuntos vía SMTP).
De forma estándar Python permite enviar correos electrónicos fácilmente haciendo uso de los módulos email y smtplib. El primero es empleado para construir el mensaje, mientras que el segundo para conectar con el servidor y enviarlo.
Existen otras soluciones, tal vez algo más simples pero no se incluyen en la librería estándar, como pyzmail, aunque no están cubiertas en este artículo.
Para comenzar, importemos las clases necesarias:
from email.mime.text import MIMEText
Los mensajes utilizan el estándar MIME, por lo tanto, empleamos la clase MIMEText
para construir un correo de texto plano.
from smtplib import SMTP
La clase SMTP
representa una conexión a un servidor SMTP.
A continuación especificamos nuestra dirección de correo electrónico, el destino y el mismo mensaje.
from_address = "contacto@recursospython.com" # Dirección personal to_address = "articulos@recursospython.com" # Destino message = "Hello, world!" # Mensaje
Implementamos una instancia de la clase MIMEText
para construir el mensaje.
mime_message = MIMEText(message, "plain") mime_message["From"] = from_address mime_message["To"] = to_address mime_message["Subject"] = "Correo de prueba" # Asunto
En caso que message
contenga carácteres unicode, considera especificar la codificación:
mime_message = MIMEText(message, "plain", _charset="utf-8")
La información del remitente y el destinatario, en este caso, puede también ser un nombre o cualquier otra cadena.
mime_message["From"] = "Contacto - Recursos Python" mime_message["To"] = "Articulos - Recursos Python"
Puedes modificar el aspecto visual del mensaje utilizando HTML:
message = "<em>Hello</em>, <strong>world</strong>!" # ... mime_message = MIMEText(message, "html", _charset="utf-8")
También puedes enviar aplicaciones, imágenes y audios, utilizando las clases MIMEApplication
, MIMEImage
, y MIMEAudio
, respectivamente. Por ejemplo:
f = open("image.jpg", "rb") image = f.read() f.close() mime_message = MIMEImage(image)
Una vez elaborado el mensaje, debemos realizar la conexión al servidor SMTP.
smtp = SMTP("mail.recursospython.com")
En mi caso utilizo la dirección del servidor que me brinda mi proveedor de hosting. En el caso de los servicios más importantes, las direcciones son: smtp.live.com (Outlook / Hotmail), smtp.mail.yahoo.com (Yahoo!) y smtp.gmail.com (Gmail).
Ingresamos los datos para la autenticación, nombre de usuario (generalmente la dirección de correo electrónico) y contraseña.
smtp.login(from_address, "clave")
Por último, enviamos el correo:
smtp.sendmail(from_address, to_address, mime_message.as_string())
Y cerramos la conexión:
smtp.quit()
Código completo:
#!/usr/bin/env python # -*- coding: utf-8 -*- from email.mime.text import MIMEText from smtplib import SMTP def main(): from_address = "remitente@ejemplo.com" to_address = "destino@ejemplo.com" message = "Hello, world!" mime_message = MIMEText(message, "plain") mime_message["From"] = from_address mime_message["To"] = to_address mime_message["Subject"] = "Correo de prueba" smtp = SMTP("smtp.ejemplo.com") smtp.login(from_address, "clave") smtp.sendmail(from_address, to_address, mime_message.as_string()) smtp.quit() if __name__ == "__main__": main()
Curso online 👨💻
¡Ya lanzamos el curso oficial de Recursos Python en Udemy!
Un curso moderno para aprender Python desde cero con programación orientada a objetos, SQL y tkinter
en 2024.
Consultoría 💡
Ofrecemos servicios profesionales de desarrollo y capacitación en Python a personas y empresas. Consultanos por tu proyecto.
Arturo says:
Muy buen aporte, sin embargo a mi me arroja un error:
socket.gaierror: [Errno -5] No address associated with hostname
Será porque utilizo un servidor proxy?
Gracias
Recursos Python says:
Hola Arturo. Te invito a que pases por el foro y nos muestres tu código.
Saludos
Arturo says:
Muchas gracias, este es mi código y estoy utilizando la versión 2.7
# envia_correo.py
# ———————————————————
from email.mime.text import MIMEText
from smtplib import SMTP
def manda_correo(nombre, direccion):
from_address = «brunoruizv@gmail.com»
to_address = direccion
message = «Hola » + nombre +», \n\n» + \
«Este correo es solo para saludarte.» + \
«\n\nAtentamente,» + \
«\n\nTu funcion que manda correos desde Python.»
mime_message = MIMEText(message, «plain»)
mime_message[«From»] = from_address
mime_message[«To»] = to_address
mime_message[«Subject»] = «Saludos » + nombre
smtp = SMTP(«smtp.gmail.com», 587)
smtp.login(from_address, «texicano04»)
smtp.sendmail(from_address, to_address, mime_message.as_string())
smtp.quit()
manda_correo(«Bruno»,»brunoruizv@gmail.com»)
Y marca lo siguiente :
Traceback (most recent call last):
File «correo_3.py», line 27, in
manda_correo(«Bruno»,»arturo.ruiz02@cfe.gob.mx»)
File «correo_3.py», line 22, in manda_correo
smtp = SMTP(«smtp.cfe.gob.mx», 587)
File «/usr/local/lib/python2.7/smtplib.py», line 256, in __init__
(code, msg) = self.connect(host, port)
File «/usr/local/lib/python2.7/smtplib.py», line 316, in connect
self.sock = self._get_socket(host, port, self.timeout)
File «/usr/local/lib/python2.7/smtplib.py», line 291, in _get_socket
return socket.create_connection((host, port), timeout)
File «/usr/local/lib/python2.7/socket.py», line 557, in create_connection
for res in getaddrinfo(host, port, 0, SOCK_STREAM):
socket.gaierror: [Errno -5] No address associated with hostname
Gracias de nuevo.
Saul says:
Hola, he logrado enviar un correo con exito, incluso estoy implementando un ejemplo que envié un correo dependiendo de la temperatura de un sensor por ejemplo así:
if temperatura > 70:
Estoy recibiendo los datos de una base de datos que recibe los valores de un sensor de temperatura y esta se actualiza cada 15 seg y me gráfica los datos. Me envía un correo si el valor de la temperatura pasa los 25°C. Mi pregunta es si hay alguna manera de limitar el envió del correo ya que si el valor se mantiene arriba de los 25°C me estará enviando un correo cada 15 seg ya que ese es el tiempo en el que se reciben valores para después graficarlos. Por ejemplo limitar el envió cada 20 minutos si es que la temperatura se mantiene arriba de los 25°C por 2 horas por ejemplo.
Muchas gracias.
Recursos Python says:
Hola Saul. Cuando la temperatura es mayor a 25ºC deberías chequear el valor de la última temperatura recibida. Si este último es mayor a 25 quiere decir que el email ya fue enviado y no deberías proceder.
Saludos
nico says:
hola, una consulta, que variaciones incluirias para enviar mails a una lista de contactos?
Recursos Python says:
Hola, deberías cambiar la línea 15 por
mime_message["To"] = ", ".join(lista_de_contactos)
y la 21 porsmtp.sendmail(from_address, lista_de_contactos, mime_message.as_string())
.Saludos
irma says:
Hola estaba probando un código, pero no enviaba el asunto así que agregue parte de tu código para armar el mensaje y funciono. Muchas gracias fue de gran ayuda.
Recursos Python says:
Hola Irma. Me alegro, saludos.
Samuel says:
Hola, excelente su sitio sobre python, muy práctico y bien explicado de manera sencilla. He estado unos meses traveseando con python y buscaba esto de poder enviar e-mails lo he hecho con el ejemplo que han puesto. Mi pregunta ahora es: ¿hay alguna forma de automatizar el envío de un correo electrónico? No he encontrado nada al respecto y me serviría mucho para poder enviar varios informes de texto a fin de mes todos los meses de forma automática a una hora específica. Espero puedas ayudarme con eso. Saludos y sigue publicando estas excelentes ayudas.
Recursos Python says:
Hola Samuel, gracias por el comentario y me alegro que te haya sido de utilidad el artículo. Con respecto a tu problema, el mismo excede los límites de Python. Generalmente para este tipo de procedimientos se utilizan tareas programadas o crontab en Unix. La idea es programar la ejecución periódica de tu script Python que envía los correos. En caso que tengas un panel de control como CPanel, podrás programar tus tareas desde allí fácilmente. Si utilizas Windows, tendrás también un bonito asistente para hacerlo.
Un saludo.