Última actualización: 04 de diciembre de 2023

10.5. email - Correo electrónico

Nota

Propósito: es una libraría para administrar mensajes de correo electrónico.

El correo electrónico es una de las formas más antiguas de comunicación digital, pero sigue siendo una de las más populares. La libraría estándar de Python incluye módulos para enviar, recibir y almacenar mensajes de correo electrónico por medio de la librería email.

smtplib se comunica con un servidor de correo para entregar un mensaje. smtpd se puede utilizar para crear un servidor de correo personalizado y proporciona clases útiles para depurar la transmisión de correo electrónico en otras aplicaciones.

imaplib utiliza el protocolo IMAP para manipular mensajes almacenados en un servidor. Proporciona una API de bajo nivel para clientes IMAP y puede consultar, recuperar, mover y eliminar mensajes.

Los archivos de mensajes locales se pueden crear y modificar mailbox utilizando varios formatos estándar, incluidos los populares formatos mbox y Maildir utilizados por muchos programas de clientes de correo electrónico.

10.5.1. Envío de correo básico

A continuación, un ejemplo de envió de correo electrónico, usando el servicio Gmail, usando una plantilla de correo básica basado en una cadena de caracteres:

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

# Tu dirección desde donde envía el correo
FROM_ADDRESS = "TU_CORREO_GOOGLE_AQUÍ"
# Tu contraseña de aplicación de Google del correo electrónico desde donde envía el correo
FROM_ADDRESS_PASSWORD = "TU_CONTRASEÑA_DE_APLICACIÓN_GOOGLE_AQUÍ"
# Tu dirección del host SMTP
SMTP_SERVER = "smtp.gmail.com"
# Tu puerto del host SMTP
SMTP_PORT = "587"

remitente = "leonardoc@plone.org"
destinatarios = ["leonardocaballero@gmail.com"]

mensaje = """From: Macagua <leonardoc@plone.org>
To: Leonardo Caballero <leonardocaballero@gmail.com>
Subject: Prueba de Envios del SMTP

Esto es un mensaje de prueba por correo electronico.
"""

try:
    smtp = smtplib.SMTP(host=SMTP_SERVER, port=SMTP_PORT)
    smtp.starttls()
    smtp.login(FROM_ADDRESS, FROM_ADDRESS_PASSWORD)
    smtp.sendmail(remitente, destinatarios, mensaje)
    smtp.quit()
    print("Correo enviado correctamente")
except Exception:
    print("Error: no se pudo enviar el correo")

El anterior código al ejecutar debe mostrar el siguiente mensaje:

Correo enviado correctamente

Y para captura todas las excepciones posibles, muestra el siguiente mensaje:

Error: no se pudo enviar el correo

El mensaje recibido en la cuenta Gmail desde el programa email_smtplib_demo1.py luciría de la siguiente forma:

Mensaje recibido en la cuenta Gmail desde el programa email_smtplib_demo1.py.

Figura 10.1, Figura 10.1, Mensaje recibido en la cuenta Gmail desde el programa email_smtplib_demo1.py.

10.5.2. Envío de correo personalizado

A continuación, un ejemplo de envió de correo electrónico, usando el servicio Gmail, acoplando variables en una plantilla de correo básica basado en una cadena de caracteres:

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

# Tu dirección desde donde envía el correo
FROM_ADDRESS = "TU_CORREO_GOOGLE_AQUÍ"
# Tu contraseña de aplicación de Google del correo electrónico desde donde envía el correo
FROM_ADDRESS_PASSWORD = "TU_CONTRASEÑA_DE_APLICACIÓN_GOOGLE_AQUÍ"
# Tu dirección del host SMTP
SMTP_SERVER = "smtp.gmail.com"
# Tu puerto del host SMTP
SMTP_PORT = "587"

