smtplib — Cliente de protocolo SMTP

Código fuente: Lib/smtplib.py


El módulo smtplib define un objeto de sesión de cliente SMTP que se puede usar para mandar correo a cualquier máquina de Internet con un demonio de escucha SMTP o ESMTP. Para detalles sobre el funcionamiento de SMTP o ESMTP, consulta RFC 821 (Simple Mail Transfer Protocol) y RFC 1869 (Extensiones de Servicio SMTP).

class smtplib.SMTP(host='', port=0, local_hostname=None, [timeout, ]source_address=None)

Una instancia SMTP encapsula una conexión SMTP. Tiene métodos que admiten un repertorio completo de operaciones SMTP y ESMTP. Si se proporcionan los parámetros opcionales de host y puerto, el método connect() de SMTP se llama con esos parámetros durante la inicialización. Si se especifica, local_hostname se usa como FQDN del host local in el comando HELO/EHLO. De lo contrario, el hostname local se busca usando socket.getfqdn(). Si la llamada a connect() retorna cualquier cosa que no sea un código de éxito, se lanza un SMTPConnectError. El parámetro timeout opcional especifica un timeout en segundos para bloquear operaciones como el intento de conexión (si no se especifica, se utilizará la configuración global del timeout por defecto). Si el timeout de espera expira, se lanza socket.timeout. El parámetro opcional source_address permite el enlace a alguna dirección de origen específica en una máquina con múltiples interfaces de red, y/o a algún puerto TCP de origen específico. Se necesita una tupla de 2 (host, puerto), para que el socket se enlace como su dirección de origen antes de conectarse. Si se omite (os si el host o el puerto son '' y/o 0 respectivamente) se utilizara el comportamiento por defecto del SO.

Para un uso normal, solo debe requerir los métodos initialization/connect, sendmail() y SMTP.quit(). A continuación se incluye un ejemplo.

La clase SMTP admite la instrucción with. Cuando se usa así, el comando SMTP QUIT se emite automáticamente cuando la with sale de la instrucción. por ejemplo:

>>> from smtplib import SMTP
>>> with SMTP("domain.org") as smtp:
...     smtp.noop()
...
(250, b'Ok')
>>>

Genera un auditing event smtplib.send con argumentos self, data.

Distinto en la versión 3.3: Se agregó soporte para la sentencia with.

Distinto en la versión 3.3: se agrego el argumento source_address.

Nuevo en la versión 3.5: La extensión SMTPUTF8 (RFC 6531) ahora es compatible.

class smtplib.SMTP_SSL(host='', port=0, local_hostname=None, keyfile=None, certfile=None, [timeout, ]context=None, source_address=None)

Una instancia de SMTP_SSL se comporta exactamente igual que las instancias de SMTP. SMTP_SSL debe usarse para situaciones donde se requiere SSL desde el comienzo de la conexión y el uso starttls() no es apropiado. Si no se especifica host, se utiliza el host local. Si port es cero, se utiliza el puerto estándar SMTP sobre SSL (465). Los argumentos opcionales local_hostname, timeout y source_address tienen el mismo significado que en la clase SMTP. context, también opcional, puede contener una SSLContext y permite configurar varios aspectos de la conexión segura. Por favor lea Security considerations para conocer las mejores prácticas.

keyfile y certfile son una alternativa heredada a context y pueden apuntar a una clave privada con formato PEM y un archivo de cadena de certificados para la conexión SSL.

Distinto en la versión 3.3: se agregó contexto.

Distinto en la versión 3.3: se agrego el argumento source_address.

Distinto en la versión 3.4: La clase ahora admite la verificación del nombre de host con ssl.SSLContext.check_hostname y Server Name Indication (ver ssl.HAS_SNI).

Obsoleto desde la versión 3.6: keyfile y certfile están obsoletos en favor de context. Por favor use ssl.SSLContext.load_cert_chain() en su lugar, o deje que ssl.create_default_context() seleccione los certificados CA confiables del sistema para usted.

class smtplib.LMTP(host='', port=LMTP_PORT, local_hostname=None, source_address=None)

El protocolo LMTP, que es muy similar a ESMTP, se basa en gran medida en el cliente SMTP estándar. Es común usar sockets Unix para LMTP, por lo que nuestro método connect() debe ser compatible con eso, así como con un servidor host:puerto normal. Los argumentos opcionales local_hostname y source_address tienen el mismo significado que en la clase SMTP. Para especificar un socket Unix, debe usar una ruta absoluta para host, comenzando con “/”.

