PHPMailer 的 mail、sendmail 与 SMTP 三种发送方式怎么选?
【免费下载链接】PHPMailerThe classic email sending library for PHP项目地址: https://gitcode.com/GitHub_Trending/ph/PHPMailer
PHPMailer 支持三种邮件传输方式:调用 PHP 内置的mail()函数、直接执行本机的 sendmail 程序、以及通过内置 SMTP 客户端连接 SMTP 服务器。三种方式写邮件内容的代码几乎一样,差别只在“如何把消息交给传输系统”。如果你正在 PHP 项目里集成 PHPMailer,需要在动手前确定用哪一种,这篇文章基于仓库内的examples/示例和 README,给出三种方式各自的前提条件、官方示例代码和验证方式,帮你按运行环境做出选择。
适用前提:PHP 5.5 及以上(README 说明兼容至 PHP 8.2),推荐通过 Composer 安装。当前仓库版本号为 6.9.3(见 VERSION)。
先安装 PHPMailer
无论选哪种传输方式,加载方式相同。README 推荐用 Composer 安装:
composer require phpmailer/phpmailer或把"phpmailer/phpmailer": "^6.9.2"加入composer.json。注意vendor目录和vendor/autoload.php由 Composer 生成,不属于 PHPMailer 仓库本身。
如果你不用 Composer 而是手动引入类文件,按 README 的“Minimal installation”一节:至少需要 src/PHPMailer.php;使用 SMTP 时还需要 src/SMTP.php;只有用 POP-before-SMTP 时才需要 src/POP3.php;不向用户展示错误信息时可省略 language 目录。
另外注意:通过 Composer 或 zip 包安装时不包含 examples 目录,本文引用的示例代码需要 git clone 仓库后在 examples 目录查看。
三种方式的前提条件与差异
选择依据都来自仓库文档,按运行环境对照:
1.mail()函数(examples/mail.phps)
- 使用 PHP 内置的
mail()函数,是三者中最简单的用法; - 依赖本机存在本地邮件服务器。PHP 的
mail()函数通常经由本地邮件服务器发送,在 Linux、BSD、macOS 上通常有 sendmail 二进制程序顶在前面,而Windows 上一般没有本地邮件服务器(见 examples/README.md 对mail.phps的说明); - README 的“Why you might need it”一节给出明确态度:
mail()应尽量避免使用,连 localhost 的 SMTP 都比它更快、更安全; mail.phps没有调用任何is*()切换方法,直接按默认传输方式发送。
2. sendmail 程序(examples/sendmail.phps)
- sendmail 是一个程序(通常出现在 Linux/BSD、OS X 及其他类 UNIX 系统上),可以不用经历完整的 SMTP 会话就把消息提交给本地邮件服务器;
- 文档评价是“可能是最快的发送机制,但错误报告功能较弱”(lacks some error reporting features);
- 通过
$mail->isSendmail()切换。从 src/PHPMailer.php#L981-L991 可以看到它的行为:读取 php.ini 的sendmail_path,如果该值中不含sendmail字样,则使用/usr/sbin/sendmail,否则使用sendmail_path配置的值。
3. SMTP(examples/smtp.phps、examples/smtp_no_auth.phps)
- 通过 PHPMailer 内置的 SMTP 客户端直接连接 SMTP 服务器,所有平台都不需要本地邮件服务器,Windows 环境的唯一可行路径;
- 支持认证(LOGIN、PLAIN、CRAM-MD5、XOAUTH2)以及 SMTPS 和 SMTP+STARTTLS 传输(README Features 一节);
- 通过
$mail->isSMTP()切换。
可以这样归纳判断路径:没有本地邮件服务器(典型为 Windows)→ 只能选 SMTP;有本地邮件服务器、要最简单 →mail();有 sendmail 类程序、追求提交速度且能接受弱错误报告 → sendmail;而 README 的官方立场是把 SMTP(哪怕是 localhost)作为首选。
配置示例
三种示例的邮件内容部分完全相同(读取contents.html、设置纯文本AltBody、附加图片),差异只在传输方式那几行。以下代码摘自仓库示例文件,域名沿用了示例中的example.com——examples/README.md 说明这是 IANA 为文档示例保留的域名(RFC 2606),运行时需替换为你自己的真实邮箱地址。
方式一:mail()(摘自 examples/mail.phps)
//Import the PHPMailer class into the global namespace use PHPMailer\PHPMailer\PHPMailer; require '../vendor/autoload.php'; //Create a new PHPMailer instance $mail = new PHPMailer(); //Set who the message is to be sent from $mail->setFrom('from@example.com', 'First Last'); //Set an alternative reply-to address $mail->addReplyTo('replyto@example.com', 'First Last'); //Set who the message is to be sent to $mail->addAddress('whoto@example.com', 'John Doe'); //Set the subject line $mail->Subject = 'PHPMailer mail() test'; //Read an HTML message body from an external file, convert referenced images to embedded, //convert HTML into a basic plain-text alternative body $mail->msgHTML(file_get_contents('contents.html'), __DIR__); //Replace the plain text body with one created manually $mail->AltBody = 'This is a plain-text message body'; //Attach an image file $mail->addAttachment('images/phpmailer_mini.png'); //send the message, check for errors if (!$mail->send()) { echo 'Mailer Error: ' . $mail->ErrorInfo; } else { echo 'Message sent!'; }方式二:sendmail(摘自 examples/sendmail.phps),与上面相比只多一行:
//Set PHPMailer to use the sendmail transport $mail->isSendmail();方式三:SMTP(带认证)(摘自 examples/smtp.phps 的传输配置部分)
//SMTP needs accurate times, and the PHP time zone MUST be set //This should be done in your php.ini, but this is how to do it if you don't have access to that date_default_timezone_set('Etc/UTC'); require '../vendor/autoload.php'; $mail = new PHPMailer(); //Tell PHPMailer to use SMTP $mail->isSMTP(); //Enable SMTP debugging //SMTP::DEBUG_OFF = off (for production use) //SMTP::DEBUG_CLIENT = client messages //SMTP::DEBUG_SERVER = client and server messages $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Set the hostname of the mail server $mail->Host = 'mail.example.com'; //Set the SMTP port number - likely to be 25, 465 or 587 $mail->Port = 25; //Whether to use SMTP authentication $mail->SMTPAuth = true; //Username to use for SMTP authentication $mail->Username = 'yourname@example.com'; //Password to use for SMTP authentication $mail->Password = 'yourpassword';Host、Port、Username、Password替换为你的 SMTP 服务器实际值。若服务器不接受匿名发信,参考 examples/smtp_no_auth.phps,它去掉认证配置并注明SMTPAuth = false是默认值,无需显式设置。
需要 TLS 加密和认证的服务商(如 Gmail)有现成配置:examples/gmail.phps 连接smtp.gmail.com的 587 提交端口,启用 TLS 和认证;README 也把 Gmail 示例列为入门推荐起点。README 主示例中则展示了SMTPSecure的两种取值:PHPMailer::ENCRYPTION_SMTPS对应 465 端口,PHPMailer::ENCRYPTION_STARTTLS对应 587 端口。
调试时SMTPDebug用SMTP::DEBUG_SERVER(输出客户端和服务器双方的消息);生产环境应改回SMTP::DEBUG_OFF,示例注释里明确标注 DEBUG_OFF 是 for production use。
验证发送结果与本地测试
三种示例用同一种方式判断结果:$mail->send()返回布尔值,失败时读取$mail->ErrorInfo:
if (!$mail->send()) { echo 'Mailer Error: ' . $mail->ErrorInfo; } else { echo 'Message sent!'; }也可以改用异常模式:new PHPMailer(true)构造时传入true即启用异常,send()失败会抛出Exception,在 catch 中读取$mail->ErrorInfo(README 的“Simple Example”和 examples/exceptions.phps 都采用这种写法)。
反复调试时不要往真实收件人发测试邮件,仓库提供了不真正外发的验证手段(见 examples/README.md 的“About testing email sending”一节):
- 测
mail/sendmail方式:用测试套件里的 test/fakesendmail.sh,这是一个模拟 sendmail 的 shell 脚本,专用于测试 PHPMailer 的 'mail' 或 'sendmail' 方法; - 测 SMTP 方式:用假 SMTP 服务器,如 FakeEmail(Python,带 Web 界面)、Postfix 自带的 smtp-sink(PHPMailer 的 CI 测试就用它)、smtp4dev、MailHog 等,它们像真实服务器一样响应但不外发邮件,可用于验证认证和错误处理;
- 用 msglint(IETF 的 MIME 结构分析器)检查消息格式是否符合规范;
- 若要真实检查邮件配置(SPF、DKIM、DMARC 等),文档列出了 aboutmy.email 这类在线服务。
运行示例文件前注意 examples/README.md 的安全说明:示例以.phps后缀提供,通常会被 PHP 以语法高亮方式显示而不是执行;如果要放到 Web 服务器运行,必须先改名为.php,并且不要把真实密码写进这些文件里。
限制与选择结论
mail()与 sendmail 都要求本机有可用的本地邮件服务器或 sendmail 程序,Windows 一般不具备这一条件,此时只有 SMTP 可选;文档同时建议遇到这种情况“安装本地邮件服务器,或使用远程服务器走 SMTP”。- sendmail 方式错误报告能力弱于 SMTP,出问题时可用信息有限。
- README 对
mail()的立场明确:应尽量避免使用它,SMTP(哪怕是 localhost)更快也更安全。 - 因此默认主路径是:有 SMTP 账号就用
isSMTP();确认本机有 sendmail 类程序且需要最快提交时才考虑isSendmail();mail()仅在已有本地邮件服务器、且希望最简配置时使用。 - 若发送量较大(如群发),SMTP 方式可参考 examples/mailing_list.phps,它利用 SMTP keepalive 避免每条消息都重新连接和认证。
【免费下载链接】PHPMailerThe classic email sending library for PHP项目地址: https://gitcode.com/GitHub_Trending/ph/PHPMailer
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考