remitente = "Macagua <leonardoc@plone.org>"
destinatarios = ["Leonardo Caballero <leonardocaballero@gmail.com>"]
asunto_mensaje = "Otro envio de prueba del SMTP"
cuerpo_mensaje = "Esto es un mensaje de prueba por correo electronico."

mensaje = f"""From: {remitente}
To: {", ".join(destinatarios)}
Subject: {asunto_mensaje}

{cuerpo_mensaje}
"""

try:
    smtp = smtplib.SMTP(host=SMTP_SERVER, port=SMTP_PORT)
    smtp.starttls()
    smtp.login(FROM_ADDRESS, FROM_ADDRESS_PASSWORD)
    smtp.sendmail(remitente, destinatarios, mensaje)
    smtp.quit()
    print("Correo enviado correctamente")
except Exception:
    print("Error: no se pudo enviar el correo")

El anterior código al ejecutar debe mostrar el siguiente mensaje:

Correo enviado correctamente

Y para captura todas las excepciones posibles, muestra el siguiente mensaje:

Error: no se pudo enviar el correo

El mensaje recibido en la cuenta Gmail desde el programa email_smtplib_demo2.py luciría de la siguiente forma:

Mensaje recibido en la cuenta Gmail desde el programa email_smtplib_demo2.py.

Figura 10.2, Figura 10.2, Mensaje recibido en la cuenta Gmail desde el programa email_smtplib_demo2.py.

10.5.3. Envío de correo avanzado

A continuación, un ejemplo de envió de correo electrónico, usando el servicio Gmail, usando una objeto de tipo Template acoplando variables, usando diversas excepciones para manipular los posibles errores:

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

from string import Template

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

DIR_ARCHIVO = os.path.dirname(os.path.abspath(__file__)) + os.sep
ARCHIVO = ["email_contactos.txt", "email_mensaje.txt"]

# Dirección desde donde se envía el correo
FROM_ADDRESS = "TU_CORREO_GOOGLE_AQUÍ"
# Contraseña de aplicación de la cuenta Google desde donde se envía el correo
FROM_ADDRESS_PASSWORD = "TU_CONTRASEÑA_DE_APLICACIÓN_GOOGLE_AQUÍ"
# Dirección del servidor SMTP
SMTP_SERVER = "smtp.gmail.com"
# Puerto del servidor SMTP
SMTP_PORT = "587"


def leer_contacto(nombre_archivo):
    """
    Devuelve dos tipo lista nombres y correos electrónicos que contienen nombres y direcciones
    de correo electrónico leídas de un archivo especificado por nombre de archivo.
    """

    nombres = []
    correos = []
    with open(nombre_archivo, encoding="utf-8") as archivo_contactos:
        for contacto in archivo_contactos:
            nombres.append(contacto.split()[0])
            correos.append(contacto.split()[1])
    return nombres, correos


def leer_plantilla(nombre_archivo):
    """
    Devuelve un objeto Template que incluye el contenido del
    archivo especificado por nombre de archivo.
    """

    with open(nombre_archivo, encoding="utf-8") as archivo_plantilla:
        contenido_archivo_plantilla = archivo_plantilla.read()
    return Template(contenido_archivo_plantilla)


