【问题标题】:Is this the correct way to send email with PHP?这是用 PHP 发送电子邮件的正确方法吗?
【发布时间】:2010-10-23 00:50:20
【问题描述】:

如果这个功能发送的电子邮件可以在大多数电子邮件和网络邮件客户端上正确识别,我有点担心,特别是我最担心这个疑问:

  • UTF-8 声明和附件格式是否正确?
  • 我需要使用quoted_printable_decode()吗?如果有,在哪里?
  • 内容传输编码: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;
}

【问题讨论】:

    标签: php email encoding utf-8


    【解决方案1】:

    虽然这应该可行,但我强烈建议使用预构建的 Mail/SMTP 类,例如 Zend_Mail。虽然我不认为整个 Zend Framework 就是猫的睡衣,但我确实对他们的邮件处理代码有很好的看法。

    编辑:我还应该补充一点,使用预构建的 Mail/SMTP 类将抽象多部分电子邮件的几乎所有复杂性/结构。

    2009-05-06 更新:直接回答您的问题。

    • UTF-8 声明和附件格式是否正确?

    它们看起来足够体面。

    • 我需要使用quoted_printable_decode()吗?如果有,在哪里?

    没有。只有在解码电子邮件消息时,您才需要使用quoted_printable_decode()。不是当你编码一个。你应该使用 quoted_printable_encode() 吗?接下来我会讨论这个。

    • 内容传输编码:7 位还是 8 位?我一直看到 7,但由于我发送的是 UTF-8 编码的邮件,所以我不确定。

    如果您知道目标 SMTP 服务器可以支持,则仅使用 8 位编码。但是,由于您将电子邮件传递给本地 MTA,因此我不建议设置此值。默认值为 7 位编码,但它有自己的一组限制:代码范围 1-127 的每行最多 998 个八位字节,CR 和 LF 只允许作为 CRLF 行结尾的一部分出现 (https://www.rfc-editor.org/rfc/rfc2045#section-2.7)。

    我建议您使用 Quoted-Printable (https://www.rfc-editor.org/rfc/rfc2045#section-6.7) 内容传输编码。在您调用trim(strip_tags($message, '&lt;a&gt;'))trim($message) 的地方,您需要用quoted_printable_encode(trim(...)) 括起来。

    • 我应该使用mb_send_mail() 还是mail() 就足够了?

    如果您知道自己不会处理多字节消息(日语、韩语、中文等),那么mail() 就足够了。

    现在我已经回答了您最初的问题,让我告诉您存在哪些问题。

    1. 您指定纯文本和 Html 内容部分的字符集为 UTF-8,但它并未显示,因为您实际上确保它们确实是 UTF-8 编码。
    2. 在进一步处理它们之前,您正在检查$to$bcc$attachments 中的null,但是,当它们实际上可能是null 时,您什么也没做。因此,如果您碰巧收到null 对应的$to,则不会处理该变量,而是继续向null 发送电子邮件。

    到目前为止,这就是我要介绍的全部内容,但我仍然强烈推荐一个预构建的解决方案,因为他们有很多用户/时间来解决错误。

    【讨论】:

    • 我同意,Zend_Mail 拥有您需要的一切,甚至更多!使用多人开发的库,一般错误少。
    • “如果你知道你不会处理多字节消息(日文、韩文、中文等),那么 mail() 就足够了。” - 其他语言的信息,如德语、法语、葡萄牙语和西班牙语? mail() 还够用吗?
    • 真正归结为字符编码。如果您使用 UTF-8 进行字符编码(HTTP GET/POST、数据库等),则使用 mail() 可以正常工作,因为它是单字节的。另一方面,UTF-16/UCS-2 是多字节的,需要使用 mb_send_mail()。
    【解决方案2】:

    在大多数情况下,我完全支持自己滚动,但在邮件方面,我衷心建议让自己更轻松,并使用Swift MailerPHPMailer 之类的东西(按此顺序,对于我的钱)。

    作为附带奖励(假设您指定回复等),您被标记为垃圾邮件的机会也大大减少。

    【讨论】:

    • 嗯.. 我从来没有听说过 Swift Mailer,但是在阅读了文档之后,我将不得不开始考虑它而不是 Zend_Mail。谢谢(你的)信息。 +1
    • 是的。我真的可以推荐 PHPMailer!它为我做了很多次很棒的工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-19
    • 1970-01-01
    • 2018-01-21
    • 2013-09-04
    • 2012-08-31
    • 1970-01-01
    相关资源
    最近更新 更多