Резюме
Из-за ошибки в WP Core отправка составных писем (html / text) с помощью wp_mail () (чтобы уменьшить вероятность попадания писем в папки со спамом) будет иронично приведет к тому, что ваш домен будет заблокирован Hotmail (и другими электронными письмами Microsoft).
Это сложная проблема, которую я постараюсь подробно описать, пытаясь помочь кому-то найти работоспособное решение, которое в конечном итоге может быть реализовано в ядре.
Это будет полезное чтение. Давайте начнем...
Ошибка
Самый распространенный совет, чтобы избежать попадания электронных писем в новостные рассылки в спам-папки, - отправлять многочастные сообщения.
Multi-part (mime) относится к отправке как HTML, так и TEXT части сообщения электронной почты в одном письме. Когда клиент получает составное сообщение, он принимает версию HTML, если он может отображать HTML, в противном случае он представляет версию в виде простого текста.
Это доказано, чтобы работать. При отправке в gmail все наши электронные письма помещались в папки со спамом, пока мы не изменили сообщения на multipart, когда они пришли в основной почтовый ящик. Отличный материал.
Теперь при отправке многокомпонентных сообщений через wp_mail (), он выводит тип контента (multipart / *) дважды, один раз с границей (если установлен отдельно) и один раз без. Это приводит к тому, что электронное письмо отображается в виде необработанного сообщения, а не в нескольких сообщениях в некоторых электронных письмах, включая все Microsoft (Hotmail, Outlook и т. Д.)
Microsoft пометит это сообщение как нежелательное, а полученное сообщение будет помечено получателем вручную. К сожалению , адреса электронной почты Microsoft широко используются. 40% наших подписчиков используют его.
Это подтверждается Microsoft через обмен электронной почтой, который мы недавно имели.
Пометка сообщений приведет к полной блокировке домена . Это означает, что сообщение не будет отправлено в папку со спамом, оно даже не будет доставлено получателю вообще.
Наш основной домен заблокирован 3 раза.
Поскольку это ошибка в ядре WP, каждый домен, отправляющий многокомпонентные сообщения, блокируется. Проблема в том, что большинство веб-мастеров не знают почему. Я подтвердил это, когда проводил свои исследования и видел, как другие пользователи обсуждают это на форумах и т. Д. Это требует углубленного изучения необработанного кода и хорошего знания того, как работает этот тип почтовых сообщений, о чем мы поговорим далее ...
Давайте разбить его на код
Создать учетную запись Hotmail / Outlook. Затем запустите следующий код:
// 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 );
И если вы хотите изменить тип содержимого по умолчанию , используйте:
add_filter( 'wp_mail_content_type', 'set_content_type' );
function set_content_type( $content_type ) {
return 'multipart/alternative';
}
Это отправит многокомпонентное сообщение.
Поэтому, если вы проверите полный необработанный источник сообщения, вы заметите, что тип контента добавляется дважды, один раз без границ:
MIME-Version: 1.0
Content-Type: multipart/alternative;
boundary="====f230673f9d7c359a81ffebccb88e5d61=="
MIME-Version: 1.0
Content-Type: multipart/alternative; charset=
Это проблема.
Источник проблемы лежит в pluggable.php
- если мы посмотрим где-то здесь:
// 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;
}
}
}
Потенциальные решения
Итак, вы задаетесь вопросом, почему вы не сообщили об этом на трассе ? Я уже есть . К моему большому удивлению, 5 лет назад был создан другой билет с изложением той же проблемы.
Посмотрим правде в глаза, это было пол десятилетия. В интернет-годы это больше похоже на 30. Проблема явно была оставлена и в основном никогда не будет решена (... если мы не решим ее здесь).
Я нашел отличную ветку, предлагающую решение, но пока его решение работает, оно ломает электронные письма, которые не имеют пользовательского $headers
набора.
Вот где мы терпим крах каждый раз. Либо многочастная версия работает нормально, а обычные незаданные $headers
сообщения - нет, либо стихи.
Решение, которое мы нашли, было:
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 ) );
}
}
Да, я знаю, редактирование файлов ядра является табу, сидеть сложа руки ... это было отчаянное исправление и плохая попытка предоставить исправление для ядра.
Проблема с нашим исправлением состоит в том, что электронные письма по умолчанию, такие как новые регистрации, комментарии, сброс пароля и т. Д., Будут доставляться как пустые сообщения. Итак, у нас есть рабочий скрипт wp_mail (), который будет отправлять многокомпонентные сообщения, но не более того
Что делать
Цель здесь - найти способ отправки как обычных (в виде обычного текста), так и составных сообщений, используя базовую функцию wp_mail () (а не пользовательскую функцию sendmail).
При попытке решить эту проблему, основная проблема, с которой вы столкнетесь, - это количество времени, которое вы потратите на отправку фиктивных сообщений, проверку их получения и, в основном, открытие ящика аспирина и проклятия в Microsoft, потому что вы привыкли к их IE выдает, в то время как гремлин здесь, к сожалению, WordPress.
Обновить
Решение, опубликованное @bonger, позволяет $message
создать массив, содержащий альтернативы с ключом типа содержимого. Я подтвердил, что это работает во всех сценариях.
Мы позволим этому вопросу оставаться открытым до тех пор, пока щедрость не иссякнет, чтобы повысить осведомленность о проблеме, возможно, до уровня, на котором она будет решена в основном. Не стесняйтесь размещать альтернативное решение, где $message
может быть строка.
wp_mail
оно подключаемо . Скопируйте оригинальную функцию в плагин, отредактируйте ее, как вам нужно, и активируйте плагин. WordPress будет использовать вашу отредактированную функцию вместо оригинальной, без необходимости редактировать ядро.
wp_mail()
функция является подключаемой, не означает ли ее замену как обязательный плагин (в wp-content / mu-plugins), не является ли хорошим решением для вас (и для всех остальных неудачное исправление ядра)? В каком случае не сработает проверка$phpmailer->ContentType = $content_type;
множественности / границы после установки (а не удаления)?