2009-04-23 2 views
1

Я не совсем понимаю, как все это работает, но я получаю эту ошибку:Zend Framework: Фатальная ошибка при попытке использовать Zend почтового транспорта отправить несколько писем с вложениями

Фатальная ошибка: Разрешены памяти размером из 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('[email protected]', '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"); 

мне нужно выяснить, как отправить электронное письмо с приложением на пару сотен человек. Вот кое-что еще я придумал, но это кажется немного Hacky, чтобы установить только ОЦК и не обращаться:

$message = new Zend_Mail('utf-8'); 
    $message->setFrom('[email protected]', '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». Не могли бы вы указать мне в правильном направлении? Что-то я не делаю?

ответ

2

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

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

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

+0

Много больших совет здесь! Однако (без установки предела памяти), и только отправка одного сообщения электронной почты, я все еще получаю ошибку.Имеет ли ошибка, что ограничение памяти в настоящее время установлено на 8Mb, и что он перейдет на 250K? Я запускаю это локально (с помощью MAMP), поэтому я задаюсь вопросом ... если я установил это в своем коде как 32Mb, это будет меньше, чем мой сервер способен? Будет ли я делать плохую услугу, установив это значение, вместо того, чтобы найти лучшее решение? – Andrew

+0

8M слишком мало. На самом деле, по умолчанию PHP memory_limit составляет 16M от PHP5.2.0. Установка его на 32M не должна быть проблемой вообще, если у вас нет очень низкого уровня сервера/компьютера. Лично я запускаю 128M на моей рабочей станции и на моем сервере (соответственно 4G/2G памяти). Что касается вашего текущего memory_limit, ini_get ('memory_limit'). Что касается вашего текущего использования, memory_get_peak_usage() и memory_get_usage(). Что касается неприятности? Имхо, нет. Использование все еще находится в допустимых параметрах. – tommym

2

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

$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('[email protected]', 'Mailing List') 
      ->addTo($subscriber->email) 
      ->setSubject($subject) 
      ->setBodyText($body); 
    $message->addAttachment($attachment); 
    $message->send($smtpConnection); 
} 
0

У меня была аналогичная проблема с ограничением памяти и отправкой одним SMTP-соединением для большого количества сообщений. Zend_Mail_Protocol_Abstract хранит свой внутренний журнал в памяти. В журнале регистрируются все почтовые запросы. Журнал растет с каждым отправленным сообщением. Иногда вы должны иногда вызывать $ protocol-> resetLog(). (Это зависит от объема данных для каждого сообщения Вы можете проверить использование памяти с помощью 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 
    } 

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

 Смежные вопросы

  • Нет связанных вопросов^_^