2009-04-23 3 views
1

Je ne comprends pas tout à fait comment tout cela fonctionne, mais je reçois cette erreur:Zend Framework: Erreur fatale lorsque vous essayez d'utiliser Zend Mail Transport pour envoyer plusieurs emails avec pièces jointes

Erreur fatale: taille maximale autorisée pour la mémoire de 8388608 octets épuisés (essayé d'allouer 261858 octets) dans /Users/andrew/Sites/myApp/library/Zend/Mail/Transport/Smtp.php à la ligne 213

Je cours ce code localement sur mon Mac en cours d'exécution MAMP. Je ne sais pas si cela a quelque chose à voir avec ça. Ceci est mon code, essentiellement:

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

Cependant, plus les abonnés il y a, plus ce nombre finit par obtenir, et ce correctif ne vous aidera si longtemps:

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

Je dois comprendre comment envoyer un email avec une pièce jointe à quelques centaines de personnes. Voici quelque chose d'autre, je suis venu avec, mais il semble un peu hacky seulement régler le Cci et non l'adresse à:

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

Cependant, même en faisant cela, je dois préciser la « memory_limit ». Pouvez-vous me diriger dans la bonne direction? Y a-t-il quelque chose que je ne fais pas?

Répondre

2

Je suppose que votre pdf est d'environ 250Kbytes? Vous le lisez en mémoire une fois par email que vous envoyez. Ne pas. Lisez-le une fois. :) Il pourrait aussi s'agir d'un encodage dans le framework Zend.

  • file_get_contents d'appel() une fois avant votre boucle
  • Définissez la limite de mémoire beaucoup plus aussi longtemps que votre serveur peut gérer (je dirais le long des lignes de 32-128)
  • Moctets
  • unset() vos variables - devraient forcer PHP à GC il (en théorie)
  • Vous pourriez réutiliser l'objet $ message (bidouille laid, mais pourrait sauver des octets si Zend fait un certain type d'encodage de fichier et il utilise beaucoup de mémoire)

Je ferais également un cron-travail pour envoyer les email, et m'assurer que chaque email (ou une référence à lui) est stocké dans la base de données avec un statut. De cette façon, vous n'enverrez pas de mails en double si vous atteignez une autre limite de mémoire, ou un bug.

+0

Beaucoup de grande conseil ici! Cependant, (sans définir la limite de mémoire), et seulement l'envoi d'un email, je reçois toujours l'erreur.Est-ce que l'erreur signifie que la limite de mémoire est actuellement fixée à 8Mb, et qu'elle dépasse 250K? Je l'utilise en local (avec MAMP), donc je me demande ... si je le mets dans mon code à 32 Mo, cela sera-t-il inférieur à ce que mon serveur est capable de faire? Est-ce que je vais rendre un mauvais service en définissant cette valeur, plutôt que de trouver une meilleure solution? – Andrew

+0

8M est trop petit. En fait, le PHP par défaut memory_limit est 16M à partir de PHP5.2.0. Le réglage à 32M ne devrait pas être un problème à moins que vous ayez un serveur/ordinateur très bas de gamme. Personnellement je cours 128M sur mon poste de travail et mon serveur (mémoire 4G/2G respectivement). En ce qui concerne votre memory_limit actuelle, ini_get ('memory_limit'). En ce qui concerne votre utilisation actuelle, memory_get_peak_usage() et memory_get_usage(). Quant à faire un mauvais service? Imho, non. L'utilisation est toujours dans les paramètres acceptables. – tommym

2

Il n'est pas nécessaire de créer une nouvelle pièce jointe avec chaque message. Il suffit de le créer une fois puis de l'attacher chaque fois que vous l'envoyez.

$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

J'ai eu le même problème avec la limite de mémoire et l'envoi par une connexion SMTP pour beaucoup de messages. Zend_Mail_Protocol_Abstract contient sa mémoire de connexion interne. Toutes les demandes de courrier sont consignées dans le journal. Le journal grandit avec chaque message envoyé. Vous devez parfois appeler $ protocol-> resetLog(). (Cela dépend de votre quantité de données pour chaque message Vous pouvez vérifier votre utilisation de la mémoire par memory_get_usage() fonction PHP..) Essayez quelque chose comme ceci:

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

Cela pourrait aussi être utile: http://framework.zend.com/manual/en/zend.mail.multiple-emails.html