Резюме
Из-за ошибки в 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()
функция является подключаемой, не означает ли ее замену как обязательный плагин (в wp-content / mu-plugins), не является ли хорошим решением для вас (и для всех остальных неудачное исправление ядра)? В каком случае не сработает проверка$phpmailer->ContentType = $content_type;
множественности / границы после установки (а не удаления)?wp_mail
оно подключаемо . Скопируйте оригинальную функцию в плагин, отредактируйте ее, как вам нужно, и активируйте плагин. WordPress будет использовать вашу отредактированную функцию вместо оригинальной, без необходимости редактировать ядро.Ответы:
Следующая версия
wp_mail()
представляет собой патч, примененный @ rmccue / @ MattyRob в билете https://core.trac.wordpress.org/ticket/15448 , обновленный для 4.2.2, который позволяет$message
быть массивом, содержащим тип содержимого ключевые ключи:Так что, если вы поместите это в ваш файл, например, "wp-content / mu-plugins / functions.php", он переопределит версию WP. Он имеет хорошее использование без каких-либо возни с заголовками, например:
Обратите внимание, я не проверял это с реальными электронными письмами ...
источник
На самом деле это не ошибка WordPress, это проблема запрета
phpmailer
пользовательских заголовков ... если вы посмотрите наclass-phpmailer.php
:Вы можете видеть, что ошибочный случай по умолчанию - это то, что выводит дополнительную строку заголовка с набором символов и без границы. Установка типа контента с помощью фильтра сама по себе не решает эту проблему только потому, что
alt
случай, заданный здесьmessage_type
, проверяетсяAltBody
не пустым, а типом контента.В конце концов, это означает, что, как только вы прикрепите файл или встроенное изображение или установите его
AltBody
, оскорбительную ошибку следует обойти. Это также означает, что нет необходимости явно устанавливать тип контента, потому что, как только есть,AltBody
он устанавливается наmultipart/alternative
наphpmailer
.Итак, простой ответ:
Тогда вам не нужно явно устанавливать заголовки, вы можете просто сделать:
К сожалению, многие функции и свойства в
phpmailer
классе защищены, если бы не это, допустимой альтернативой было бы просто проверить и переопределитьMIMEHeaders
свойство с помощьюphpmailer_init
ловушки перед отправкой.источник
Я только что выпустил плагин, позволяющий пользователям использовать HTML-шаблоны на WordPress, и я сейчас играю на dev-версии, чтобы добавить простой текстовый запасной вариант. Я сделал следующее, и в своих тестах я увидел только одну добавленную границу, и письма в Hotmail приходят нормально.
В общем, что я здесь делаю, это модифицирую объект phpmailer, загружаю сообщение в html-шаблон и устанавливаю для него свойство Body. Также я взял исходное сообщение и установил свойство AltBody.
источник
Мое простое решение - использовать html2text https://github.com/soundasleep/html2text следующим образом:
Здесь https://gist.github.com/ewake/6c4d22cd856456480bd77b988b5c9e80 также суть о.
источник
Для тех, кто использует ловушку phpmailer_init, чтобы добавить свою собственную AltBody:
Альтернативное текстовое тело используется повторно для разных последовательных отправляемых писем, если вы не очистите его вручную! WordPress не очищает его в wp_mail (), потому что не ожидает использования этого свойства.
Это приводит к тому, что получатели могут получать письма, не предназначенные для них. К счастью, большинство людей, использующих почтовые клиенты с поддержкой HTML, не увидят текстовую версию, но в основном это проблема безопасности.
К счастью, это легко исправить. Это включает бит замены altbody; обратите внимание, что вам нужна PHP-библиотека Html2Text:
Вот также суть плагина WP, который я модифицировал для решения этой проблемы: https://gist.github.com/youri--/c4618740b7c50c549314eaebc9f78661
К сожалению, я не могу комментировать другие решения, используя вышеупомянутую ловушку, чтобы предупредить их об этом, поскольку у меня еще недостаточно представителей, чтобы комментировать.
источник
это может быть не точный ответ на первоначальный пост здесь, но это альтернатива некоторым решениям, представленным здесь, относительно установки alt body
по сути, мне нужно (хотелось) установить отдельное altbody (т.е. открытый текст) дополнительно к html-части вместо того, чтобы полагаться на некоторые преобразования / стрип-теги и еще много чего. так что я пришел с этим, который, кажется, работает просто отлично
источник
Если вы не хотите создавать какой-либо конфликт кода в ядре Wordpress, я думаю, что альтернативное или самое простое решение - добавить действие,
phpmailer_init
которое будет сделано до фактической отправки почты вwp_mail
. Чтобы упростить мое объяснение, посмотрите пример кода ниже:Если вы добавите контент в
AltBody
свойство класса PHPMailer, тип контента по умолчанию будет автоматически установлен наmultipart/alternative
.источник