# `smtpd` — Servidor SMTP

Source code: Lib/smtpd.py

Este módulo ofrece varias clases para implementar servidores SMTP (correo electrónico).

Obsoleto desde la versión 3.6: `smtpd` will be removed in Python 3.12 (see PEP 594 for details). The aiosmtpd package is a recommended replacement for this module. It is based on `asyncio` and provides a more straightforward API.

Este módulo ofrece varias implementaciones del servidor; una es una implementación genérica de no hace nada, pero cuyos métodos pueden ser sobrescritos para crear una implementación concreta, mientras que las otras dos ofrecen estrategias específicas de envío de correo.

Además, SMTPChannel puede ampliarse para implementar un comportamiento de interacción muy específico con clientes SMTP.

El código admite RFC 5321, más las extensiones RFC 1870 SIZE y RFC 6531 SMTPUTF8.

## Objetos SMTPServer

class `smtpd.``SMTPServer`(localaddr, remoteaddr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=False)

  Crea un nuevo objeto `SMTPServer`, que se vincula a la dirección local localaddr. Tratará remoteaddr como un transmisor SMTP ascendente. Tanto localaddr como remoteaddr deben ser una tupla (host, port). El objeto hereda de `asyncore.dispatcher`, por lo que se insertará en el bucle de eventos de `asyncore` en la instanciación.

  data_size_limit especifica el número máximo de bytes que se aceptarán en un comando `DATA`. Un valor de `None` o `0` significa que no hay límite.

  map es el mapa de conectores que se utilizará para las conexiones (un diccionario inicialmente vacío es un valor adecuado). Si no se especifica, se utiliza el mapa de socket global `asyncore`.

  enable_SMTPUTF8 determina si la extensión `SMTPUTF8` (como se define en RFC 6531) debe estar habilitada. El valor predeterminado es `False`. Cuando es `True`, `SMTPUTF8` se acepta como parámetro para el comando `MAIL` y cuando está presente se pasa a `process_message()` en la lista `kwargs[‘mail_options’]` . decode_data y enable_SMTPUTF8 no se pueden establecer en `True` al mismo tiempo.

  decode_data especifica si la porción de datos de la transacción SMTP debe decodificarse usando UTF-8. Cuando decode_data es `False` (el valor predeterminado), el servidor anuncia la extensión `8BITMIME` (RFC 6152), acepta el parámetro `BODY=8BITMIME` al comando `MAIL`, y cuando está presente lo pasa a `process_message()` en la lista `kwargs['mail_options']`. decode_data y enable_SMTPUTF8 no se pueden establecer en `True` al mismo tiempo.

  `process_message`(peer, mailfrom, rcpttos, data, **kwargs)

    Lanza una excepción `NotImplementedError`. Sobrescribe este método en subclases para hacer algo útil con este mensaje. Todo lo que se haya pasado en el constructor como remoteaddr estará disponible en el atributo `_remoteaddr`. peer es la dirección del host remoto, mailfrom es el creador del sobre, rcpttos son los destinatarios del sobre y data es una cadena de caracteres que contiene el contenido del correo electrónico (que debe estar en formato RFC 5321).

    Si la palabra clave del constructor decode_data se establece en `True`, el argumento data será una cadena Unicode. Si se establece en `False`, será un objeto de bytes.

    kwargs es un diccionario que contiene información adicional. Está vacío si se proporcionó `decode_data=True` como argumento de inicialización; de lo contrario, contiene las siguientes claves:

    > mail_options:

    >   una lista de todos los parámetros recibidos para el comando `MAIL` (los elementos son cadenas en mayúsculas; ejemplo: `['BODY=8BITMIME', 'SMTPUTF8']`).

    > rcpt_options:

    >   igual que mail_options pero para el comando `RCPT`. Actualmente, no se admiten las opciones `RCPT TO`, por lo que, por ahora, siempre será una lista vacía.

    Las implementaciones de `process_message` deben usar la firma `**kwargs` para aceptar argumentos por palabra clave arbitrarios, ya que las mejoras de características futuras pueden agregar claves al diccionario de argumentos de palabras clave.

    Retorne `None` para solicitar una respuesta normal de `250 Ok`; de lo contrario, retorne la cadena de respuesta deseada en formato RFC 5321.

  `channel_class`

    Sobrescriba este método en las subclases para usar una clase `SMTPChannel` personalizada para administrar clientes SMTP.

  Nuevo en la versión 3.4: El argumento del constructor map.

  Distinto en la versión 3.5: localaddr y remoteaddr ahora pueden contener direcciones IPv6.

  Nuevo en la versión 3.5: Los parámetros del constructor decode_data y enable_SMTPUTF8, y el parámetro kwargs para `process_message()` cuando decode_data es `False`.

  Distinto en la versión 3.6: decode_data ahora es `False` por defecto.

## Objetos DebuggingServer

class `smtpd.``DebuggingServer`(localaddr, remoteaddr)

  Crea un nuevo servidor de depuración. Los argumentos son iguales que en `SMTPServer`. Los mensajes se descartarán y se imprimirán en la salida estándar.

## Objetos PureProxy

