Sommaire
En raison d'un bogue dans WP de base, l' envoi multipart e - mails (html / texte) avec wp_mail () (pour réduire la chance d'e - mails qui se terminent dans les dossiers de spam) sera ironiquement résultat avec votre domaine bloqué par Hotmail (et d' autres e - mails Microsoft).
C’est un problème complexe que je vais tenter d’exploiter de manière très détaillée pour tenter d’aider une personne à trouver une solution viable pouvant éventuellement être mise en œuvre de manière centralisée.
Ce sera une lecture enrichissante. Commençons...
L'insecte
Le conseil le plus courant pour éviter que vos e-mails de bulletin d'information finissent dans des dossiers de courrier indésirable est d'envoyer des messages en plusieurs parties.
Multi-part (mime) fait référence à l'envoi simultané d'une partie HTML et d'une partie TEXT d'un message électronique. Lorsqu'un client reçoit un message en plusieurs parties, il accepte la version HTML s'il peut restituer le code HTML. Sinon, il présente la version en texte brut.
Ceci est prouvé pour fonctionner. Lors de l'envoi à gmail, tous nos courriels se retrouvaient dans des dossiers de courrier indésirable jusqu'à ce que nous changions les messages en plusieurs parties lorsqu'ils arrivaient dans la boîte de réception principale. Super truc.
Désormais, lors de l'envoi de messages en plusieurs parties via wp_mail (), le type de contenu (multipart / *) est généré deux fois, une fois avec une limite (si défini de manière personnalisée) et une fois sans. Ce comportement a pour résultat que l'e-mail est affiché en tant que message brut et non en plusieurs parties sur certains courriels, y compris tous les Microsoft (Hotmail, Outlook, etc.).
Microsoft signalera ce message comme courrier indésirable et les quelques messages reçus seront signalés manuellement par le destinataire. Malheureusement , les adresses électroniques de Microsoft sont largement utilisées. 40% de nos abonnés l'utilisent.
Ceci est confirmé par Microsoft via un échange de courrier électronique que nous avons eu récemment.
Le signalement des messages entraînera le blocage complet du domaine . Cela signifie que le message ne sera pas envoyé dans le dossier spam, ils ne seront même pas remis au destinataire.
Nous avons eu notre domaine principal bloqué 3 fois jusqu'à présent.
Comme il s’agit d’un bogue dans le noyau de WP, chaque domaine qui envoie des messages en plusieurs parties est bloqué. Le problème est que la plupart des webmasters ne savent pas pourquoi. Je l'ai confirmé lors de mes recherches et lorsque j'ai vu d'autres utilisateurs en discuter sur des forums, etc. Cela nécessite de fouiller dans le code brut et de bien connaître le fonctionnement de ce type de messages électroniques, que nous passons ensuite à ...
Décomposons en code
Créez un compte hotmail / outlook. Ensuite, exécutez le code suivant:
// Set $to to an hotmail.com or outlook.com email
$to = "YourEmail@hotmail.com";
$subject = 'wp_mail testing multipart';
$message = '------=_Part_18243133_1346573420.1408991447668
Content-Type: text/plain; charset=UTF-8
Hello world! This is plain text...
------=_Part_18243133_1346573420.1408991447668
Content-Type: text/html; charset=UTF-8
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<p>Hello World! This is HTML...</p>
</body>
</html>
------=_Part_18243133_1346573420.1408991447668--';
$headers = "MIME-Version: 1.0\r\n";
$headers .= "From: Foo <foo@bar.com>\r\n";
$headers .= 'Content-Type: multipart/alternative;boundary="----=_Part_18243133_1346573420.1408991447668"';
// send email
wp_mail( $to, $subject, $message, $headers );
Et si vous souhaitez modifier le type de contenu par défaut , utilisez:
add_filter( 'wp_mail_content_type', 'set_content_type' );
function set_content_type( $content_type ) {
return 'multipart/alternative';
}
Cela enverra un message en plusieurs parties.
Ainsi, si vous vérifiez la source brute complète du message, vous remarquerez que le type de contenu est ajouté deux fois, une fois sans limite:
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="====f230673f9d7c359a81ffebccb88e5d61=="
MIME-Version: 1.0
Content-Type: multipart/alternative; charset=
C'est le problème.
La source du problème réside dans pluggable.php
- si nous regardons quelque part ici:
// Set Content-Type and charset
// If we don't have a content-type from the input headers
if ( !isset( $content_type ) )
$content_type = 'text/plain';
/**
* Filter the wp_mail() content type.
*
* @since 2.3.0
*
* @param string $content_type Default wp_mail() content type.
*/
$content_type = apply_filters( 'wp_mail_content_type', $content_type );
$phpmailer->ContentType = $content_type;
// Set whether it's plaintext, depending on $content_type
if ( 'text/html' == $content_type )
$phpmailer->IsHTML( true );
// If we don't have a charset from the input headers
if ( !isset( $charset ) )
$charset = get_bloginfo( 'charset' );
// Set the content-type and charset
/**
* Filter the default wp_mail() charset.
*
* @since 2.3.0
*
* @param string $charset Default email charset.
*/
$phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
// Set custom headers
if ( !empty( $headers ) ) {
foreach( (array) $headers as $name => $content ) {
$phpmailer->AddCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
}
if ( false !== stripos( $content_type, 'multipart' ) && ! empty($boundary) )
$phpmailer->AddCustomHeader( sprintf( "Content-Type: %s;\n\t boundary=\"%s\"", $content_type, $boundary ) );
}
if ( !empty( $attachments ) ) {
foreach ( $attachments as $attachment ) {
try {
$phpmailer->AddAttachment($attachment);
} catch ( phpmailerException $e ) {
continue;
}
}
}
Solutions potentielles
Vous vous demandez donc pourquoi vous n'avez pas signalé cela à Trac ? J'ai déjà . À ma grande surprise, un billet différent a été créé il y a 5 ans, soulignant le même problème.
Regardons les choses en face, cela fait une demi-décennie. Dans les années Internet, cela correspond plus à 30 ans. Le problème a clairement été abandonné et ne sera fondamentalement jamais résolu (... sauf si nous le résolvons ici).
J'ai trouvé ici un bon fil offrant une solution, mais si sa solution fonctionne, elle casse les courriers électroniques qui n'ont pas de $headers
configuration personnalisée .
C'est là que nous nous écrasons à chaque fois. Soit la version en plusieurs parties fonctionne bien, et les $headers
messages normaux non définis ne le sont pas, soit un verset.
La solution que nous avons trouvée était:
if ( false !== stripos( $content_type, 'multipart' ) && ! empty($boundary) ) {
$phpmailer->ContentType = $content_type . "; boundary=" . $boundary;
}
else {
$content_type = apply_filters( 'wp_mail_content_type', $content_type );
$phpmailer->ContentType = $content_type;
// Set whether it's plaintext, depending on $content_type
if ( 'text/html' == $content_type )
$phpmailer->IsHTML( true );
// If we don't have a charset from the input headers
if ( !isset( $charset ) )
$charset = get_bloginfo( 'charset' );
}
// Set the content-type and charset
/**
* Filter the default wp_mail() charset.
*
* @since 2.3.0
*
* @param string $charset Default email charset.
*/
$phpmailer->CharSet = apply_filters( 'wp_mail_charset', $charset );
// Set custom headers
if ( !empty( $headers ) ) {
foreach( (array) $headers as $name => $content ) {
$phpmailer->AddCustomHeader( sprintf( '%1$s: %2$s', $name, $content ) );
}
}
Oui, je sais, éditer des fichiers core est tabou, asseyez-vous… c’était un correctif désespéré et une mauvaise tentative de fournir un correctif pour le core.
Le problème avec notre solution est que les emails par défaut tels que les nouvelles inscriptions, les commentaires, la réinitialisation du mot de passe, etc. seront livrés sous forme de messages vierges. Nous avons donc un script de travail wp_mail () qui envoie des messages en plusieurs parties, mais rien d’autre.
Que faire
Le but ici est de trouver un moyen d’envoyer des messages normaux (texte brut) et multipart à l’aide de la fonction principale wp_mail () (et non d’une fonction sendmail personnalisée).
Lorsque vous tentez de résoudre ce problème, le principal problème que vous rencontrerez est le temps que vous passerez à envoyer des messages factices, à vérifier s'ils sont reçus et à ouvrir une boîte d'aspirine et à maudire Microsoft car vous êtes habitué à leurs messages. Problèmes IE alors que le gremlin ici est malheureusement WordPress.
Mise à jour
La solution publiée par @bonger permet $message
d’être un tableau contenant des substituts avec une clé de type contenu. J'ai confirmé que cela fonctionne dans tous les scénarios.
Nous laisserons cette question ouverte jusqu'à épuisement des primes pour sensibiliser le public au problème, peut - être à un niveau où elles seront résolues de manière fondamentale. N'hésitez pas à poster une solution alternative où $message
peut être une chaîne.
wp_mail
est connectable . Copiez la fonction originale dans un plugin, modifiez-la comme vous le souhaitez et activez le plugin. WordPress utilisera votre fonction modifiée au lieu de celle d'origine, sans avoir besoin de modifier le coeur.
wp_mail()
fonction est connectable, votre remplaçant n'est pas défini comme un plug-in à utiliser absolument (dans wp-content / mu-plugins), ce n'est pas une bonne solution pour vous (et tous les autres, le correctif principal défaillant)? Dans quel cas le déplacement de la vérification multipartie / limite après réglage$phpmailer->ContentType = $content_type;
(plutôt que elsing) ne fonctionnerait-il pas?