php通过原始smtp协议发送邮件时,仅在邮件头中添加cc字段无法使抄送人收到邮件,必须在smtp会话中显式调用rcpt to:命令为每个cc地址注册接收者。
在您提供的自定义smtp_mail()函数中,当前逻辑仅对$to列表中的收件人执行了RCPT TO:命令(即SMTP协议中声明“该邮件将送达这些地址”),但完全忽略了$cc地址。SMTP协议本身不区分To/CC/BCC——它只关心“谁是合法的收件人(envelope recipient)”,而To、CC、BCC语义仅由邮件头(Header)控制,用于客户端显示。若未在SMTP会话中为CC邮箱调用RCPT TO:,邮件服务器会直接拒绝投递给这些地址,导致CC收件人收不到任何邮件。
需在MAIL FROM:之后、DATA之前,为所有CC邮箱逐一发送RCPT TO:指令。修改原函数中相关部分如下:
// 原有:仅处理 To 收件人
foreach ($recipients as $email) {
fwrite($socket, 'RCPT TO: <'.trim($email).'>'."\r\n");
server_parse($socket, '250');
}
// ✅ 新增:同样处理 CC 收件人(注意去空格,避免解析失败)
foreach ($recipientscc as $email) {
$email = trim($email);
if (!empty($email)) {
fwrite($socket, 'RCPT TO: <'.$email.'>'."\r\n");
server_parse($socket, '250');
}
}⚠️ 注意事项:RCPT TO: 是信封级(envelope-level) 命令,必须为每个实际接收邮箱调用一次;To: 和 Cc: 头字段(header-level)仅影响邮件客户端如何显示,不决定投递权限;若CC邮箱格式不规范(如含多余空格、换行或非法字符),RCPT TO: 会失败,建议使用trim()预处理;BCC同理:需调用RCPT TO:,但不在邮件头中出现,实现“隐藏收件人”。
发送后检查SMTP服务器日志(如Postfix、Exim)或使用MailHog、Mailtrap等测试工具捕获原始SMTP会话,确认RCPT TO:命令是否包含所有CC邮箱。若仍失败,请检查:
遵循以上修正,您的CC收件人即可正常接收邮件——本质不是“头没写对”,而是“门没敲开”。