Se admite la autenticación mediante el mecanismo SMTP habitual. Cuando se usa un socket Unix, LMTP generalmente no admite ni requiere autenticación, pero su millaje puede variar.

También se define una buena selección de excepciones:

exception smtplib.SMTPException

Subclase de OSError que es la clase de excepción base para todas las demás excepciones proporcionadas por este módulo.

Distinto en la versión 3.4: SMTPException se convirtió en subclase de OSError

exception smtplib.SMTPServerDisconnected

Esta excepción se genera cuando el servidor se desconecta inesperadamente o cuando se intenta usar la instancia SMTP antes de conectarlo a un servidor.

exception smtplib.SMTPResponseException

Clase base para todas las excepciones que incluyen un código de error SMTP. Estas excepciones se generan en algunos casos cuando el servidor SMTP devuelve un código de error. El código de error se almacena en el atributo smtp_code del error, y el atributo smtp_error se establece en el mensaje de error.

exception smtplib.SMTPSenderRefused

Dirección del remitente rechazada. Además de los atributos establecidos por todas las excepciones SMTPResponseException, éste establece “remitente” para la cadena de caracteres que el servidor SMTP rechazó.

exception smtplib.SMTPRecipientsRefused

Se rechazaron todas las direcciones de destinatarios. Los errores para cada destinatario son accesibles mediante el atributo recipients, el cual es un diccionario del mismo tipo que el SMTP.sendmail() retorna.

exception smtplib.SMTPDataError

El servidor SMTP se negó a aceptar los datos del mensaje.

exception smtplib.SMTPConnectError

Se produjo un error durante el establecimiento de conexión con el servidor.

exception smtplib.SMTPHeloError

El servidor rechazó nuestro mensaje HELO.

exception smtplib.SMTPNotSupportedError

El servidor no admite el comando o la opción que se intentó.

Nuevo en la versión 3.5.

exception smtplib.SMTPAuthenticationError

La autenticación SMTP salió mal. Lo más probable es que el servidor no aceptó la combinación proporcionada de username/password.

Ver también

RFC 821 - Simple Mail Transfer Protocol

Definición de protocolo para SMTP. Este documento cubre el modelo, el procedimiento operativo y los detalles del protocolo para SMTP.

RFC 1869 - Extensiones de Servicio SMTP

Definición de las extensiones ESMTP para SMTP. Esto describe un marco para extender SMTP con nuevos comandos, que admite el descubrimiento dinámico de los comandos proporcionados por el servidor y define algunos comandos adicionales.

Objetos SMTP

Una instancia SMTP tiene los siguientes métodos:

SMTP.set_debuglevel(level)

Establezca el nivel de salida de depuración. Un valor de 1 o True para level da como resultado mensajes de depuración para la conexión y para todos los mensajes enviados y recibidos desde el servidor. Un valor de 2 para level da como resultado que estos mensajes tengan una marca de tiempo.

Distinto en la versión 3.5: Se agregó el nivel de depuración 2.

SMTP.docmd(cmd, args='')

Envíe un comando cmd al servidor. El argumento opcional args simplemente se concatena al comando, separado por un espacio.

Esto devuelve una tupla de 2 compuestos por un código de respuesta numérico y la línea de respuesta real (las respuestas de varias líneas se unen en una línea larga).

En funcionamiento normal, no debería ser necesario llamar a este método explícitamente. Se utiliza para implementar otros métodos y puede resultar útil para probar extensiones privadas.

Si se pierde la conexión con el servidor mientras se espera la respuesta, se activará SMTPServerDisconnected.

SMTP.connect(host='localhost', port=0)

Conéctese a un host en un puerto determinado. Los valores predeterminados son para conectarse al host local en el puerto SMTP estándar (25). Si el nombre de host termina con dos puntos (':') seguido de un número, ese sufijo se eliminará y el número se interpretará como el número de puerto a utilizar. El constructor invoca automáticamente este método si se especifica un host durante la instanciación. Devuelve una tupla de 2 del código de respuesta y el mensaje enviado por el servidor en su respuesta de conexión.

Genera un evento de auditoría smtplib.connect con argumentos self, host, port.

SMTP.helo(name='')

