问题
我有一个脚本可以将通讯发送给我的联系人。如果我没有附件(2,000封电子邮件证明),该脚本可以正常工作。
现在,如果我使用附件,脚本也可以正常工作。但是只能发送大约30封电子邮件。
测试设置
测试版本
memory_limit
从100M更改为500M->无效。收到34封电子邮件后仍然出错。sleep(5)
->无效。收到34封电子邮件后仍然出错。max_execution_time
无效。假设
由于这种行为,我希望有一个内存问题而不是一个时间问题。
但是对每个循环的内存(memory_get_usage()
)的测试表明,第一个循环的内存为1.1 MB
,第34个循环的内存为1.2 MB
。
问题
请在下面的代码中查找,但我想应该没问题。 是否有人知道导致问题的原因?非常感谢!
myMailer.class
class myMailer extends PHPMailer {
public function __construct(?bool $exceptions = true) {
$config = parse_ini_file('../../ini/config.ini', true);
parent::__construct($exceptions);
try {
// Language of Errors
$this->setLanguage('en', dirname(__FILE__) . '/../external/PHPMailer/language/');
// Server settings
$this->SMTPDebug = 0; // Enable verbose debug output
$this->isSMTP(); // Set mailer to use SMTP
$this->SMTPAuth = true; // Enable SMTP authentication
$this->SMTPSecure = 'ssl'; // Enable TLS encryption, `ssl` also accepted
$this->Port = 465; // TCP port to connect to
$this->Host = $config['smtp_server']['host']; // SMTP server
$this->Username = $config['smtp_server']['username']; // SMTP username
$this->Password = $config['smtp_server']['password']; // SMTP password
$this->CharSet ='UTF-8'; // Set Character Set
$this->isHTML(true); // Set email format to HTML
$this->setFrom("office@superman.com", "superman OFFICE");
} catch (Exception $e) {
// echo 'Message could not be sent. Mailer Error: ', $mail->ErrorInfo;
trigger_error("myMailer(): " . $this->ErrorInfo,E_USER_ERROR);
}
}
public function setBody(string $salutation, string $receiver, string $message) : void {
// Linebreak to <BR>
$message = nl2br($message);
// Create Body
$body = file_get_contents('../../ini/email_template.html');
$body = str_replace("{Receiver}", $receiver, $body);
$body = str_replace("{Salutation}", $salutation, $body);
$body = str_replace("{Message}", $message, $body);
$this->Body = $body;
}
}
send_emails.php
<?php
$groupID = $_POST['id'];
$subject = $_POST['Subject'];
$message = $_POST['Message'];
$attachments = (key_exists('Files', $_POST)) ? $_POST['Files'] : array();
$group = new Group($groupID);
// Prepare and get HTML
$htmlGenerator = HtmlGenerator::getInstance();
$htmlGenerator->setTitle("sending emails");
$header = $htmlGenerator->getWebbaseHtmlHeader();
$footer = $htmlGenerator->getWebbaseHtmlFooter();
echo $header;
?>
<div class="container">
<h1>Emailing</h1>
<h3>Group: <?php echo $group->getTitle(); ?></h3>
<h4>Number of members: <?php echo $group->getNumberOfMembers(); ?></h4>
<?php
$strScreenOutput = "
<table class='table table-sm table-hover table-responsive-md'>
<thead class='thead-dark'>
<th scope='col'>Nr.</th>
<th scope='col'>Date</th>
<th scope='col'>Company</th>
<th scope='col'>Lastname</th>
<th scope='col'>Firstname</th>
<th scope='col'>Email</th>
<th scope='col'>Newsletter</th>
<th scope='col'>Result</th>
</thead>
<tbody>";
$protocol = $strScreenOutput;
echo $strScreenOutput;
$i = 0;
$members = Contact::getAllOfGroup($groupID);
foreach ($members as $contact) {
$i++;
$datRun = date('d.m.Y (H:i:s)');
if ($contact->getNewsletter() === false) {
$result = "no sub.";
} elseif ($contact->getEmail() === "" || $contact->getEmail() === null) {
$result = "no email";
} else {
$return = $contact->sendEmail($subject, $message, $attachments);
$result = ($return===true) ? "ok" : $return;
}
// create feedback for browser
$strScreenOutput = "<tr>";
$strScreenOutput .= "<th scope='row'>".str_pad($i, 4 ,'0', STR_PAD_LEFT)."</th>";
$strScreenOutput .= "<td>{$datRun}</td>";
$strScreenOutput .= "<td>{$contact->getCompany()}</td>";
$strScreenOutput .= "<td>{$contact->getLastName()}</td>";
$strScreenOutput .= "<td>{$contact->getFirstName()}</td>";
$strScreenOutput .= "<td>{$contact->getEmail()}</td>";
$strScreenOutput .= "<td>".(($contact->getNewsletter()) ? "yes" : "no")."</td>";
$strScreenOutput .= "<td>{$result}</td>";
$strScreenOutput .= "</tr>";
echo str_pad($strScreenOutput,4096)."\n"; // Add some additional blanks to enable flushing (as some browsers suppress flushing)
// create internal protocol
$protocol .= $strScreenOutput . "\n";
// Send to browser
flush();
ob_flush();
// add some execution time
set_time_limit(30);
}
$strScreenOutput = "</tbody>
</table>";
$protocol .= $strScreenOutput;
echo $strScreenOutput;
?>
<h3>Emails successfully transmitted.</h3>
</div>
<?php
// send protocols
$protocol = "<h3>Group: {$group->getTitle()}</h3>".$protocol;
$protocol = "<div style='margin-top: 30px'>$protocol</div>";
$internal = new Contact(1);
$internal->sendEmail("PROTOCOL: ".$subject, $message . $protocol, $attachments);
echo $footer;
联系人:: sendEmail()
public function sendEmail(string $subject, string $message, array $attachments = array()) {
$mail = new myMailer();
if ( is_null($this->getEmail() || $this->getEmail() == "") ) {
return false;
} else {
try {
// Compose Email
$mail->addAddress($this->getEmail(), $this->getFirstName() . " " . $this->getLastName());
$mail->Subject = $subject;
$mail->setBody($this->getSalutationText(), $this->getAddress(), $message);
foreach ($attachments as $file) {
$uploadPath = $_SERVER['DOCUMENT_ROOT'] . "/../../files/email_attachments/";
$file_url = $uploadPath.$file;
if (! is_dir($uploadPath)) { die("Folder \"$uploadPath\" does not exist.");}
if (! file_exists($file_url)) { die("File \"$file_url\" does not exist."); }
$mail->addAttachment($file_url);
}
$return = $mail->send();
// clean up
$mail->clearAddresses();
$mail->clearAttachments();
} catch (Exception $error) {
$return = $error->getMessage();
}
return $return;
}
unset($mail);
}
答案 0 :(得分:0)
这听起来确实像是内存问题-发送大型附件时,PHPMailer在内存上的效率不是很高-尝试在循环内回显从memory_get_usage()获得的内容,以确认内存消耗。
通常,由于创建新的PHPMailer实例,重新处理相同的附件并为每封邮件打开新的SMTP连接,您的发送效率非常低,所有这些仅需要执行一次。有关如何更高效地发送邮件,请查看the mailing list example provided with PHPMailer和the wiki doc on sending to lists。
更有效地重用实例和连接可能会减少总体内存需求。