Подтвердить что ты не робот

Это правильный способ отправить электронную почту с помощью 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;
}
4b9b3361

Ответ 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 (в этом порядке за мои деньги).

Как бонусный бонус (и если вы укажете ответ и т.д.), у вас также будет гораздо меньше шансов быть помеченным как спам.