Identifíquese en el servidor SMTP usando HELO. El argumento del nombre de host tiene como valor predeterminado el nombre de dominio completo del host local. El mensaje devuelto por el servidor se almacena como el atributo helo_resp del objeto.

En funcionamiento normal, no debería ser necesario llamar a este método explícitamente. Será llamado implícitamente por sendmail() cuando sea necesario.

SMTP.ehlo(name='')

Identifíquese en un servidor ESMTP usando EHLO. El argumento del nombre de host tiene como valor predeterminado el nombre de dominio completo del host local. Examine la respuesta para la opción ESMTP y guárdelos para que los use has_extn(). También establece varios atributos informativos: el mensaje devuelto por el servidor se almacena como el atributo ehlo_resp, does_esmtp se establece en verdadero o falso dependiendo de si el servidor admite ESMTP, y esmtp_features será un diccionario que contiene los nombres de las extensiones de servicio SMTP que admite este servidor, y sus parámetros (si los hay).

A menos que desee utilizar has_extn() antes de enviar correo, no debería ser necesario llamar a este método explícitamente. Se llamará implícitamente por sendmail() cuando sea necesario.

SMTP.ehlo_or_helo_if_needed()

Este método llama a ehlo() o helo() si no ha habido ningún comando EHLO o HELO anterior en esta sesión. Primero prueba ESMTP EHLO.

SMTPHeloError

El servidor no respondió correctamente al saludo HELO.

SMTP.has_extn(name)

Retorna True si name está en el conjunto de extensiones de servicio SMTP devueltas por el servidor, False en caso contrario. El método es insensible a la presencia de mayúsculas en name.

SMTP.verify(address)

Verifique la validez de una dirección en este servidor usando SMTP VRFY. Retorna una tupla que consta del código 250 y una dirección completa RFC 822 (incluido el nombre humano) si la dirección del usuario es válida. De lo contrario, devuelve un código de error SMTP de 400 o más y una cadena de error.

Nota

Muchos sitios desactivan SMTP VRFY para frustrar a los spammers.

SMTP.login(user, password, *, initial_response_ok=True)

Inicie sesión en un servidor SMTP que requiera autenticación. Los argumentos son el nombre de usuario y la contraseña para autenticarse. Si no ha habido ningún comando EHLO o HELO anterior en esta sesión, este método prueba primero ESMTP EHLO. Este método regresará normalmente si la autenticación fue exitosa o puede generar las siguientes excepciones:

SMTPHeloError

El servidor no respondió correctamente al saludo HELO.

SMTPAuthenticationError

El servidor no aceptó la combinación de nombre de username/password.

SMTPNotSupportedError

El servidor no admite el comando AUTH.

SMTPException

No se encontró ningún método de autenticación adecuado.

Cada uno de los métodos de autenticación admitidos por smtplib se prueban a su vez si se anuncian como admitidos por el servidor. Consulte auth() para obtener una lista de los métodos de autenticación admitidos. initial_response_ok se pasa a auth().

El argumento de palabra clave opcional initial_response_ok especifica si, para los métodos de autenticación que lo admiten, se puede enviar una «respuesta inicial» como se especifica en RFC 4954 junto con el comando AUTH, en lugar de requerir un desafío/respuesta .

Distinto en la versión 3.5: SMTPNotSupportedError se puede generar y se agregó el parámetro initial_response_ok.

SMTP.auth(mechanism, authobject, *, initial_response_ok=True)

Emita un comando SMTP AUTH para el mechanism de autenticación especificado y maneje la respuesta de desafío a través de authobject.

mechanism especifica qué mecanismo de autenticación se utilizará como argumento para el comando AUTH; los valores válidos son los enumerados en el elemento auth de esmtp_features.

authobject debe ser un objeto invocable que tome un único argumento opcional:

data = authobject(challenge=None)

Si la verificación de respuesta inicial devuelve None, o si initial_response_ok es falso, se llamará a authobject() para procesar la respuesta de desafío del servidor; el argumento challenge que se pasa será un bytes. Debería devolver data ASCII str que serán codificados en base64 y enviados al servidor.

Si la verificación de respuesta inicial devuelve None, o si initial_response_ok es falso, se llamará a authobject() para procesar la respuesta de desafío del servidor; el argumento challenge que se pasa será un bytes. Debería devolver data ASCII str que serán codificados en base64 y enviados al servidor.

