【发布时间】:2017-05-20 17:41:27
【问题描述】:
您好,我正在尝试使用 PhpMailer 发送多封电子邮件作为通知系统。为避免用户提交表单时出现时间延迟问题,我决定将所有电子邮件消息排队存储到 mysql 表中,然后使用 cron 作业运行后台脚本来发送队列。这是我使用 cron 作业运行的脚本
include('config/config.php');
require_once(ROOT_PATH.'/helper/phpmailer/PHPMailerAutoload.php');
$mail = new PHPMailer;
$mail->isSMTP();
$mail->SMTPAuth = true;
$mail->isHTML(true);
$mail->Host = SSE_HOST;
$mail->Username = SSE_USER;
$mail->Password = SSE_PASSWORD;
$mail->SMTPSecure = SSE_SECURE;
$mail->Port = 465;
$mail->SetFrom(SSE_FROM, SSE_FROM_NAME);
$mail->addReplyTo(SSE_REPLY, 'Invia Risposta');
$result = mysqli_query($conn, "SELECT queue_emails_email, queue_emails_subject, queue_emails_body FROM queue_emails WHERE queue_emails_status = '1' " );
foreach ($result as $row) {
$mail->addAddress($row['queue_emails_email']);
$subject = $row['queue_emails_subject'];
$mail->Subject = $subject;
$mail->MsgHTML($row['queue_emails_body']);
if (!$mail->send()) {
echo "Mailer Error (" . str_replace("@", "@", $row["queue_emails_email"]) . ') ' . $mail->ErrorInfo . '<br />';
break; //Abandon sending
} else {
echo "Message sent to :" . $row['queue_emails_email'] . ' (' . str_replace("@", "@", $row['queue_emails_email']) . ')<br />';
//Mark it as sent in the DB
mysqli_query($conn, "UPDATE queue_emails SET queue_emails_status = '0' WHERE queue_emails_email = '" .
mysqli_real_escape_string($conn, $row['queue_emails_email']) . "'");
}
// Clear all addresses and attachments for next loop
$mail->clearAddresses();
}
这是mysql表queue_emails结构:
queue_emails_id int(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
queue_emails_email varchar(255) NOT NULL,
queue_emails_status int(2) DEFAULT '1',
queue_emails_subject TEXT NOT NULL,
queue_emails_body TEXT NOT NULL
现在我的问题是:如果我收到了不止一条正文不同但电子邮件地址相同的消息,如果 cron 作业进程中断会发生什么?我已经使用 mailtrap 在我的本地主机上进行了测试,它似乎工作正常,但我想知道这种方法在实时服务器上是否有效。我认为我的队列不会超过 200-300 封电子邮件。非常感谢您的帮助
【问题讨论】:
-
为什么不直接在表中添加一个 ID 列并根据这个 ID 而不是电子邮件地址进行更新?
-
嗨@TodorSimeonov 感谢您的快速回答。抱歉,我不明白您添加 id 是什么意思(是用户 id)吗?
-
在您的 DB 表
queue_emails- 添加一个可以是 AUTO INCREMENT 的列,它将是您必须发送的每封电子邮件的唯一 ID。然后在此基础上,您可以使用queue_emails_status = '0'更新您刚刚发送的电子邮件消息的这一行,但发送给该用户(地址)的所有其他消息将留在队列中。如果所有表格都填写相同的电子邮件地址,则无关紧要。 -
好的,我现在明白了,所以基本上我需要从 UPDATE queue_emails SET queue_emails_status = '0' 中删除 where 子句,我已经有了一个带有 auto_increment 的 queue_emails_id 表。因此,即使 cron 作业进程超时,它也应该从哪里开始,如果它是正确的吗?还有什么我可以实施的吗?我添加了 $mail->SMTPKeepAlive = true;按照这里的建议到 Phpmailer 配置 github.com/PHPMailer/PHPMailer/blob/master/examples/…
-
不,在没有 WHERE 子句的情况下执行 UPDATE 不是一个好主意 :) 您将只发送一封电子邮件并更新整个表。我的意思是将 WHERE 子句更改为
UPDATE ... SET .... WHERE queue_email_id = '$last_email_id';比较您确定是唯一的东西,而不是可能不是的地址。例如,在在线商店中,您将向新用户发送 2 条后续消息 - 一条用于成功注册,一条用于下订单。很高兴他收到了他们两个:)