Случайные символы HTML, закодированные в электронных письмах

Я генерирую письмо с PHP, который выводит таблицу HTML. Большая часть таблицы проходит нормально, но некоторые из < а также > символы случайным образом кодируются в &lt; а также &gt;, Это не всегда делает это в одном и том же месте. Иногда это просто происходит в одном месте, иногда нет вообще, а иногда в нескольких местах.

Вот фрагмент кода из середины моей таблицы, как его видит мой почтовый клиент. Обратите внимание на вставленный &lt; /tr&gt; этого не должно быть

<tr>  
  <td>SERVER_SOFTWARE</td>
  <td>Apache/2.2.29 (Red Hat)</td>
</tr>
<tr>
  <td>SERVER_PROTOCOL</td>
  <td>HTTP/1.1</td>
  &lt; /tr&gt;
</tr>
<tr>
  <td>REQUEST_METHOD</td>
  <td>POST</td>
</tr>

И тот же сегмент в текстовой части письма: (опять же, обратите внимание, что </tr> как-то вставляется.)

SERVER_SOFTWARE Apache/2.2.29 (Red Hat)
SERVER_PROTOCOL HTTP/1.1 < /tr>
REQUEST_METHOD POST

Я устанавливаю это в UTF-8 в заголовках перед отправкой:

$headers  = "MIME-Version: 1.0\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Transfer-Encoding: quoted-printable";

(PS У меня была точно такая же проблема ранее, используя charset=ISO-8859-1.)

Но, несмотря на это, это как-то отображается в US-ASCII:

Content-type: text/html;
    charset="US-ASCII"
Content-transfer-encoding: quoted-printable

Сценарий PHP, который генерирует электронную почту, выглядит следующим образом:

//generate $table
$indicesServer = array('PHP_SELF', 'argv', 'argc', 'GATEWAY_INTERFACE', 'SERVER_ADDR', 'SERVER_NAME', 'SERVER_SOFTWARE', 'SERVER_PROTOCOL', 'REQUEST_METHOD', 'REQUEST_TIME', 'REQUEST_TIME_FLOAT', 'QUERY_STRING', 'DOCUMENT_ROOT', 'HTTP_ACCEPT', 'HTTP_ACCEPT_CHARSET', 'HTTP_ACCEPT_ENCODING', 'HTTP_ACCEPT_LANGUAGE', 'HTTP_CONNECTION', 'HTTP_HOST', 'HTTP_REFERER', 'HTTP_USER_AGENT', 'HTTPS', 'REMOTE_ADDR', 'REMOTE_HOST', 'REMOTE_PORT', 'REMOTE_USER', 'REDIRECT_REMOTE_USER', 'SCRIPT_FILENAME', 'SERVER_ADMIN', 'SERVER_PORT', 'SERVER_SIGNATURE', 'PATH_TRANSLATED', 'SCRIPT_NAME', 'REQUEST_URI', 'PHP_AUTH_DIGEST', 'PHP_AUTH_USER', 'PHP_AUTH_PW', 'AUTH_TYPE', 'PATH_INFO', 'ORIG_PATH_INFO') ;
$table = '<table cellpadding="3" cellspacing="0" border="1" bordercolor="#bbb">';
foreach ($indicesServer as $arg) {
    if (isset($_SERVER[$arg])) {
        $table .= '<tr><td>'.$arg.'</td><td>' . $_SERVER[$arg] . '</td></tr>' ;
    } else {
        $table .= '<tr><td>'.$arg.'</td><td>-</td></tr>' ;
    }
}
$table .=  '</table>' ;

//set up email
$to = [redacted];
$subject = [redacted];
$email_body = "Heres data:" . $table;
$headers  = "MIME-Version: 1.0\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Transfer-Encoding: quoted-printable";

//send email
mail($to, $subject, $email_body, $headers);

РЕДАКТИРОВАТЬ: я заметил, что атрибуты HTML портятся. Это связано с quoted-printable кодирование знаков равенства. = закодирован в =3D как и ожидалось, но иногда следующий символ удаляется! Таким образом происходит следующее:

<a href="http://example.com">становится<a href=3D"ttp://example.com">

<table cellpadding=3 cellspacing=0 border=1>становится<table cellpadding<ellspacingorder=3D"&lt;tr">

2 ответа

Решение

Я предполагаю, что поскольку это закрывающее "tr", которого не должно быть (у вас есть еще один сразу после него), какой-то дружественный html-парсер "помогает" вам, превращаясь из тега в обычную строку.

Еще одна мысль:

Смотрите здесь: https://support.sendgrid.com/hc/en-us/articles/200182068-HTML-Formatting-Issues

  1. Некоторые почтовые клиенты, такие как Outlook и Thunderbird, по-видимому, вставляют двойные межстрочные разрывы в каждой строке. Причина в том, что для "content-Transfer-Encoding" в MIME установлено значение "quoted-printable", которое добавляет разрывы строки перевода строки (CRLF) к исходному контенту электронной почты, которые представляют собой символы, интерпретируемые этими почтовыми клиентами. Чтобы решить эту проблему, сделайте следующее:

а. Если вы можете настроить параметры MIME для своей электронной почты, установите "Content-Transfer-Encoding" на "7bit" вместо "Quoted-Printable".

б. Убедитесь, что ваш контент соответствует ограничениям длины строки из пункта 2 выше.

Интересно, если что-то ставит разрыв в вашем теге, что делает его нечитаемым, то браузер добавляет дополнительный в качестве замены.

Можете ли вы попробовать это: измените "Content-Transfer-Encoding" на "7bit" или оставьте его полностью?

Проблема может быть связана со специальными символами HTML, которые находятся в значениях, которые вы вставляете. Когда вы вставляете случайный текст в HTML и не хотите, чтобы он интерпретировался как HTML, вы должны использовать htmlentities или же htmlspecialchars закодировать это:

foreach ($indicesServer as $arg) {
    if (isset($_SERVER[$arg])) {
        $table .= '<tr><td>'.$arg.'</td><td>' . htmlentities($_SERVER[$arg]) . '</td></tr>' ;
    } else {
        $table .= '<tr><td>'.$arg.'</td><td>-</td></tr>' ;
    }
}

Другая возможность заключается в том, что ваши строки слишком длинные для почтового программного обеспечения. Попробуйте добавить "\n" в конце каждой строки таблицы:

$table .= '<tr><td>'.$arg.'</td><td>' . htmlentities($_SERVER[$arg]) . "</td></tr>'."\n" ;
Другие вопросы по тегам