Fuente de datos: SMTP


1Presentación

Esta fuente de datos es un cliente SMTP minimalista, que envía correos electrónicos conectándose a un relay SMTP configurable: un servidor externo (Gmail, Mailgun, Mailjet, Brevo…) o uno local (Postfix/Exim en smtp://localhost).

No depende de ninguna biblioteca externa (usa directamente los sockets de PHP) y se conecta a un único relay. La entrega directa al servidor MX del destinatario no está soportada: siempre se requiere un relay.

Al igual que las fuentes de datos Slack o Discord, esta es una fuente de datos de solo escritura: los métodos de lectura (get(), read(), find()…) son inertes o lanzan una excepción.

Si has configurado correctamente los parámetros de conexión, Temma crea automáticamente un objeto de tipo \Temma\Datasources\Smtp. Por convención, supondremos que has nombrado esta conexión smtp en el archivo etc/temma.php (consulta la documentación de configuración).

En los controladores, la conexión está entonces disponible de la siguiente forma:

$smtp = $this->smtp;

En los demás objetos gestionados por el componente de inyección de dependencias, la conexión es accesible de la siguiente forma:

$smtp = $loader->dataSources->smtp;
$smtp = $loader->dataSources['smtp'];
En la mayoría de los casos, no usarás esta fuente de datos directamente: la configurarás como el transporte del helper Email, que construye los mensajes y delega la entrega al relay. Consulta la sección Envío a través de un relay SMTP.

2Configuración

2.1DSN

En el archivo etc/temma.php (consulta la documentación de configuración), declaras el DSN (Data Source Name) usado para conectarte al relay SMTP. Hay tres esquemas disponibles, según el modo de cifrado de la conexión:

  • smtp://[user:password@]server[:port]
    Conexión en texto plano. Puerto por defecto: 25.
  • smtp+tls://[user:password@]server[:port]
    Conexión cifrada mediante STARTTLS (el cifrado se negocia después de la conexión). Puerto por defecto: 587.
  • smtps://[user:password@]server[:port]
    Conexión cifrada desde el inicio (TLS implícito). Puerto por defecto: 465.

La autenticación es opcional: solo se activa si el DSN contiene un par user:password (mecanismos PLAIN o LOGIN, preferiblemente sobre una conexión cifrada). Un relay local como smtp://localhost:25 se conecta, por lo tanto, sin autenticación.

Ejemplos:

// relay de Gmail con STARTTLS y autenticación
'smtp+tls://user:password@smtp.gmail.com:587'

// relay local sin autenticación
'smtp://localhost:25'
Si el nombre de usuario o la contraseña contienen caracteres especiales (@, :, /…), deben codificarse para URL en el DSN, o puedes usar la construcción a partir de parámetros separados.

La fábrica de fuentes de datos reconoce los prefijos smtp://, smtp+tls:// y smtps://. La forma genérica también puede usarse: [\Temma\Datasources\Smtp]smtp://….


2.2Parámetros opcionales

El DSN acepta parámetros de consulta opcionales:

  • helo: nombre anunciado en el comando EHLO/HELO.
  • timeout: tiempo límite de red, en segundos.
  • verify: verificación del certificado TLS (1 para activar, 0 para desactivar; activado por defecto).
smtp+tls://user:pass@smtp.example.com:587?helo=mysite.com&timeout=10&verify=1

2.3Construcción a partir de parámetros

Una contraseña (o un nombre de usuario) que contiene caracteres especiales es incómoda de codificar en un DSN. En ese caso, puedes describir la conexión usando parámetros separados en lugar de un DSN. Los parámetros aceptados son: host, port, user, password, security (none, starttls o tls), helo, timeout y verify.

'x-email' => [
    'transport' => [
        'host'     => 'smtp.example.com',
        'port'     => 587,
        'user'     => 'user@example.com',
        'password' => 'p@ss:w/rd!',
        'security' => 'starttls',
    ],
],

Esta forma es equivalente al DSN correspondiente. Es utilizada, en particular, por el helper Email mediante la directiva transport en forma de array.


3Sobre y mensaje

El envío de un correo electrónico SMTP se basa en dos nociones distintas:

  • el sobre: el remitente (MAIL FROM) y la lista de destinatarios (RCPT TO) realmente utilizados por el protocolo SMTP;
  • el mensaje: el flujo completo RFC 5322 (From, To, Cc, Subject, Date, Message-ID, cabeceras MIME… y el cuerpo).

El sobre y el mensaje son independientes. Por ejemplo, los destinatarios en copia oculta aparecen en el sobre (para que reciban el mensaje) pero no en las cabeceras del mensaje (sin cabecera Bcc).

La fuente de datos se encarga de la transparencia SMTP (normalización de los finales de línea a CRLF y el "dot-stuffing" de las líneas del cuerpo que comienzan con un punto). Tú proporcionas un mensaje RFC 5322 normal; el cumplimiento a nivel de protocolo es automático.


4Envío

4.1set()

El método set() es la vía normal de envío (es la que utiliza el helper Email). Espera un valor de array estructurado que describe el sobre y el mensaje:

$smtp->set($id, [
    'from'       => 'sender@example.com',
    'recipients' => ['dest1@example.com', 'dest2@example.com'],
    'message'    => $rawRfc5322Message,
]);
  • from: remitente del sobre, usado para MAIL FROM.
  • recipients: lista de destinatarios, un RCPT TO por cada entrada.
  • message: flujo RFC 5322 completo, enviado en DATA.

El primer parámetro ($id) es un simple identificador (Message-ID o identificador de la aplicación), usado para el log.

Esta estructura "portátil" es lo que permite usar cualquier fuente de datos como transporte: una fuente SMTP entrega el mensaje, una fuente File o S3 lo archiva, una fuente de cola de mensajes lo encola, etc. El sobre viaja en el valor, nunca en las opciones ni en la clave.


4.2write()

El método write() ofrece un acceso en bruto: el valor es directamente el flujo RFC 5322, y el sobre se pasa en el tercer parámetro ($options).

$smtp->write($id, $rawRfc5322Message, [
    'from'       => 'sender@example.com',
    'recipients' => ['dest1@example.com', 'dest2@example.com'],
]);

El envío es inmediato en ambos casos.


5Uso del helper Email

En la práctica, esta fuente de datos se usa principalmente como transporte para el helper Email. Entonces no llamas ni a set() ni a write() tú mismo: el helper construye el mensaje y el sobre, y luego delega la entrega. Consulta la sección Envío a través de un relay SMTP del helper Email.