简体   繁体   English

Zend Framework:尝试使用Zend Mail Transport发送带附件的多封电子邮件时出现致命错误

[英]Zend Framework: Fatal error when trying to use Zend Mail Transport to send multiple emails with attachments

I don't totally understand how all this works, but I'm getting this error: 我不完全理解这一切是如何工作的,但我收到了这个错误:

Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 261858 bytes) in /Users/andrew/Sites/myApp/library/Zend/Mail/Transport/Smtp.php on line 213 致命错误:第213行的/Users/andrew/Sites/myApp/library/Zend/Mail/Transport/Smtp.php中允许的内存大小为8388608字节(试图分配261858字节)

I'm running this code locally on my Mac running MAMP. 我在运行MAMP的Mac上本地运行此代码。 Not sure if that has anything to do with it. 不确定这是否与它有关。 This is my code, basically: 这是我的代码,基本上:

$config = array('ssl' => 'tls', 'port' => 587, 'auth' => 'login', 'username' => 'username', 'password' => 'password');
    $smtpConnection = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config);

    foreach ($subscribers as $subscriber) {
        $message = new Zend_Mail('utf-8');
        $message->setFrom('my@mailinglist.com', 'Mailing List')
                ->addTo($subscriber->email)
                ->setSubject($subject)
                ->setBodyText($body);
        $attachment = $message->createAttachment(file_get_contents($filepath));
        $attachment->type = 'application/pdf';
        $attachment->filename = $filename;
        $message->send($smtpConnection);
    }

However, the more subscribers there are, the higher this number ends up getting, and this fix will only help for so long: 但是,订阅者越多,这个数字最终得到的越多,这个修复只会帮助这么久:

ini_set("memory_limit","12M");

I need to figure out how to send an email with an attachment to a couple hundred people. 我需要弄清楚如何发送一封带有附件的电子邮件给几百个人。 Here's something else I've come up with but it seems a little hacky to only set the bcc and not the to address: 这是我想出来的其他东西,但是只设置密件抄送而不是地址似乎有点笨拙:

$message = new Zend_Mail('utf-8');
    $message->setFrom('my@mailinglist.com', 'Mailing list')
            ->setSubject($subject)
            ->setBodyText($body);
    $attachment = $message->createAttachment(file_get_contents($filepath));
    $attachment->type = 'application/pdf';
    $attachment->filename = $filename;

    foreach ($subscribers as $subscriber) {
        $message->addBcc($subscriber->email);
    }
    $message->send($smtpConnection);

However, even doing this, I need to specify the "memory_limit". 但是,即使这样做,我也需要指定“memory_limit”。 Can you please point me in the right direction with this? 你能指点我正确的方向吗? Is there something I'm not doing? 有什么我不做的事吗?

I'm guessing your pdf is about 250Kbytes? 我猜你的pdf大概是250K字节? You're reading it into memory once per email you send out. 您发送的每封电子邮件都会将其读入内存。 Don't. 别。 Read it once. 阅读一次。 :) It might also be an encoding-thing in the Zend framework. :)它也可能是Zend框架中的编码事物。

  • Call file_get_contents() once before your loop 在循环之前调用file_get_contents() 一次
  • Set the memory limit much higher as long as your server can handle it (I'd say along the lines of 32-128 Mbytes) 只要您的服务器可以处理它就设置内存限制更高(我说的是32-128 MB)
  • unset() your variables - should force php to GC it (in theory) unset()你的变量 - 应该强制php到GC它(理论上)
  • You could reuse the $message object (ugly hack, but could save bytes if Zend does some sort of file-encoding and it uses lots of memory) 您可以重用$ message对象(丑陋的黑客,但如果Zend执行某种文件编码并且它使用大量内存,则可以节省字节)

I'd also make a cron-job for sending the emails, and making sure that each email (or a reference to it) is stored in the database along with a status. 我还会发送电子邮件,并确保每封电子邮件(或对其的引用)与状态一起存储在数据库中。 This way you won't send duplicate mails if you hit another memory limit, or bug. 这样,如果您遇到另一个内存限制或错误,您将不会发送重复的邮件。

There's no need to create a new attachment with each message. 无需为每条消息创建新附件。 Just create it once and then attach it each time you send. 只需创建一次,然后在每次发送时附加它。

$config = array('ssl' => 'tls', 'port' => 587, 'auth' => 'login', 'username' => 'username', 'password' => 'password');
$smtpConnection = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config);

$attachment = new Zend_Mime_Part(file_get_contents($filepath));
$attachment->type = 'application/pdf';
$attachment->disposition = Zend_Mime::DISPOSITION_ATTACHMENT;
$attachment->filename = $filename;

foreach ($subscribers as $subscriber) {
    $message = new Zend_Mail('utf-8');
    $message->setFrom('my@mailinglist.com', 'Mailing List')
            ->addTo($subscriber->email)
            ->setSubject($subject)
            ->setBodyText($body);
    $message->addAttachment($attachment);
    $message->send($smtpConnection);
}

I have had the similar problem with memory limit and sending by one SMTP connection for a lot of messages. 我有内存限制的类似问题,并通过一个SMTP连接发送大量的消息。 Zend_Mail_Protocol_Abstract holds its internal log in memory. Zend_Mail_Protocol_Abstract将其内部日志保存在内存中。 There are logged all mail requests in the log. 日志中记录了所有邮件请求。 The log is growing up with each message sent. 日志随着每条消息的发送而成长。 You has to call $protocol->resetLog() sometimes. 你有时需要调用$ protocol-> resetLog()。 (It depends on your data amount for each message. You can check your memory use by memory_get_usage() PHP function.) Try something like this: (这取决于每条消息的数据量。您可以通过memory_get_usage()PHP函数检查内存使用情况。)尝试这样的事情:

  $transport = new Zend_Mail_Transport_Smtp();
  $protocol = new Zend_Mail_Protocol_Smtp('localhost');
  $protocol->connect();
  $protocol->helo('localhost');
  $transport->setConnection($protocol);
  foreach(){
    $mail = new Zend_Mail('utf-8');
    ...
    $protocol->rset();
    $mail->send($transport);
    $protocol->resetLog();  // you don't need to resetLog for each message
  }

This also might be helpful: http://framework.zend.com/manual/en/zend.mail.multiple-emails.html 这也可能有用: http//framework.zend.com/manual/en/zend.mail.multiple-emails.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM