Zend Framework: фатальная ошибка при попытке использовать Zend Mail Transport для отправки нескольких писем с вложениями - PullRequest
1 голос
/ 23 апреля 2009

Я не совсем понимаю, как все это работает, но я получаю эту ошибку:

Неустранимая ошибка: допустимый объем памяти 8388608 байт исчерпан (попытка выделить 261858 байт) в /Users/andrew/Sites/myApp/library/Zend/Mail/Transport/Smtp.php в строке 213

Я запускаю этот код локально на моем Mac с MAMP. Не уверен, что это как-то связано с этим. Это мой код, в основном:

$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);
    }

Однако, чем больше подписчиков, тем выше будет это число, и это исправление будет помогать только так долго:

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

Мне нужно выяснить, как отправить электронное письмо с вложением на пару сотен человек. Вот еще кое-что, что я придумал, но кажется немного глупым задавать только bcc, а не адрес:

$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);

Однако, даже делая это, мне нужно указать «memory_limit». Можете ли вы указать мне правильное направление с этим? Есть что-то, чем я не занимаюсь?

Ответы [ 3 ]

2 голосов
/ 23 апреля 2009

Нет необходимости создавать новое вложение с каждым сообщением. Просто создайте его один раз, а затем присоединяйте при каждой отправке.

$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);
}
2 голосов
/ 23 апреля 2009

Я предполагаю, что ваш PDF составляет около 250 Кбайт? Вы читаете это в память один раз на электронное письмо, которое вы отправляете. Не. Прочитайте это один раз. :) Это также может быть вещь кодирования в среде Zend.

  • Вызовите file_get_contents () один раз перед вашим циклом
  • Установите предел памяти намного выше, если ваш сервер может его обработать (я бы сказал, 32-128 Мбайт)
  • unset () ваши переменные - должны заставить php GC его (теоретически)
  • Вы можете повторно использовать объект $ message (безобразно, но вы можете сохранить байты, если Zend выполняет какую-то кодировку файлов и использует много памяти)

Я бы также сделал cron-задание для отправки электронных писем и проверки того, что каждое электронное письмо (или ссылка на него) хранится в базе данных вместе со статусом. Таким образом, вы не будете отправлять повторяющиеся письма, если у вас будет другой предел памяти или ошибка.

0 голосов
/ 26 июня 2009

У меня была похожая проблема с ограничением памяти и отправкой одним SMTP-соединением для большого количества сообщений. Zend_Mail_Protocol_Abstract хранит свой внутренний журнал в памяти. В журнале регистрируются все почтовые запросы. Журнал растет с каждым отправленным сообщением. Вы должны иногда вызывать $ protocol-> resetLog (). (Это зависит от количества данных для каждого сообщения. Вы можете проверить использование памяти с помощью PHP-функции memory_get_usage ().) Попробуйте что-то вроде этого:

  $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
  }

Это также может быть полезно: http://framework.zend.com/manual/en/zend.mail.multiple-emails.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...