PHPMailer同时使用AddStringAttachment和AddAttachment时发信异常问题
问题原因
- 上传临时文件不可重复读取:PHP的HTTP上传临时文件默认会在请求结束后自动销毁,且第一次被
AddAttachment读取后文件指针会指向文件末尾,第二次循环读取同一临时文件时无法获取到完整内容,会导致邮件MIME结构损坏,出现内容错乱。 - 临时文件变量名错误:PHP官方上传临时文件路径存储在
$_FILES['upload']['tmp_name']中,你代码中使用的tmp_path是非标准写法,可能会出现读取不稳定的问题。 - 表单重复提交:单个收件人仍收到两封邮件,说明整个请求脚本被重复触发了两次:第一次请求有完整的表单数据和上传临时文件,邮件符合预期;第二次请求时上传临时文件已经被第一次请求销毁,表单数据可能也丢失,生成的PDF内容异常,最终出现仅含错乱PDF的邮件。
解决方法
- 修正临时文件变量名,提前将上传文件读取到内存中,避免循环中重复读取临时文件,同时每次循环重新实例化PHPMailer避免对象复用残留数据:
//PDF $pdf = $dompdf->output(); // 提前处理上传附件,读入内存避免反复读取临时文件 $uploadFileContent = null; $uploadFileName = 'upload.pdf'; if (!empty($_FILES['upload']['tmp_name']) && is_file($_FILES['upload']['tmp_name'])) { $uploadFileContent = file_get_contents($_FILES['upload']['tmp_name']); } //Loop through recipients $recipients = ['email1@email.com', 'email2@email.com']; foreach ($recipients as $recipient) { // 每次循环重新实例化PHPMailer,避免对象复用残留数据 $mail = new PHPMailer; $mail->IsSMTP(); $mail->CharSet = 'UTF-8'; $mail->Host = 'localhost'; $mail->SMTPAuth = false; //Email details $mail->From = 'email@email.com'; $mail->FromName = 'My email'; $mail->Subject = 'You have a new email'; $mail->Body = 'Hi there, You have a new message.<br>'; $mail->AltBody = 'Hi there, You have a new message.'; $mail->addAddress($recipient); $mail->AddStringAttachment($pdf, 'name.pdf'); // 直接用内存中的文件内容添加附件 if ($uploadFileContent !== null) { $mail->AddStringAttachment($uploadFileContent, $uploadFileName); } if ( !$mail->Send() ) { echo 'Not sent'; } else { echo 'Sent'; } }
- 新增表单重复提交校验:
- 前端:提交按钮点击后立即设置disabled状态,避免用户多次点击
- 后端:生成唯一的表单token存入session,提交后校验token有效性,校验通过立即销毁该token,同一个token仅允许提交一次
内容的提问来源于stack exchange,提问作者mm1234
相关产品推荐
相关产品推荐

