Source de données : SMTP


1Présentation

Cette source de données est un client SMTP minimal, qui envoie des emails en se connectant à un relais SMTP configurable : un serveur externe (Gmail, Mailgun, Mailjet, Brevo…) ou local (Postfix/Exim sur smtp://localhost).

Elle ne dépend d'aucune bibliothèque externe (elle utilise directement les sockets PHP) et se connecte à un seul relais. L'envoi direct vers le serveur MX du destinataire n'est pas pris en charge : il faut toujours passer par un relais.

Comme les sources de données Slack ou Discord, il s'agit d'une source de données en écriture seule : les méthodes de lecture (get(), read(), find()…) sont inertes ou lèvent une exception.

Si vous avez correctement configuré les paramètres de connexion, Temma crée automatiquement un objet de type \Temma\Datasources\Smtp. Par convention, nous partirons du principe que vous avez nommé cette connexion smtp dans le fichier etc/temma.php (voir la documentation de la configuration).

Dans les contrôleurs, la connexion est alors disponible en écrivant :

$smtp = $this->smtp;

Dans les autres objets gérés par le composant d'injection de dépendances, la connexion est accessible en écrivant :

$smtp = $loader->dataSources->smtp;
$smtp = $loader->dataSources['smtp'];
Dans la plupart des cas, vous n'utiliserez pas cette source de données directement : vous la configurerez comme transport du helper Email, qui construit les messages et délègue l'envoi au relais. Voir la section Envoi via un relais SMTP.

2Configuration

2.1DSN

Dans le fichier etc/temma.php (voir la documentation de la configuration), vous déclarez le DSN (Data Source Name) qui permet de se connecter au relais SMTP. Trois schémas sont disponibles, selon le mode de chiffrement de la connexion :

  • smtp://[utilisateur:motdepasse@]serveur[:port]
    Connexion en clair. Port par défaut : 25.
  • smtp+tls://[utilisateur:motdepasse@]serveur[:port]
    Connexion chiffrée via STARTTLS (le chiffrement est négocié après la connexion). Port par défaut : 587.
  • smtps://[utilisateur:motdepasse@]serveur[:port]
    Connexion chiffrée dès l'ouverture (TLS implicite). Port par défaut : 465.

L'authentification est optionnelle : elle n'est déclenchée que si le DSN contient un couple utilisateur:motdepasse (mécanismes PLAIN ou LOGIN, à utiliser de préférence par-dessus une connexion chiffrée). Un relais local comme smtp://localhost:25 se connecte donc sans authentification.

Exemples :

// relais Gmail avec STARTTLS et authentification
'smtp+tls://user:motdepasse@smtp.gmail.com:587'

// relais local sans authentification
'smtp://localhost:25'
Si l'identifiant ou le mot de passe contient des caractères spéciaux (@, :, /…), il faut les encoder au format URL dans le DSN, ou utiliser la construction par paramètres séparés.

La fabrique de sources de données reconnaît les préfixes smtp://, smtp+tls:// et smtps://. La forme générique reste également utilisable : [\Temma\Datasources\Smtp]smtp://….


2.2Paramètres optionnels

Le DSN accepte des paramètres de requête optionnels :

  • helo : nom annoncé lors de la commande EHLO/HELO.
  • timeout : délai d'attente réseau, en secondes.
  • verify : vérification du certificat TLS (1 pour activer, 0 pour désactiver ; activée par défaut).
smtp+tls://user:pass@smtp.example.com:587?helo=monsite.com&timeout=10&verify=1

2.3Construction par paramètres

Un mot de passe (ou un identifiant) contenant des caractères spéciaux est pénible à encoder dans un DSN. Vous pouvez alors décrire la connexion à partir de paramètres séparés plutôt qu'à partir d'un DSN. Les paramètres acceptés sont : host, port, user, password, security (none, starttls ou tls), helo, timeout et verify.

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

Cette forme est équivalente au DSN correspondant. Elle est notamment utilisée par le helper Email via la directive smtp sous forme de tableau.


3Enveloppe et message

L'envoi d'un email SMTP repose sur deux notions distinctes :

  • l'enveloppe : l'expéditeur (MAIL FROM) et la liste des destinataires (RCPT TO) réellement utilisés par le protocole SMTP ;
  • le message : le flux RFC 5322 complet (en-têtes From, To, Cc, Subject, Date, Message-ID, en-têtes MIME… et corps).

Enveloppe et message sont indépendants. Par exemple, les destinataires en copie cachée figurent dans l'enveloppe (pour être livrés) mais pas dans les en-têtes du message (pas d'en-tête Bcc).

La source de données gère la transparence SMTP (normalisation des fins de ligne en CRLF et "dot-stuffing" des lignes du corps commençant par un point). Vous fournissez un message RFC 5322 normal ; la mise en conformité pour le protocole est automatique.


4Envoi

4.1set()

La méthode set() est la voie normale d'envoi (c'est celle qu'utilise le helper Email). Elle attend en valeur un tableau structuré décrivant l'enveloppe et le message :

$smtp->set($id, [
    'from'       => 'expediteur@example.com',
    'recipients' => ['dest1@example.com', 'dest2@example.com'],
    'message'    => $rawRfc5322Message,
]);
  • from : expéditeur d'enveloppe, utilisé pour MAIL FROM.
  • recipients : liste des destinataires, un RCPT TO par entrée.
  • message : flux RFC 5322 complet, transmis dans DATA.

Le premier paramètre ($id) est un simple identifiant (Message-ID ou identifiant applicatif), utilisé pour la journalisation.

C'est cette structure "portable" qui permet d'utiliser n'importe quelle source de données comme transport : une source SMTP livre le message, une source File ou S3 l'archive, une source de file de messages le met en attente, etc. L'enveloppe voyage dans la valeur, jamais dans les options ni dans la clé.


4.2write()

La méthode write() offre un accès brut : la valeur est directement le flux RFC 5322, et l'enveloppe est passée dans le troisième paramètre ($options).

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

L'envoi est immédiat dans les deux cas.


5Utilisation avec le helper Email

En pratique, cette source de données sert surtout de transport au helper Email. Vous n'appelez alors ni set() ni write() vous-même : le helper construit le message et l'enveloppe, puis délègue l'envoi. Reportez-vous à la section Envoi via un relais SMTP du helper Email.