Это правильный способ отправить электронную почту с помощью PHP?
Я немного волнуюсь, если эта функция отправляет электронные письма, которые могут быть правильно распознаны на большинстве клиентов электронной почты и веб-почты так, как это должно быть, особенно меня больше всего волнуют эти сомнения:
- Хорошо ли сформированы декларации и вложения UTF-8?
- Нужно ли использовать quoted_printable_decode()? Если да, то где?
- Content-Transfer-Encoding: 7 или 8 бит? Я всегда видел 7, но, поскольку я отправляю почтовую кодировку UTF-8, я не уверен.
- Должен ли я использовать mb_send_mail() или достаточно mail()?
EDIT: я не знаю, почему, но код не отображается правильно, я сделал его доступным @http://gist.github.com/104818
РЕДАКТИРОВАТЬ 2: Я знаю о других альтернативах (библиотеках) для обработки электронной почты, но ради собственного любопытства и знаний я просто хочу знать, является ли этот код на 100% хорошим, или если он ошибочен.
function Email($name, $from, $to, $subject, $message, $bcc = null, $attachments = null)
{
ini_set('SMTP', 'localhost');
ini_set('sendmail_from', $from);
$name = filter_var($name, FILTER_SANITIZE_STRING);
$from = filter_var($from, FILTER_SANITIZE_EMAIL);
$subject = filter_var($subject, FILTER_SANITIZE_STRING);
$boundary = '_Boundary_' . md5(microtime(true) . mt_rand(0, PHP_INT_MAX));
$headers = array
(
'MIME-Version: 1.0',
'Content-Type: multipart/mixed; boundary="Mixed' . $boundary . '"',
'Date: ' . date('r', time()),
'From: "' . $name . '" <' . $from . '>',
'Reply-To: "' . $name . '" <' . $from . '>',
'Return-Path: "' . $name . '" <' . $from . '>',
'X-Mailer: PHP ' . phpversion(),
'X-Priority: 2',
'X-MSMail-Priority: High',
'X-Originating-IP: ' . $_SERVER['SERVER_ADDR'],
);
if (is_null($to) === false)
{
if (is_array($to) === false)
{
$to = explode(',', $to);
}
foreach ($to as $key => $value)
{
$to[$key] = filter_var($value, FILTER_SANITIZE_EMAIL);
}
$to = implode(', ', array_filter($to));
}
if (is_null($bcc) === false)
{
if (is_array($bcc) === false)
{
$bcc = explode(',', $bcc);
}
foreach ($bcc as $key => $value)
{
$bcc[$key] = filter_var($value, FILTER_SANITIZE_EMAIL);
}
$headers[] = 'BCC: ' . implode(', ', array_filter($bcc));
}
if (is_null($attachments) === false)
{
settype($attachments, 'array');
foreach ($attachments as $key => $value)
{
if (is_file($value) === true)
{
$attachments[$key] = array
(
'',
'--Mixed' . $boundary,
'Content-Type: application/octet-stream; name="' . basename($value) . '"',
'Content-Disposition: attachment; filename="' . basename($value) . '"',
'Content-Transfer-Encoding: base64',
'',
trim(chunk_split(base64_encode(file_get_contents($value)))),
);
$attachments[$key] = implode("\n", $attachments[$key]);
}
else
{
unset($attachments[$key]);
}
}
$attachments = implode("\n", $attachments) . "\n";
}
$message = array
(
'This is a multi-part message in MIME format.',
'',
'--Mixed' . $boundary,
'Content-Type: multipart/alternative; boundary="Alt' . $boundary . '"',
'',
'--Alt' . $boundary,
'Content-Type: text/plain; charset="UTF-8"',
'Content-Disposition: inline',
'Content-Transfer-Encoding: 8bit',
'',
trim(strip_tags($message, '<a>')),
'',
'--Alt' . $boundary,
'Content-Type: text/html; charset="UTF-8"',
'Content-Disposition: inline',
'Content-Transfer-Encoding: 8bit',
'',
trim($message),
'',
'--Alt' . $boundary . '--',
$attachments,
'--Mixed' . $boundary . '--',
);
if (@mail($to, stripslashes($subject), implode("\n", $message), implode("\n", $headers)) === true)
{
return true;
}
return false;
}
Ответы
Ответ 1
В то время как это должно работать, я настоятельно рекомендую использовать предварительно построенный класс Mail/SMTP, например Zend_Mail. Хотя я не думаю, что вся Zend Framework является пижамой для кошек, у меня есть очень хорошее мнение об их почтовом коде.
EDIT: Я также должен добавить, что использование предварительно созданного класса Mail/SMTP абстрагирует почти всю сложность/структуру многочастных электронных писем.
Обновление 2009-05-06: Отвечая на ваш вопрос напрямую.
- Хорошо ли сформированы декларации и вложения UTF-8?
Они выглядят достаточно прилично.
- Нужно ли использовать
quoted_printable_decode()
? Если да, то где?
Нет. Вы хотите использовать quoted_printable_decode()
только в том случае, если вы декодируете сообщение электронной почты. Не когда вы его кодируете. Если вы используете quoted_printable_encode()
? Я расскажу об этом дальше.
- Content-Transfer-Encoding: 7 или 8 бит? Я всегда видел 7, но, поскольку я отправляю почтовую кодировку UTF-8, я не уверен.
Используйте только 8-битную кодировку, если вы знаете, что целевой SMTP-сервер может ее поддерживать. Однако, поскольку вы отправляете свою электронную почту в локальный MTA, я бы не рекомендовал устанавливать это значение. Значение по умолчанию - 7-битное кодирование, но у него есть собственный набор ограничений: до 998 октетов на строку диапазона кода 1-127 с CR и LF разрешено появляться как часть окончания строки CRLF (http://tools.ietf.org/html/rfc2045#section-2.7).
Я бы порекомендовал вам использовать Quoted-Printable (http://tools.ietf.org/html/rfc2045#section-6.7) Content-Transfer-Encoding. Если вы вызываете trim(strip_tags($message, '<a>'))
и trim($message)
, вам нужно заключить их в quoted_printable_encode(trim(...))
.
- Должен ли я использовать
mb_send_mail()
или mail()
достаточно?
Если вы знаете, что вы не будете обрабатывать многобайтовые сообщения (японский, корейский, китайский и т.д.), тогда mail()
должно быть достаточно.
Теперь, когда я ответил на ваши начальные вопросы, позвольте мне рассказать вам, где существуют некоторые проблемы.
- Вы указываете, что набор символов ваших частей контента Plain Text и Html является UTF-8, однако он не отображается, поскольку вы на самом деле гарантируете, что они действительно кодируются в кодировке UTF-8.
- Вы проверяете
null
в $to
, $bcc
, $attachments
перед тем, как продолжить их обработку, однако вы ничего не делаете, когда они могут быть null
. Итак, если вы получили null
для $to
, вы не обрабатываете эту переменную, но продолжаете отправлять электронное письмо на адрес null
.
Как сейчас, все, что я собираюсь войти, но я по-прежнему очень рекомендую готовое решение, так как у них было много пользователей/время для разработки ошибок.
Ответ 2
В большинстве случаев я все катаюсь на своем, но когда дело доходит до почты, я бы от души рекомендовал облегчить себе и использовать что-то вроде Swift Mailer или PHPMailer (в этом порядке за мои деньги).
Как бонусный бонус (и если вы укажете ответ и т.д.), у вас также будет гораздо меньше шансов быть помеченным как спам.