Un mail envoyé par script PHP bloqué par Gmail révèle un problème d'authentification : mail() l'expédie sans signature DKIM publiée dans les DNS, avec un expéditeur que le SPF ignore. Message de contact, commentaire ou discussion WordPress : pour envoyer vers Gmail, Google exige depuis février 2024 SPF ou DKIM, et son centre d'aide liste chaque raison de refus.
Trois corrections pour envoyer sans blocage Gmail
- Un From du site dans le mail PHP, le visiteur en Reply-To.
- Un envoi par SMTP authentifié (PHPMailer ou Symfony Mailer) au lieu de la fonction mail(), y compris pour chaque commentaire.
- Une zone DNS qui publie SPF, DKIM et DMARC, contrôlés dans Gmail par l'aide de Google.
Ce que Gmail contrôle à l'arrivée d'un message
Gmail vérifie l'identité de l'expéditeur avant de lire le contenu du mail. Les consignes que Google publie dans l'aide Google Workspace distinguent deux niveaux d'exigence. Tout expéditeur doit authentifier son domaine par SPF ou par DKIM, disposer d'un enregistrement DNS inverse (PTR) cohérent pour l'adresse IP d'envoi, transmettre en TLS, respecter le format de message de la RFC 5322 et garder un taux de plaintes pour spam sous 0,3 %, Google recommandant de rester sous 0,1 %.
Au-delà de 5 000 messages par jour vers des adresses Gmail, la barre monte : SPF et DKIM ensemble, une politique DMARC publiée, l'alignement du domaine du champ From sur celui que valident SPF ou DKIM, et un désabonnement en un clic pour les mails marketing. Un formulaire de contact n'atteint jamais ce volume, mais une boutique qui confirme ses commandes par la fonction mail() peut s'en approcher.
Un message qui échoue à ces contrôles part dans le dossier spam ou se voit refusé. Google a annoncé un durcissement progressif des rejets à partir de novembre 2025 pour le trafic non conforme : un script qui passait de justesse peut ainsi cesser de livrer du jour au lendemain, sans aucune modification du code PHP.
Lire le code d'erreur renvoyé par Gmail
Le code d'erreur de Gmail figure dans le message de non-remise (bounce) reçu par l'adresse Return-Path, ou dans le journal du serveur de courrier (/var/log/mail.log sur Debian, par exemple). Chaque code désigne une cause précise, et sa lecture évite de corriger au hasard. Le tableau suivant reprend les retours les plus fréquents pour un mail parti d'un script PHP.
| Code | Ce que Gmail reproche | Où corriger |
|---|---|---|
| 550 5.7.26 | Message non authentifié : SPF et DKIM échouent, ou DMARC rejette | Zone DNS, champ From du script |
| 550 5.7.25 | L'IP d'envoi n'a pas de DNS inverse (PTR) | Hébergeur ou fournisseur du serveur |
| 550 5.7.1 | Message jugé indésirable ou IP de mauvaise réputation | Contenu, liste noire, passage par un SMTP |
| 421 4.7.28 | Débit inhabituel depuis l'IP ou le domaine, envoi différé | Rythme d'envoi, formulaire détourné |
Un code qui commence par 4 signale un refus temporaire : le serveur retente l'envoi plus tard. Un code en 5 marque un rejet définitif du mail, qu'aucune nouvelle tentative ne fera passer tant que la cause demeure.
Quatre erreurs fréquentes dans le script PHP
La fonction mail() de PHP remet le message au programme sendmail du serveur, réglé par la directive sendmail_path du fichier php.ini. Sur un hébergement mutualisé, il part d'une IP partagée par des centaines de sites, sans DKIM, et le SPF du domaine ne la mentionne pas toujours. Quatre défauts reviennent dans le code source des formulaires.
- Le From usurpé. Le champ From reprend l'adresse saisie par le visiteur dans le formulaire de contact. Le mail prétend alors venir de gmail.com ou d'un autre domaine qui n'a jamais autorisé ce serveur : DMARC échoue à coup sûr. Le From doit porter une adresse du domaine du site, celle du visiteur passant dans Reply-To.
- Le Return-Path du système. L'adresse de retour technique reste celle de l'utilisateur système du serveur (www-data@machine), faute du paramètre -f passé en cinquième argument de mail(). Le contrôle SPF porte justement sur cette adresse.
- Des en-têtes bricolés. Accents non encodés dans le sujet, retours à la ligne en \n au lieu de \r\n, absence de Date ou de Message-ID : le message paraît forgé aux filtres de Google.
- Aucun contrôle de saisie. Un formulaire qui accepte n'importe quel texte dans un champ d'en-tête sert de relais aux robots ; les plaintes pour spam font chuter la réputation de l'IP, puis du domaine.
Notifications de commentaire : le même piège sous WordPress
Les notifications de commentaire de WordPress empruntent le même chemin que le formulaire de contact : wp_mail() s'appuie sur PHPMailer, qui, sans réglage, délègue l'envoi à la fonction mail() du serveur. Un site qui reçoit dix commentaires par jour envoie donc dix mails non signés à l'administrateur, et Gmail les range en spam ou les refuse comme ceux d'un script maison.
L'avis de nouveau commentaire, la demande de modération, la réponse à un commentaire envoyée à son auteur : chaque notification part du même expéditeur, souvent wordpress@domaine.fr, une adresse que personne ne lit. Les cases du menu Réglages, Discussion décident quels mails partent vers l'administrateur et le modérateur : un modérateur qui reçoit chaque commentaire en attente multiplie les envois, et le destinataire Gmail voit arriver une série de messages non authentifiés. Une extension SMTP, ou quelques lignes branchées sur le crochet phpmailer_init, font passer ces mails WordPress par une vraie boîte du domaine. Le réglage vaut pour toute l'utilisation de wp_mail() : commentaires, réinitialisation de mot de passe, commandes WooCommerce.
Sur un blog très commenté, un commentaire indésirable qui déclenche une notification compte aussi : filtrer les robots en amont (Akismet, question anti-robot) réduit le volume de mails envoyés et protège la réputation du domaine.
Questions de dépannage sur l'envoi PHP vers Gmail
Pourquoi le message arrive en spam au lieu d'être refusé ?
Un mail classé en spam a franchi l'authentification de justesse, ou provient d'un domaine sans historique d'envoi. Un DMARC aligné, un contenu sans liens raccourcis et une version texte à côté du HTML améliorent le classement. Un corps en HTML seul, chargé d'images ou de publicité, pèse aussi dans le verdict du filtre de Gmail ; PHPMailer produit la double version par la propriété AltBody.
Aucun retour d'erreur et rien dans la boîte de réception ?
Le retour d'erreur part vers l'adresse Return-Path. Si elle appartient à l'utilisateur système, personne ne le lit : fixer cette adresse sur une boîte consultée, par le paramètre -f ou par la configuration SMTP.
Pourquoi les autres messageries acceptent ce que Gmail bloque ?
Gmail applique ses exigences d'authentification de l'expéditeur plus strictement que certains fournisseurs. Yahoo impose pourtant des règles proches depuis février 2024 et Microsoft a suivi en 2025 pour Outlook.com : le défaut finira par toucher toutes les boîtes.
Passer par un serveur SMTP authentifié
Un serveur SMTP authentifié règle la cause du blocage au lieu de la contourner : le script ouvre une session avec une vraie boîte du domaine, comme le ferait un client de messagerie. Le serveur de courrier de l'hébergement signe alors le message en DKIM et l'envoie depuis une IP déclarée dans le SPF. Avec la bibliothèque PHPMailer, installée par Composer, le code PHP tient en quelques lignes :
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = 'smtp.exemple.fr';
$mail->SMTPAuth = true;
$mail->Username = 'site@exemple.fr';
$mail->Password = getenv('SMTP_PASS'); // jamais en clair dans le fichier php
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->CharSet = 'UTF-8';
$mail->setFrom('site@exemple.fr', 'Formulaire du site');
$mail->addReplyTo($emailVisiteur);
$mail->addAddress('contact@exemple.fr');
$mail->Subject = 'Nouveau message du formulaire';
$mail->Body = $texte;
$mail->send();
Le port SMTP 587 correspond à la soumission de messages décrite par la RFC 6409, avec chiffrement STARTTLS ; le port 465 chiffre la connexion d'emblée. Le commentaire placé dans le code rappelle la règle : le mot de passe vit dans une variable d'environnement ou un fichier de configuration hors du dossier public. Avant de passer l'adresse du visiteur à addReplyTo(), filter_var() avec FILTER_VALIDATE_EMAIL écarte les saisies piégées. Une erreur de connexion au serveur SMTP se lit dans la propriété ErrorInfo, ou en activant SMTPDebug pendant la mise en place.
Un compte Gmail ou Google Workspace peut lui-même servir de serveur SMTP (smtp.gmail.com), avec un mot de passe d'application : la solution dépanne un petit site, mais lie l'envoi à une boîte personnelle et à ses quotas quotidiens.
Contrôler la zone DNS du domaine
Un script PHP corrigé ne suffit pas si la zone DNS du nom de domaine ne déclare pas l'expéditeur. Trois enregistrements TXT sont à vérifier :
exemple.fr. TXT "v=spf1 mx include:spf.hebergeur.example ~all"
sel1._domainkey.exemple.fr. TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkq..."
_dmarc.exemple.fr. TXT "v=DMARC1; p=none; rua=mailto:dmarc@exemple.fr"
La valeur exacte de l'include SPF et la clé publique DKIM viennent de l'hébergeur de la messagerie. La syntaxe et les pièges de la configuration SPF sont détaillés dans l'écriture d'un enregistrement SPF sans erreur, et la montée progressive de p=none vers p=quarantine dans le contenu d'un enregistrement DMARC.
Pour tester l'envoi d'un mail et lire le verdict de Gmail, il suffit d'ouvrir un message reçu puis la commande Afficher l'original : les lignes SPF, DKIM et DMARC indiquent PASS ou FAIL. Un FAIL sur DMARC avec PASS sur SPF trahit un défaut d'alignement : le domaine du From diffère de celui du Return-Path. Un domaine sur liste noire se vérifie enfin sur les sites de réputation (Spamhaus, MXToolbox) et dans les Postmaster Tools de Google, qui affichent le taux de plaintes du domaine. D'autres réglages de messagerie figurent dans la rubrique consacrée aux mails et à leurs DNS.
Sources : Google, consignes pour les expéditeurs d'e-mails (aide Google Workspace) ; RFC 7208 (SPF), RFC 6409 (soumission de messages) et RFC 5322 (format des messages) ; documentation de PHPMailer ; manuel de php.net, fonction mail().