class `smtpd.``PureProxy`(localaddr, remoteaddr)

  Crea un nuevo servidor proxy puro. Los argumentos son iguales que en `SMTPServer`. Todo se transmitirá a remoteaddr. Tenga en cuenta que ejecutar esto implica una buena posibilidad de convertirlo en un relé abierto, así que tenga cuidado.

## Objetos MailmanProxy

class `smtpd.``MailmanProxy`(localaddr, remoteaddr)

  Obsoleto desde la versión 3.9, se eliminará en la versión 3.11: `MailmanProxy` está obsoleto, ya que depende del módulo `Mailman` el cual ya no existe.

  Crea un nuevo servidor proxy puro. Los argumentos son iguales que en `SMTPServer`. Todo se transmitirá a remoteaddr, a menos que las configuraciones locales de mailman conozcan una dirección, en cuyo caso se manejará a través de mailman. Tenga en cuenta que ejecutar esto implica una buena posibilidad de convertirlo en un relé abierto, así que tenga cuidado.

## Objetos SMTPChannel

class `smtpd.``SMTPChannel`(server, conn, addr, data_size_limit=33554432, map=None, enable_SMTPUTF8=False, decode_data=False)

  Crea un nuevo objeto `SMTPChannel` que gestiona la comunicación entre el servidor y un único cliente SMTP.

  conn y addr son según las variables de instancia que se describen a continuación.

  data_size_limit especifica el número máximo de bytes que se aceptarán en un comando `DATA`. Un valor de `None` o `0` significa que no hay límite.

  enable_SMTPUTF8 determina si la extensión `SMTPUTF8` (como se define en RFC 6531) debe estar habilitada. El valor predeterminado es `False`. decode_data y enable_SMTPUTF8 no se pueden establecer en `True` al mismo tiempo.

  Se puede especificar un diccionario en map para evitar el uso de un mapa de socket global.

  decode_data especifica si la porción de datos de la transacción SMTP debe decodificarse usando UTF-8. El valor predeterminado es `False`. decode_data y enable_SMTPUTF8 no se pueden establecer en `True` al mismo tiempo.

  Para utilizar una implementación SMTPChannel personalizada, debe anular `SMTPServer.channel_class` de su `SMTPServer`.

  Distinto en la versión 3.5: Se agregaron los parámetros decode_data y enable_SMTPUTF8.

  Distinto en la versión 3.6: decode_data ahora es `False` por defecto.

  La clase `SMTPChannel` tiene las siguientes variables de instancia:

  `smtp_server`

    Contiene el `SMTPServer` que generó este canal.

  `conn`

    Contiene el objeto de socket que se conecta al cliente.

  `addr`

    Contiene la dirección del cliente, el segundo valor retornado por `socket.accept`

  `received_lines`

    Contiene una lista de las cadenas de línea (decodificadas mediante UTF-8) recibidas del cliente. Las líneas tienen su final de línea `"\r\n"` traducido a `"\n"`.

  `smtp_state`

    Contiene el estado actual del canal. Será `COMMAND` inicialmente y luego `DATA` después de que el cliente envíe una línea «DATA».

  `seen_greeting`

    Contiene una cadena de caracteres que contiene el saludo enviado por el cliente en su «HELO».

  `mailfrom`

    Contiene una cadena de caracteres que contiene la dirección identificada en la línea «MAIL FROM:» del cliente.

  `rcpttos`

    Contiene una lista de cadenas de caracteres que contienen las direcciones identificadas en las líneas «RCPT TO:» del cliente.

  `received_data`

    Contiene una cadena de caracteres que contiene todos los datos enviados por el cliente durante el estado de DATA, hasta pero sin incluir la terminación `"\r\n.\r\n"`.

  `fqdn`

    Holds the fully qualified domain name of the server as returned by `socket.getfqdn()`.

  `peer`

    Contiene el nombre del par del cliente como lo retorna `conn.getpeername()` donde `conn` es `conn`.

  La clase `SMTPChannel` opera invocando métodos llamados `smtp_<command>` al recibir una línea de comando del cliente. Construidos en la clase base `SMTPChannel`, son métodos para manejar los siguientes comandos (y responder a ellos de manera apropiada):

  Comando | Acción tomada
  --- | ---
  HELO | Acepta el saludo del cliente y lo almacena en `seen_greeting`. Establece el servidor en el modo de comando base.
  EHLO | Acepta el saludo del cliente y lo almacena en `seen_greeting`. Establece el servidor en el modo de comando extendido.
  NOOP | No realiza ninguna acción.
  QUIT | Cierra la conexión limpiamente.
  MAIL | Acepta la sintaxis «MAIL FROM:» y almacena la dirección proporcionada como `mailfrom`. En el modo de comando extendido, acepta el atributo RFC 1870 SIZE y responde apropiadamente según el valor de data_size_limit.
  RCPT | Acepta la sintaxis «RCPT TO:» y almacena las direcciones proporcionadas en la lista `rcpttos`.
  RSET | Restablece `mailfrom`, `rcpttos` y `received_data`, pero no el saludo.
  DATA | Establece el estado interno en `DATA` y almacena las líneas restantes del cliente en `received_data` hasta que se recibe el terminador `”\r\n.\r\n”`.
  HELP | Retorna información mínima sobre la sintaxis del comando
  VRFY | Retorna el código 252 (el servidor no sabe si la dirección es válida)
  EXPN | Informa que el comando no está implementado.