La clase SMTP proporciona authobjects para los mecanismos CRAM-MD5, PLAIN y LOGIN; se denominan SMTP.auth_cram_md5, SMTP.auth_plain y SMTP.auth_login respectivamente. Todos requieren que las propiedades de user y password de la instancia SMTP se establezcan en los valores adecuados.

El código de usuario normalmente no necesita llamar a auth directamente, sino que puede llamar al método login(), que probará cada uno de los mecanismos anteriores a su vez, en el orden indicado. auth está expuesto para facilitar la implementación de métodos de autenticación que no (o aún no) son compatibles directamente con smtplib.

Nuevo en la versión 3.5.

SMTP.starttls(keyfile=None, certfile=None, context=None)

Ponga la conexión SMTP en modo TLS (Seguridad de la capa de transporte). Todos los comandos SMTP que siguen se cifrarán. Entonces deberías llamar a ehlo() de nuevo.

Si se proporcionan keyfile y certfile, se utilizan para crear una ssl.SSLContext.

El parámetro context opcional es un objeto ssl.SSLContext; Esta es una alternativa al uso de un archivo de claves y un archivo de certificado y, si se especifica, tanto keyfile como certfile deben ser None.

Si no ha habido ningún comando EHLO o HELO anterior en esta sesión, este método intenta ESMTP EHLO primero.

Obsoleto desde la versión 3.6: keyfile y certfile están obsoletos en favor de context. Por favor use ssl.SSLContext.load_cert_chain() en su lugar, o deje que ssl.create_default_context() seleccione los certificados CA confiables del sistema para usted.

SMTPHeloError

El servidor no respondió correctamente al saludo HELO.

SMTPNotSupportedError

El servidor no admite la extensión STARTTLS.

RuntimeError

La compatibilidad con SSL/TLS no está disponible para su intérprete de Python.

Distinto en la versión 3.3: se agregó contexto.

Distinto en la versión 3.4: El método ahora admite la verificación del nombre de host con SSLContext.check_hostname y Server Name Indicator (ver HAS_SNI).

Distinto en la versión 3.5: El error generado por falta de compatibilidad con STARTTLS ahora es la subclase SMTPNotSupportedError en lugar de la base SMTPException.

SMTP.sendmail(from_addr, to_addrs, msg, mail_options=(), rcpt_options=())

Enviar correo. Los argumentos requeridos son RFC 822 cadena de dirección de origen, una lista de RFC 822 cadenas de dirección (una cadena simple se tratará como una lista con 1 dirección) y una cadena de mensaje. La persona que llama puede pasar una lista de opciones de ESMTP (como 8bitmime) para usar en los comandos MAIL FROM como mail_options. Las opciones de ESMTP (como los comandos DSN) que deben usarse con todos los comandos RCPT se pueden pasar como rcpt_options. (Si necesita usar diferentes opciones de ESMTP para diferentes destinatarios, debe usar los métodos de bajo nivel como mail(), rcpt() y data() para enviar el mensaje).

Nota

Los parámetros from_addr y to_addrs se utilizan para construir el sobre del mensaje utilizado por los agentes de transporte. sendmail no modifica los encabezados de los mensajes de ninguna manera.

msg puede ser una cadena que contenga caracteres en el rango ASCII o una cadena de bytes. Una cadena se codifica en bytes utilizando el códec ascii, y los caracteres \r y \n solitarios se convierten en caracteres \ r\n. Una cadena de bytes no se modifica.

Si no ha habido ningún comando EHLO o HELO anterior en esta sesión, este método prueba primero ESMTP EHLO. Si el servidor utiliza ESMTP, se le pasará el tamaño del mensaje y cada una de las opciones especificadas (si la opción está en el conjunto de funciones que anuncia el servidor). Si EHLO falla, se probará HELO y se eliminarán las opciones de ESMTP.

Este método volverá normalmente si se acepta el correo para al menos un destinatario. De lo contrario, generará una excepción. Es decir, si este método no genera una excepción, alguien debería recibir su correo. Si este método no genera una excepción, devuelve un diccionario, con una entrada para cada destinatario rechazado. Cada entrada contiene una tupla del código de error SMTP y el mensaje de error adjunto enviado por el servidor.

Si se incluye SMTPUTF8” en mail_options * y el servidor lo admite, *from_addr y to_addrs pueden contener caracteres no ASCII.

Este método puede lanzar las siguientes excepciones:

