"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.
