LINUX.ORG.RU

php mail и нехватка памяти.

 


0

1

Добрый день. Имеется следующая проблема:

Скрипт рассылает email сообщения по базе адресов. Пока база была маленькая проблем не было. После того как количество подписчиков перевалило за 2000 тыс. начались проблемы.

Warning: mail() [function.mail]: Could not execute mail delivery program '/usr/sbin/sendmail -t -i ' in 

Методом научного тыка установлено, что проблема в лимите памяти для php. На другом сервере подняв лимит памяти проблему решили, 4500 тыс писем улетает без проблем. На этом сервере поднять лимит не представляется возможным.

Функция в которой происходит затык выглядит так:

function sendNewsletterMail ($emails,$emailFrom,$html,$subject) {

    foreach ($emails as $id => $datas) {
      $email = $datas['val'];
      ............
      ............
      ............
      $result=mail($email, "=?utf-8?B?".base64_encode($subject." - ".$i)."?=" ,'', $headers);
    }
    return $result;
  }

Несущественное вырезал. В $emails массив с адресами. Где то в районе двухтысячного письма все это дело упирается в лимит памяти и выдает приведенную ошибку.

Какие могут быть варианты решения. Смена хостинга пока невозможна. Спасибо.


В $emails массив с адресами
варианты решения

Ты как будто с луны свалился. Конечно же, вариант решения — не пихать весь этот набор в массив, а призывать в while цикле из какой-нибудь базы данных. Или читать из файла построчно, не кидая в оперативку весь файл разом. Лимит они подняли, жеж…

alexmaru
()

Посылать порциями.

anonymous
()
Ответ на: комментарий от alexmaru

Там веб морда в которой юзер настраивает, что отсылать кому отсылать, и прочее. Соответственно этот массив есть здесь и сейчас, в момент отработки скрипта.

Переделка с вариантами создания заданий, записывания их в БД и последующей рассылки порциями, получится довольно масштабная. Пока думаю о каком нибудь костыле, как временное решение.

RaDiSt
() автор топика
Ответ на: комментарий от RaDiSt

Других вариантов как переделать не вижу. Ваш метод вообще ненадёжен - мало ли что может случиться с браузером. Я бы переписал на python script а из php ложил бы в DBMS.

tyler19
()
Ответ на: комментарий от RaDiSt

Переделка с вариантами создания заданий, записывания их в БД и последующей рассылки порциями, получится довольно масштабная.

Что там, япона мать, масштабного?

В вебморде делаешь вызов не mail(), а некой функции, которая письмо пишет в табличку вида.

CREATE TABLE  `test`.`mails` (
`id` INT( 11 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`to` VARCHAR( 255 ) NOT NULL ,
`subject` VARCHAR( 255 ) NOT NULL ,
`body` LONGTEXT NOT NULL ,
`headers` LONGTEXT NOT NULL ,
`added` TIMESTAMP NOT NULL ,
`sended` TIMESTAMP NOT NULL ,
INDEX (  `sended` ),
INDEX (  `added` )
)

Потом делаешь простой скрипт, который за раз тянет несколько писем(например 16) запросом типа

SELECT * FROM `mails` WHERE `sended`<=`added` ORDER BY `added` ASC LIMIT 16
cкармливаеш их функции mail и обновляет значение `sended` на now() если mail() отработала штатно. А потом вешаешь это добро на крон раз в минуту.

Работы на 15 мин. 5 мин из которых сделано выше.

И у тебя ещё в добавок будут логи рассылки, и админ не будет проклинать того содомита, что почтовику локальный пи...здец устраивает, а ещё и, может быть, имеет наглость требовать скриптам больше памяти и времени исполнения, чтобы пи...здец был полным.

Будет не лень - ещё на 2 мин скрипт соорудишь(из одного sql-запроса), который слишком старые логи чистить будет.

r_asian ★☆☆
()

Эээ..как костыль, использовать ссылки и удалять использованные элементы; Попробовать Mail::send вместо mail; А вообще массовую рассылку лучше делать по крону отдельной задачей

а вообще сильно - 4500 адресов из веб-морды сразу в одну переменную :)

MKuznetsov ★★★★★
()
Ответ на: комментарий от r_asian

Зачем cron 16 раз в минуту. Лучше такое в boot service `while 30 ; do /path/to/sender ; done` и брать сразу все, и слать можно в несколько потоков для ускорения.

tyler19
()
unset($result);

внутри цикла после отправки письма.

убирайте переменную из памяти если она вам не нужна

oskar0609
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.