在 while 循环中使用 PHPMailer 发送多封电子邮件
Send Multiple emails with PHPMailer within while loop
我试图在 while 循环中发送多封电子邮件,使用以下代码它不发送电子邮件通知并给出错误 'Fatal error: Uncaught Error: Class "PHPMailer" not found in C:\xampp\htdocs\clinic\paients\run_medications.php:98 Stack trace: #0 {main} thrown in'。虽然位置正确并且它从另一个子目录发送单个电子邮件。
require_once('../includes/PHPMailer.php');
require_once('../includes/SMTP.php');
require_once('../includes/Exception.php');
$full_dt = date('Y-m-d H:i:s');
$dt = date('Y-m-d');
$dt_hr = date('H');
$check_timing = $con->prepare("SELECT medication, start_time, end_time FROM timings WHERE HOUR(end_time) = :end ");
$check_timing->bindparam(':end', $dt_hr);
$check_timing->execute();
$count1 = $check_timing->rowCount();
if($count1 > 0) {
while($rows = $check_timing->fetch(PDO:: FETCH_OBJ)) {
$medication = $rows->medication;
$start_time = $dt.' '. $rows->start_time;
$end_time = $dt.' '.$rows->end_time;
$timestamp = strtotime($end_time) + 60*60;
$end_hour = date('Y-m-d H:i:s', $timestamp);
$query = "SELECT a.location_code, b.* FROM patients a INNER JOIN medication b ON a.id = b.pat_id WHERE b.status != 2 AND b.directions = :med AND b.last_time NOT BETWEEN :start AND :end AND :crntime BETWEEN b.start_date AND b.end_date AND :crntime BETWEEN :end AND :end_hour";
$statement = $con->prepare($query);
$statement->bindparam(':med', $medication);
$statement->bindparam(':start', $start_time);
$statement->bindparam(':end', $end_time);
$statement->bindparam(':crntime', $full_dt);
$statement->bindparam(':end_hour', $end_hour);
$statement->execute();
$count = $statement->rowCount();
if($count > 0) {
while($row = $statement->fetch(PDO:: FETCH_OBJ)) {
$drug_id = $row->drgid;
$code = $row->location_code;
$pat_id = $row->pat_id;
$drug = $row->med_type.' - '.$row->drug.' ('.$row->strength.')';
$dose = $row->dosage;
$route = $row->route;
$directions = $row->directions;
$getUserName = "SELECT name FROM users WHERE FIND_IN_SET(location_code, :codes)>0 ";
$runUser = $con->prepare($getUserName);
$runUser->bindParam(':codes',$code);
$runUser->execute();
$check = $runUser->rowCount();
if($check > 0) {
$userRow = $runUser->fetch(PDO::FETCH_OBJ);
$by = $userRow->name;
}
$insert_report = $con->prepare("
INSERT INTO `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')");
$insert_report->bindparam(':m_id',$drug_id);
$insert_report->bindparam(':p_id',$pat_id);
$insert_report->bindparam(':time',$end_time);
$insert_report->bindparam(':by',$by);
$insert_report->execute();
$mail = new PHPMailer();
$mail->isSMTP();
$mail-> SMTPOptions = array (
'ssl' => array (
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
$mail->Host = "smtp.gmail.com";
$mail->SMTPAuth = true;
$mail->SMTPSecure = "tls";
$mail->Port = "587";
$mail->Username = "from@gmail.com";
$mail->Password = "12345678";
$mail->Subject = "Medication Report";
$mail->setFrom("from@gmail.com",$by);
$mail->isHTML(true);
//Attachment
//$mail->addAttachment('img/attachment.png');
//Email body
$mail->Body = "<h3>Medication Report by ($by) </h3></br>
You are being alerted that <b>$name</b> has missed their $directions Medication $row->med_type. And you may need to take appropriate action..";
$mail->addAddress($to_email['Email_add']);
$mail->send();
} // /while
}// if num_rows
}//while close
}// if num_rows
您的代码中有:
$check = $runUser->rowCount();
if($check > 0) {
$userRow = $runUser->fetch(PDO::FETCH_OBJ);
$by = $userRow->name;
}
$insert_report = $con->prepare("
INSERT INTO `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')");
$insert_report->bindparam(':m_id',$drug_id);
$insert_report->bindparam(':p_id',$pat_id);
$insert_report->bindparam(':time',$end_time);
$insert_report->bindparam(':by',$by);
但是如果没有返回任何行并且因此 $check
为 0,则不会设置变量 $by
。但是您随后继续使用 $by
进行数据库插入和发送电子邮件的逻辑。我认为如果列 responsible
不可为空,这可能会产生数据库异常。无论如何,这显然是不正确的逻辑。
在执行 while
循环之前,您还对返回的行数进行了大量测试。这些测试确实是多余的:如果返回的行数为 0,如果您只测试返回 FALSE
的 fetch 语句,while
循环将立即退出。因此,可以通过删除那些多余的检查来减少嵌套级别。
第二个问题是您正在从 table users 读取列 name
并将其存储在变量 $by
中。然而,您的电子邮件正文引用了尚未定义的变量 $name
。我暂时用 varibale $by
替换了它。但只有你能说这是否正确。但很明显,如果没有,那么您需要用适当的值初始化 $name
。
$full_dt = date('Y-m-d H:i:s');
$dt = date('Y-m-d');
$dt_hr = date('H');
$check_timing = $con->prepare("SELECT medication, start_time, end_time FROM timings WHERE HOUR(end_time) = :end ");
$check_timing->bindparam(':end', $dt_hr);
$check_timing->execute();
while(($timingRow = $check_timing->fetch(PDO:: FETCH_OBJ)) !== FALSE) {
$medication = $timingRow->medication;
$start_time = $dt.' '. $timingRow->start_time;
$end_time = $dt.' '.$timingRow->end_time;
$timestamp = strtotime($end_time) + 60*60;
$end_hour = date('Y-m-d H:i:s', $timestamp);
$query = "SELECT a.location_code, b.* FROM patients a INNER JOIN medication b ON a.id = b.pat_id
WHERE b.status != 2 AND b.directions = :med AND b.last_time NOT BETWEEN :start AND :end
AND :crntime BETWEEN b.start_date AND b.end_date AND :crntime BETWEEN :end AND :end_hour";
$statement = $con->prepare($query);
$statement->bindparam(':med', $medication);
$statement->bindparam(':start', $start_time);
$statement->bindparam(':end', $end_time);
$statement->bindparam(':crntime', $full_dt);
$statement->bindparam(':end_hour', $end_hour);
$statement->execute();
while(($row = $statement->fetch(PDO:: FETCH_OBJ)) !== FALSE) {
$drug_id = $row->drgid;
$code = $row->location_code;
$pat_id = $row->pat_id;
$drug = $row->med_type.' - '.$row->drug.' ('.$row->strength.')';
$dose = $row->dosage;
$route = $row->route;
$directions = $row->directions;
$getUserName = "SELECT name FROM users WHERE FIND_IN_SET(location_code, :codes)>0 ";
$runUser = $con->prepare($getUserName);
$runUser->bindParam(':codes',$code);
$runUser->execute();
$userRow = $runUser->fetch(PDO::FETCH_OBJ);
if ($userRow !== FALSE) {
$by = $userRow->name;
$insert_report = $con->prepare("
INSERT INTO `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')"
);
$insert_report->bindparam(':m_id',$drug_id);
$insert_report->bindparam(':p_id',$pat_id);
$insert_report->bindparam(':time',$end_time);
$insert_report->bindparam(':by',$by);
$insert_report->execute();
$mail = new PHPMailer();
$mail->isSMTP();
$mail-> SMTPOptions = array (
'ssl' => array (
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
$mail->Host = "smtp.gmail.com";
$mail->SMTPAuth = true;
$mail->SMTPSecure = "tls";
$mail->Port = "587";
$mail->Username = "from@gmail.com";
$mail->Password = "12345678";
$mail->Subject = "Medication Report";
$mail->setFrom("from@gmail.com",$by);
$mail->isHTML(true);
//Attachment
//$mail->addAttachment('img/attachment.png');
//Email body
$mail->Body = "<h3>Medication Report by ($by) </h3></br>
You are being alerted that <b>$by</b> has missed their $directions Medication $row->med_type. And you may need to take appropriate action..";
$mail->addAddress($to_email['Email_add']);
$mail->send();
}
} // while($row = ...
} //while $timingRow = ...
您的 PHPMailerAutoload.php 文件位于何处?
你需要用这个导入它:
require_once('phpmailer/PHPMailerAutoload.php');
总体而言,您必须执行以下步骤:
单击页面右下角的“下载 ZIP”按钮,从 https://github.com/PHPMailer/PHPMailer 下载程序包。
解压缩文件。
上传语言文件夹,class.phpmailer.php、class、pop3.php、class.smtp.php、PHPMailerAutoload.php都放在同一个目录下在你的服务器上,我想在服务器上创建一个名为 phpmailer 的目录来放置所有这些。
在您的项目中加载 class:
require_once('phpmailer/PHPMailerAutoload.php');
完成...
如果您不使用异常,您仍然需要加载异常 class,因为它在内部使用。
因此,像这样将 use 放在页面顶部(我认为这就是您收到未定义错误的原因):
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
然后像这样调用文件:
require 'path/to/PHPMailer/src/Exception.php';
require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php';
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
try {
$mail->SMTPDebug = 0;
$mail->isSMTP();
$mail->Host = "smtp.gmail.com";
$mail->SMTPAuth = true;
$mail->Username = "email@gmail.com";
$mail->Password = "password";
$mail->Port = 587;
$mail->setFrom('admin@example.com', 'Mailer');
$mail->addAddress($email);
$mail->addReplyTo("user@gmail.com", "Alias");
$mail->CharSet = "UTF-8";
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $message;
$mail->send();
echo "Mail sent.";
} catch (Exception $e) {
echo "Failed. Mailer error: {$mail->ErrorInfo}";
}
有时这条线 use PHPMailer\PHPMailer\PHPMailer;
像这样工作 use PHPMailer\PHPMailer;
尝试两种方式。但我认为第一个对你有用。
我不使用 ssl 选项,如果您需要它,只需将它放在 isSMTP 下即可。
$mail-> SMTPOptions = array (
'ssl' => array (
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
这里是发送多封邮件的例子:Send multiple email
注意:您必须将您的 gmail 帐户设置为应用安全性较低才能使用 phpmailer。
因为 Gmail 已经开始实施一种身份验证机制,用 SMTP 身份验证代替基于 OAuth2 的授权。 more info
安全性较低的帐户more info , Less secure accounts
据您所知,Google 正在阻止低安全帐户。
我试图在 while 循环中发送多封电子邮件,使用以下代码它不发送电子邮件通知并给出错误 'Fatal error: Uncaught Error: Class "PHPMailer" not found in C:\xampp\htdocs\clinic\paients\run_medications.php:98 Stack trace: #0 {main} thrown in'。虽然位置正确并且它从另一个子目录发送单个电子邮件。
require_once('../includes/PHPMailer.php');
require_once('../includes/SMTP.php');
require_once('../includes/Exception.php');
$full_dt = date('Y-m-d H:i:s');
$dt = date('Y-m-d');
$dt_hr = date('H');
$check_timing = $con->prepare("SELECT medication, start_time, end_time FROM timings WHERE HOUR(end_time) = :end ");
$check_timing->bindparam(':end', $dt_hr);
$check_timing->execute();
$count1 = $check_timing->rowCount();
if($count1 > 0) {
while($rows = $check_timing->fetch(PDO:: FETCH_OBJ)) {
$medication = $rows->medication;
$start_time = $dt.' '. $rows->start_time;
$end_time = $dt.' '.$rows->end_time;
$timestamp = strtotime($end_time) + 60*60;
$end_hour = date('Y-m-d H:i:s', $timestamp);
$query = "SELECT a.location_code, b.* FROM patients a INNER JOIN medication b ON a.id = b.pat_id WHERE b.status != 2 AND b.directions = :med AND b.last_time NOT BETWEEN :start AND :end AND :crntime BETWEEN b.start_date AND b.end_date AND :crntime BETWEEN :end AND :end_hour";
$statement = $con->prepare($query);
$statement->bindparam(':med', $medication);
$statement->bindparam(':start', $start_time);
$statement->bindparam(':end', $end_time);
$statement->bindparam(':crntime', $full_dt);
$statement->bindparam(':end_hour', $end_hour);
$statement->execute();
$count = $statement->rowCount();
if($count > 0) {
while($row = $statement->fetch(PDO:: FETCH_OBJ)) {
$drug_id = $row->drgid;
$code = $row->location_code;
$pat_id = $row->pat_id;
$drug = $row->med_type.' - '.$row->drug.' ('.$row->strength.')';
$dose = $row->dosage;
$route = $row->route;
$directions = $row->directions;
$getUserName = "SELECT name FROM users WHERE FIND_IN_SET(location_code, :codes)>0 ";
$runUser = $con->prepare($getUserName);
$runUser->bindParam(':codes',$code);
$runUser->execute();
$check = $runUser->rowCount();
if($check > 0) {
$userRow = $runUser->fetch(PDO::FETCH_OBJ);
$by = $userRow->name;
}
$insert_report = $con->prepare("
INSERT INTO `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')");
$insert_report->bindparam(':m_id',$drug_id);
$insert_report->bindparam(':p_id',$pat_id);
$insert_report->bindparam(':time',$end_time);
$insert_report->bindparam(':by',$by);
$insert_report->execute();
$mail = new PHPMailer();
$mail->isSMTP();
$mail-> SMTPOptions = array (
'ssl' => array (
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
$mail->Host = "smtp.gmail.com";
$mail->SMTPAuth = true;
$mail->SMTPSecure = "tls";
$mail->Port = "587";
$mail->Username = "from@gmail.com";
$mail->Password = "12345678";
$mail->Subject = "Medication Report";
$mail->setFrom("from@gmail.com",$by);
$mail->isHTML(true);
//Attachment
//$mail->addAttachment('img/attachment.png');
//Email body
$mail->Body = "<h3>Medication Report by ($by) </h3></br>
You are being alerted that <b>$name</b> has missed their $directions Medication $row->med_type. And you may need to take appropriate action..";
$mail->addAddress($to_email['Email_add']);
$mail->send();
} // /while
}// if num_rows
}//while close
}// if num_rows
您的代码中有:
$check = $runUser->rowCount();
if($check > 0) {
$userRow = $runUser->fetch(PDO::FETCH_OBJ);
$by = $userRow->name;
}
$insert_report = $con->prepare("
INSERT INTO `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')");
$insert_report->bindparam(':m_id',$drug_id);
$insert_report->bindparam(':p_id',$pat_id);
$insert_report->bindparam(':time',$end_time);
$insert_report->bindparam(':by',$by);
但是如果没有返回任何行并且因此 $check
为 0,则不会设置变量 $by
。但是您随后继续使用 $by
进行数据库插入和发送电子邮件的逻辑。我认为如果列 responsible
不可为空,这可能会产生数据库异常。无论如何,这显然是不正确的逻辑。
在执行 while
循环之前,您还对返回的行数进行了大量测试。这些测试确实是多余的:如果返回的行数为 0,如果您只测试返回 FALSE
的 fetch 语句,while
循环将立即退出。因此,可以通过删除那些多余的检查来减少嵌套级别。
第二个问题是您正在从 table users 读取列 name
并将其存储在变量 $by
中。然而,您的电子邮件正文引用了尚未定义的变量 $name
。我暂时用 varibale $by
替换了它。但只有你能说这是否正确。但很明显,如果没有,那么您需要用适当的值初始化 $name
。
$full_dt = date('Y-m-d H:i:s');
$dt = date('Y-m-d');
$dt_hr = date('H');
$check_timing = $con->prepare("SELECT medication, start_time, end_time FROM timings WHERE HOUR(end_time) = :end ");
$check_timing->bindparam(':end', $dt_hr);
$check_timing->execute();
while(($timingRow = $check_timing->fetch(PDO:: FETCH_OBJ)) !== FALSE) {
$medication = $timingRow->medication;
$start_time = $dt.' '. $timingRow->start_time;
$end_time = $dt.' '.$timingRow->end_time;
$timestamp = strtotime($end_time) + 60*60;
$end_hour = date('Y-m-d H:i:s', $timestamp);
$query = "SELECT a.location_code, b.* FROM patients a INNER JOIN medication b ON a.id = b.pat_id
WHERE b.status != 2 AND b.directions = :med AND b.last_time NOT BETWEEN :start AND :end
AND :crntime BETWEEN b.start_date AND b.end_date AND :crntime BETWEEN :end AND :end_hour";
$statement = $con->prepare($query);
$statement->bindparam(':med', $medication);
$statement->bindparam(':start', $start_time);
$statement->bindparam(':end', $end_time);
$statement->bindparam(':crntime', $full_dt);
$statement->bindparam(':end_hour', $end_hour);
$statement->execute();
while(($row = $statement->fetch(PDO:: FETCH_OBJ)) !== FALSE) {
$drug_id = $row->drgid;
$code = $row->location_code;
$pat_id = $row->pat_id;
$drug = $row->med_type.' - '.$row->drug.' ('.$row->strength.')';
$dose = $row->dosage;
$route = $row->route;
$directions = $row->directions;
$getUserName = "SELECT name FROM users WHERE FIND_IN_SET(location_code, :codes)>0 ";
$runUser = $con->prepare($getUserName);
$runUser->bindParam(':codes',$code);
$runUser->execute();
$userRow = $runUser->fetch(PDO::FETCH_OBJ);
if ($userRow !== FALSE) {
$by = $userRow->name;
$insert_report = $con->prepare("
INSERT INTO `report` (`med_id`,`pat_id`,`dtime`,`responsible`,`status`) values(:m_id,:p_id,:time,:by,'3')"
);
$insert_report->bindparam(':m_id',$drug_id);
$insert_report->bindparam(':p_id',$pat_id);
$insert_report->bindparam(':time',$end_time);
$insert_report->bindparam(':by',$by);
$insert_report->execute();
$mail = new PHPMailer();
$mail->isSMTP();
$mail-> SMTPOptions = array (
'ssl' => array (
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
$mail->Host = "smtp.gmail.com";
$mail->SMTPAuth = true;
$mail->SMTPSecure = "tls";
$mail->Port = "587";
$mail->Username = "from@gmail.com";
$mail->Password = "12345678";
$mail->Subject = "Medication Report";
$mail->setFrom("from@gmail.com",$by);
$mail->isHTML(true);
//Attachment
//$mail->addAttachment('img/attachment.png');
//Email body
$mail->Body = "<h3>Medication Report by ($by) </h3></br>
You are being alerted that <b>$by</b> has missed their $directions Medication $row->med_type. And you may need to take appropriate action..";
$mail->addAddress($to_email['Email_add']);
$mail->send();
}
} // while($row = ...
} //while $timingRow = ...
您的 PHPMailerAutoload.php 文件位于何处?
你需要用这个导入它:
require_once('phpmailer/PHPMailerAutoload.php');
总体而言,您必须执行以下步骤:
单击页面右下角的“下载 ZIP”按钮,从 https://github.com/PHPMailer/PHPMailer 下载程序包。
解压缩文件。
上传语言文件夹,class.phpmailer.php、class、pop3.php、class.smtp.php、PHPMailerAutoload.php都放在同一个目录下在你的服务器上,我想在服务器上创建一个名为 phpmailer 的目录来放置所有这些。
在您的项目中加载 class:
require_once('phpmailer/PHPMailerAutoload.php');
完成...
如果您不使用异常,您仍然需要加载异常 class,因为它在内部使用。
因此,像这样将 use 放在页面顶部(我认为这就是您收到未定义错误的原因):
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
然后像这样调用文件:
require 'path/to/PHPMailer/src/Exception.php';
require 'path/to/PHPMailer/src/PHPMailer.php';
require 'path/to/PHPMailer/src/SMTP.php';
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
try {
$mail->SMTPDebug = 0;
$mail->isSMTP();
$mail->Host = "smtp.gmail.com";
$mail->SMTPAuth = true;
$mail->Username = "email@gmail.com";
$mail->Password = "password";
$mail->Port = 587;
$mail->setFrom('admin@example.com', 'Mailer');
$mail->addAddress($email);
$mail->addReplyTo("user@gmail.com", "Alias");
$mail->CharSet = "UTF-8";
$mail->isHTML(true);
$mail->Subject = $subject;
$mail->Body = $message;
$mail->send();
echo "Mail sent.";
} catch (Exception $e) {
echo "Failed. Mailer error: {$mail->ErrorInfo}";
}
有时这条线 use PHPMailer\PHPMailer\PHPMailer;
像这样工作 use PHPMailer\PHPMailer;
尝试两种方式。但我认为第一个对你有用。
我不使用 ssl 选项,如果您需要它,只需将它放在 isSMTP 下即可。
$mail-> SMTPOptions = array (
'ssl' => array (
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
这里是发送多封邮件的例子:Send multiple email
注意:您必须将您的 gmail 帐户设置为应用安全性较低才能使用 phpmailer。
因为 Gmail 已经开始实施一种身份验证机制,用 SMTP 身份验证代替基于 OAuth2 的授权。 more info
安全性较低的帐户more info , Less secure accounts
据您所知,Google 正在阻止低安全帐户。