SMTPRecipientsRefused

Todos los destinatarios fueron rechazados. Nadie recibió el correo. El atributo recipients del objeto de excepción es un diccionario con información sobre los destinatarios rechazados (como el que se retorna cuando se aceptó al menos un destinatario).

SMTPHeloError

El servidor no respondió correctamente al saludo HELO.

SMTPSenderRefused

El servidor no aceptó el from_addr.

SMTPDataError

El servidor respondió con un código de error inesperado (que no sea el rechazo de un destinatario).

SMTPNotSupportedError

Se proporcionó SMTPUTF8 en mail_options pero el servidor no lo admite.

A menos que se indique lo contrario, la conexión estará abierta incluso después de que se lance una excepción.

Distinto en la versión 3.2: msg puede ser una cadena de bytes.

Distinto en la versión 3.5: Se agregó compatibilidad con SMTPUTF8, y SMTPNotSupportedError puede aparecer si se especifica SMTPUTF8 pero el servidor no lo admite.

SMTP.send_message(msg, from_addr=None, to_addrs=None, mail_options=(), rcpt_options=())

Este es un método conveniente para llamar a sendmail() con el mensaje representado por un objeto email.message.Message. Los argumentos tienen el mismo significado que para sendmail(), excepto que msg es un objeto Mensaje.

Si from_addr es None o to_addrs es None, send_message llena esos argumentos con direcciones extraídas de los encabezados de msg como se especifica en RFC 5322: from_addr se establece en el campo Sender si está presente, y de lo contrario, en el campo From. to_addrs combina los valores (si los hay) de los campos To, Cc y Bcc de msg. Si aparece exactamente un conjunto de encabezados Resent-* en el mensaje, los encabezados normales se ignoran y en su lugar se utilizan los encabezados Resent- *. Si el mensaje contiene más de un conjunto de encabezados Resent-*, se lanza un ValueError, ya que no hay forma de detectar sin ambigüedades el conjunto más reciente de encabezados Resent-.

send_message serializa msg usando BytesGenerator con``r n`` como linesep, y llama a sendmail() para transmitir el mensaje resultante. Independientemente de los valores de from_addr y to_addrs, send_message no transmite ningún encabezado Bcc o Resent-Bcc que puedan aparecer en msg. Si alguna de las direcciones en from_addr y to_addrs contiene caracteres que no son ASCII y el servidor no anuncia la compatibilidad con SMTPUTF8, se lanza un error SMTPNotSupported. De lo contrario, el Message se serializa con un clon de su policy con el atributo utf8 establecido en True y SMTPUTF8 y BODY=8BITMIME se agregan a mail_options.

Nuevo en la versión 3.2.

Nuevo en la versión 3.5: Soporte para direcciones internacionalizadas (SMTPUTF8).

SMTP.quit()

Termine la sesión SMTP y cierre la conexión. Retorna el resultado del comando SMTP QUIT.

Los métodos de bajo nivel correspondientes a los comandos estándar SMTP/ESMTP `HELP, RSET, NOOP, MAIL, RCPT, y DATA también están soportados. Normalmente, no es necesario llamarlos directamente, por lo que no se documentan aquí. Para más detalles, consulte el código del módulo.

Ejemplo SMTP

Este ejemplo solicita al usuario las direcciones necesarias en el sobre del mensaje (direcciones “To” y “From” ) y el mensaje que se entregará. Tenga en cuenta que los encabezados que se incluirán con el mensaje deben incluirse en el mensaje tal y como se introdujeron; este ejemplo no procesa los encabezados RFC 822 . En particular, las direcciones “To” y “From deben incluirse explícitamente en los encabezados de los mensajes.

import smtplib

def prompt(prompt):
    return input(prompt).strip()

fromaddr = prompt("From: ")
toaddrs  = prompt("To: ").split()
print("Enter message, end with ^D (Unix) or ^Z (Windows):")

# Add the From: and To: headers at the start!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
       % (fromaddr, ", ".join(toaddrs)))
while True:
    try:
        line = input()
    except EOFError:
        break
    if not line:
        break
    msg = msg + line

print("Message length is", len(msg))

server = smtplib.SMTP('localhost')
server.set_debuglevel(1)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()

Nota

En general, querrá usar las características del paquete email para construir un mensaje de correo electrónico, que luego puede enviar a través de send_message(); ver email: Ejemplos.