PHP Mail
mail() parameters, configuration, and alternatives.
Key Points`mail()` only hands the message to a local MTA — it does not deliver.
Functions
| Function | Purpose |
|---|---|
| 发送邮件 | |
| mb_send_mail | 按字符集编码后发送(中文友好) |
| imap_mail | 支持更多头字段(需 imap 扩展) |
| mailparse_* | 解析邮件(需 pecl mailparse) |
Parameters
PHP
<?php
$to = "someone@example.com";
$subject = "测试";
$message = "第一行\n第二行";
$headers = "From: noreply@example.com\r\nReply-To: support@example.com";
$params = "-f noreply@example.com"; // 设置 envelope sender
$ok = mail($to, $subject, $message, $headers, $params);
echo $ok ? "已提交" : "失败", "\n";Output
已提交The fifth parameter sets the envelope sender, distinct from the From header. SPF checks the envelope — omit it and mail lands in spam.
Configuration
INI
; php.ini
SMTP = smtp.example.com ; 仅 Windows 生效
smtp_port = 25
sendmail_from = noreply@example.com
; Linux 下 mail() 调用 sendmail 路径
sendmail_path = "/usr/sbin/sendmail -t -i"On Linux mail() invokes the local MTA via sendmail_path; on Windows it uses SMTP. Behaviour differs entirely — cross-platform code cannot assume otherwise.
Chinese mail
PHP
<?php
$subject = "=?UTF-8?B?" . base64_encode("账户激活") . "?=";
$body = "<h1>欢迎</h1><p>请点击链接激活账户。</p>";
$headers = implode("\r\n", [
"MIME-Version: 1.0",
"Content-Type: text/html; charset=UTF-8",
"Content-Transfer-Encoding: base64",
"From: =?UTF-8?B?" . base64_encode("我的站点") . "?= <noreply@example.com>",
]);
echo $subject, "\n";
echo strlen(base64_encode($body)) > 0 ? "正文已编码" : "编码失败", "\n";Output
=?UTF-8?B?6LSm5oi35r+A5rS7?=
正文已编码=?UTF-8?B?base64?= is a MIME encoded-word. Chinese subjects and display names need it or clients show mojibake.
Alternatives
| Approach | Pros | Cons |
|---|---|---|
| mail() | 零依赖 | 依赖 MTA,无 SMTP 认证,几乎无错误信息 |
| PHPMailer | SMTP + TLS + 附件 + 模板 | 需 Composer |
| Symfony Mailer | 组件化,支持多传输 | 学习成本 |
| 第三方 API | 送达率高,有统计 | 收费,依赖外部服务 |
PHP
<?php
// PHPMailer 的最小用法
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = "smtp.example.com";
$mail->SMTPAuth = true;
$mail->Username = "noreply@example.com";
$mail->Password = getenv("MAIL_PASS");
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom("noreply@example.com", "我的站点");
$mail->addAddress("someone@example.com");
$mail->Subject = "账户激活";
$mail->Body = "<p>请点击链接激活</p>";
$mail->isHTML(true);
$mail->send();
echo "发送成功\n";Output
发送成功Whatever the transport, rate limit sending. An unthrottled public form becomes a spam source within hours and blacklists your IP and domain.
函数
| 函数 | 作用 |
|---|---|
| 发送邮件 | |
| mb_send_mail | 按字符集编码后发送(中文友好) |
| imap_mail | 支持更多头字段(需 imap 扩展) |
| mailparse_* | 解析邮件(需 pecl mailparse) |
参数
PHP
<?php
$to = "someone@example.com";
$subject = "测试";
$message = "第一行\n第二行";
$headers = "From: noreply@example.com\r\nReply-To: support@example.com";
$params = "-f noreply@example.com"; // 设置 envelope sender
$ok = mail($to, $subject, $message, $headers, $params);
echo $ok ? "已提交" : "失败", "\n";Output
已提交第五个参数 -f 设置的是信封发件人,和 From 头不是一回事。SPF 校验看的是信封发件人,不设它会被判垃圾邮件。
配置
INI
; php.ini
SMTP = smtp.example.com ; 仅 Windows 生效
smtp_port = 25
sendmail_from = noreply@example.com
; Linux 下 mail() 调用 sendmail 路径
sendmail_path = "/usr/sbin/sendmail -t -i"Linux 上 mail() 通过 sendmail_path 调用本地 MTA(Postfix、Exim、Sendmail)。Windows 上走 SMTP 配置。两者行为完全不同,跨平台代码不能假设一致。
中文邮件
PHP
<?php
$subject = "=?UTF-8?B?" . base64_encode("账户激活") . "?=";
$body = "<h1>欢迎</h1><p>请点击链接激活账户。</p>";
$headers = implode("\r\n", [
"MIME-Version: 1.0",
"Content-Type: text/html; charset=UTF-8",
"Content-Transfer-Encoding: base64",
"From: =?UTF-8?B?" . base64_encode("我的站点") . "?= <noreply@example.com>",
]);
echo $subject, "\n";
echo strlen(base64_encode($body)) > 0 ? "正文已编码" : "编码失败", "\n";Output
=?UTF-8?B?6LSm5oi35r+A5rS7?=
正文已编码=?UTF-8?B?base64?= 是 MIME 的「编码字」。中文主题、发件人显示名都必须这样编码,否则客户端显示乱码。
替代方案
| 方案 | 优点 | 缺点 |
|---|---|---|
| mail() | 零依赖 | 依赖 MTA,无 SMTP 认证,几乎无错误信息 |
| PHPMailer | SMTP + TLS + 附件 + 模板 | 需 Composer |
| Symfony Mailer | 组件化,支持多传输 | 学习成本 |
| 第三方 API | 送达率高,有统计 | 收费,依赖外部服务 |
PHP
<?php
// PHPMailer 的最小用法
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = "smtp.example.com";
$mail->SMTPAuth = true;
$mail->Username = "noreply@example.com";
$mail->Password = getenv("MAIL_PASS");
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Port = 587;
$mail->setFrom("noreply@example.com", "我的站点");
$mail->addAddress("someone@example.com");
$mail->Subject = "账户激活";
$mail->Body = "<p>请点击链接激活</p>";
$mail->isHTML(true);
$mail->send();
echo "发送成功\n";Output
发送成功无论用哪种方案,发信都必须限流。公开表单不限流,几小时内就会被脚本刷成垃圾邮件源,然后你的 IP 和域名一起进黑名单。