Это правильный способ отправки электронной почты с помощью PHP? - PullRequest
16 голосов
/ 01 мая 2009

Я немного волнуюсь, если эта функция отправляет электронные письма, которые могут быть правильно распознаны на большинстве почтовых и веб-почтовых клиентов, так, как это должно быть, особенно меня больше всего беспокоит этот вопрос:

  • Правильно ли сформированы декларации и приложения UTF-8?
  • Нужно ли использовать quoted_printable_decode ()? Если да, то где?
  • Content-Transfer-Encoding: 7 или 8 бит? Я всегда видел 7, но так как я отправляю почту в кодировке UTF-8, я не уверен.
  • Должен ли я использовать mb_send_mail () или mail () достаточно?

РЕДАКТИРОВАТЬ: я не знаю, почему, но код не отображается правильно, я сделал его доступным @ 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;
}

Ответы [ 2 ]

27 голосов
/ 01 мая 2009

Хотя это должно работать, я настоятельно рекомендую использовать готовый класс Mail / SMTP, такой как Zend_Mail . Хотя я не думаю, что вся Zend Framework - это кошачья пижама, у меня очень хорошее мнение об их коде обработки почты.

РЕДАКТИРОВАТЬ: Я также должен добавить, что использование готового класса 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().

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

  1. Вы указываете, что набор символов ваших частей с простым текстом и Html-содержимым имеет формат UTF-8, однако он не отображается, поскольку вы фактически гарантируете, что они действительно имеют кодировку UTF-8.
  2. Вы проверяете null в $to, $bcc, $attachments перед дальнейшей их обработкой, однако вы ничего не делаете, когда они на самом деле могут быть null. Таким образом, если вы получили null для $to, вы не обработаете переменную, но продолжите отправлять электронное письмо на null.

На данный момент это все, что я собираюсь рассмотреть, но я все еще собираюсь настоятельно рекомендовать предварительно построенное решение, поскольку у них было много пользователей / времени для устранения ошибок.

17 голосов
/ 01 мая 2009

В большинстве случаев я полностью за себя, но когда дело доходит до почты, я от всей души рекомендую облегчить себе задачу и использовать что-то вроде Swift Mailer или PHPMailer (в таком порядке, за мои деньги).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...