
在开发web应用程序时,我们经常会遇到需要动态生成文件(如pdf、图片证书等)并将其作为电子邮件附件发送的场景。phpmailer是一个功能强大的php邮件发送库,但如果不注意文件生成与附件添加的执行顺序,可能会遇到附件首次发送失败,而刷新页面后却能成功发送的“奇怪”现象。
这种现象的根本原因在于PHP脚本的执行顺序。当一个PHP脚本同时负责生成文件和发送邮件时,如果邮件发送逻辑(特别是附件添加部分)在文件生成并保存到磁盘之前执行,PHPMailer将无法找到或访问该文件,从而导致附件发送失败。
首次提交表单时:
刷新页面时:
这表明问题并非出在PHPMailer本身或文件路径错误,而是文件在PHPMailer尝试访问时还未就绪。
立即学习“PHP免费学习笔记(深入)”;
解决此问题的关键在于确保文件生成和保存操作在PHPMailer尝试添加该文件作为附件之前完成。这意味着,生成证书图片并将其保存到指定路径的代码必须在PHPMailer的AddAttachment()方法调用之前执行。
以下是修正后的PHP代码结构示例,展示了正确的执行顺序:
<?php
// 引入PHPMailer类和设置文件
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
require 'PHPMailer-master/src/PHPMailer.php';
require 'PHPMailer-master/src/SMTP.php';
require 'PHPMailer-master/src/Exception.php';
include 'settings.php'; // 包含设置文件
// 检查表单是否提交
if (isset($_POST['generate'])) {
// 获取表单数据
$name = ucwords($_POST['name']);
$customerref = ($_POST['customerref']);
$date = ($_POST['date']);
$customeremail = ($_POST['customeremail']);
$weight = ucwords($_POST['weight']);
// 输入验证
if ($name == "" || $weight == "" || $date == "" || $customeremail == "" || $customerref == "") {
echo "<div class='alert alert-danger col-sm-6' role='alert'>并非所有表单字段都已填写。请重试。</div>";
} else {
// 提示信息
echo "<div class='alert alert-success col-sm-6' role='alert'>恭喜!$name 的证书已生成并发送至 $customeremail。</div>";
// --- 第一步:生成并保存证书图片 ---
$image = "CSD-Certificates/certi.png";
$createimage = imagecreatefrompng($image);
$output = dirname(__FILE__) . "/CSD-Certificates/saved-certs/destruction-cert($customerref-$date).png";
$white = imagecolorallocate($createimage, 254, 254, 254);
$black = imagecolorallocate($createimage, 0, 0, 0);
$rotation = 0;
// 字体路径
$drFont = "CSD-Certificates/TitilliumWeb-Regular.ttf";
// 根据名称长度调整字体大小和位置
$name_len = strlen($_POST['name']);
$font_size = 50;
$origin_x = 1600;
if ($name_len > 7 && $name_len <= 12) { $font_size = 40; }
elseif ($name_len > 12 && $name_len <= 15) { $font_size = 40; }
// ... 其他长度判断
// 写入文本到图片
imagettftext($createimage, $font_size, $rotation, $origin_x, 700, $white, $drFont, $name);
imagettftext($createimage, 50, $rotation, 2302, 900, $white, $drFont, $weight);
imagettftext($createimage, $font_size, $rotation, 1850, 900, $white, $drFont, $date);
imagettftext($createimage, $font_size, $rotation, 2200, 1980, $white, $drFont, $date);
imagettftext($createimage, $font_size, $rotation, 2200, 2180, $white, $drFont, $customerref);
// 保存生成的图片文件
imagepng($createimage, $output, 3);
// 释放内存
imagedestroy($createimage);
// --- 第二步:使用PHPMailer发送邮件 ---
$mail = new PHPMailer(true); // 启用异常
try {
// 服务器设置
$mail->isSMTP();
$mail->Host = 'mail.smtp2go.com';
$mail->SMTPAuth = true;
$mail->Username = 'refurbsa.com';
$mail->Password = 'Y2F6ejMxbGFseTUw';
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
$mail->Port = 465;
// 收件人
$mail->setFrom('sender@example.com', 'Electronic Cemetery');
$mail->addAddress($customeremail); // 使用从表单获取的邮箱
$mail->addReplyTo('replyto@example.com', 'Electronic Cemetery');
// 添加附件 (确保 $output 路径的文件已存在)
$mail->AddAttachment($output);
// 内容
$mail->isHTML(true);
$mail->Subject = '您的电子废物处理证书';
$mail->Body = "您好 $name,<br><br>
感谢您使用我们的服务。您的回收请求已处理,我们已将销毁证书附加到此电子邮件中。
<br><br>
如果您对我们的服务感到满意,请花一点时间在 <a href='https://www.facebook.com/eastcoastewaste/reviews'>这里</a> 给予我们评价,我们将不胜感激。
<br><br>
我们期待未来能继续协助您处理所有电子废物需求。
<br><br>
祝您有美好的一天!
<br><br>
电子墓地团队";
$mail->send();
} catch (Exception $e) {
echo "邮件无法发送。Mailer Error: {$mail->ErrorInfo}";
}
}
}
?>在上述代码中,关键的改动是将 imagepng($createimage, $output, 3); 这行代码(负责保存图片文件)放置在 PHPMailer 的 AddAttachment() 方法调用之前。这样,当 PHPMailer 尝试添加附件时,目标文件已经确保存在于文件系统中。
PHPMailer附件发送首次失败、刷新后成功的现象,本质上是文件生成与附件引用之间的时序问题。通过简单地调整代码执行顺序,确保附件文件在被PHPMailer访问之前已经完全生成并保存,即可有效解决此问题。理解并遵循正确的执行流程,是构建稳定可靠的PHP应用程序的关键。
以上就是解决PHPMailer附件发送时序问题:首次失败刷新后成功的解决方案的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号