def main():
    """
    Función principal del programa.
    """

    try:
        # leer contactos
        nombres, correos = leer_contacto(DIR_ARCHIVO + ARCHIVO[0])
        # leer mensaje de plantilla
        mensaje_plantilla = leer_plantilla(DIR_ARCHIVO + ARCHIVO[1])

        # configurar el servidor SMTP
        smtp = smtplib.SMTP(host=SMTP_SERVER, port=SMTP_PORT)
        smtp.starttls()
        smtp.login(FROM_ADDRESS, FROM_ADDRESS_PASSWORD)

        # Para cada contacto, envíe el correo electrónico:
        for nombre, correo in zip(nombres, correos):
            # crear un mensaje
            msg = MIMEMultipart()

            # agregue el nombre de la persona real a la plantilla de mensaje
            mensaje = mensaje_plantilla.substitute(NOMBRE_PERSONA=nombre.title())

            # Imprime el cuerpo del mensaje por nuestro bien
            print(mensaje)

            # configurar los parámetros del mensaje
            msg["From"] = FROM_ADDRESS
            msg["To"] = correo
            msg["Subject"] = "Esto es un mensaje PRUEBA"

            # añadir en el cuerpo del mensaje
            msg.attach(MIMEText(mensaje, "plain"))

            # enviar el mensaje a través del servidor configurado anteriormente.
            smtp.send_message(msg)
            del msg

        # Terminar la sesión SMTP y cerrar la conexión
        smtp.quit()
        print("Correo(s) enviado(s) correctamente")
    except smtplib.SMTPConnectError as e:
        print(f"Error: Conexión al servidor de correo fallo: {e}")
    except smtplib.SMTPAuthenticationError as e:
        print(f"Error: Credenciales de acceso al correo no coinciden: {e}")
    except Exception as e:
        print(f"Error: no se pudo enviar el correo: {e}")


if __name__ == "__main__":
    main()

Archivo que incluye la lista de contactos:

1
2
leonardo leonardocaballero@gmail.com
macagua leonardoc@plone.org

Archivo que incluye la plantilla del mensaje:

1
2
3
4
5
6
Estimado(a) ${NOMBRE_PERSONA},

Este es un mensaje de prueba.
Espero tengas una gran semana!

Sinceramente

El anterior código al ejecutar debe mostrar el siguiente mensaje:

Estimado(a) Leonardo,

Este es un mensaje de prueba.
Espero tengas una gran semana!

Sinceramente


Estimado(a) Macagua,

Este es un mensaje de prueba.
Espero tengas una gran semana!

Sinceramente

Correo(s) enviado(s) correctamente

Cuando hay error de conexión al servidor SMTP, muestra el siguiente mensaje:

Error: Conexión al servidor de correo fallo: [Errno -2] Name or service not known

Cuando hay error de en las credenciales de acceso al correo, muestra el siguiente mensaje:

Error: Credenciales de acceso al correo no coinciden: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8  https://support.google.com/mail/?p=BadCredentials g24-20020ab02058000000b00418c627a089sm538715ual.7 - gsmtp')

Y para captura todas las excepciones posibles, muestra el siguiente mensaje:

Error: no se pudo enviar el correo: (535, b'5.7.8 Username and Password not accepted. Learn more at\n5.7.8  https://support.google.com/mail/?p=BadCredentials h199-20020a1f9ed0000000b003b7d46d80b6sm569582vke.16 - gsmtp')

Puede ejecutar distribución binaria hello.exe generada, el cual mostrara la siguiente pantalla.

El mensaje recibido en la cuenta Gmail desde el programa emails_gmail_send.py luciría de la siguiente forma:

Mensaje recibido en la cuenta Gmail desde el programa emails_gmail_send.py.

Figura 10.3, Figura 10.3, Mensaje recibido en la cuenta Gmail desde el programa emails_gmail_send.py.

Además de los procesos de permisos específicos de Gmail (que incluyen aplicaciones menos seguras, etc.), estas secuencias de comandos y ejemplos funcionarían con casi cualquier otro servicio de correo que proporcione conectividad SMTP, siempre que tenga la dirección del servidor y el puerto necesarios.


Ver también

Consulte la sección de lecturas suplementarias del entrenamiento para ampliar su conocimiento en esta temática.


¿Cómo puedo ayudar?

¡Mi soporte está aquí para ayudar!

Mi horario de oficina es de lunes a sábado, de 9 AM a 5 PM. GMT-4 - Caracas, Venezuela.

La hora aquí es actualmente 7:35 PM GMT-4.

Mi objetivo es responder a todos los mensajes dentro de un día hábil.

Contrata mi increíble soporte profesional