Форум программистов, компьютерный форум, киберфорум
PHP для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/18: Рейтинг темы: голосов - 18, средняя оценка - 4.67
7 / 7 / 3
Регистрация: 28.01.2013
Сообщений: 70

Приходят дубликаты писем mail()

14.02.2013, 21:47. Показов 3591. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Организована рассылка писем на ~30 000 адресов подписчиков. Рассылка по cron каждые 2 минуты. В базе данных организуется очередь с идентификаторами сообщений и подписчиков. После выбирается 300 адреатов. Через цикл происходит отправка одного письма на 300 адресов. Так примерно за 3,5 часа уходит вся почта. Однако проблема возникла в отправке дубликатов писем. По логам отправки видно что письмо отправляется 2 раза за одно время.
Так же по крону запущена задача формирования списка подписчиков, но разница между ее вызовом и вызовом функции отправки 1,5 минуты.
В чем может быть проблема?
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// Проверка на наличие подготовленных писем
 $lettersQueryOne = $db_connect->prepare("SELECT `user_id`,`id`,`message_id`,`is_sended` FROM `subscribe_letter` WHERE `is_sended`=0 ORDER BY `id` ASC LIMIT 300");
                    $lettersQueryOne->execute();
                    $lettersQuery = $lettersQueryOne->fetchAll(PDO::FETCH_ASSOC);
   
                    if(empty($lettersQuery)){
//Если очередь пуста устанавливаем для письма значение ОТПРАВЛЕНО
                        $subscribeMessageSet = $db_connect->prepare("UPDATE `subscribe_messages` SET `is_sended`=1 WHERE `to_all`=1 AND `letters_created`=1 AND `is_sended`=0");
                        $subscribeMessageSet->execute();
                        
                        $truncate = $db_connect->query("TRUNCATE TABLE `subscribe_letter`");
                    }
                    foreach ($lettersQuery as $key => $letters) {
//Устанавливаем для выбранного адресата значение отправлено в очереди
                        $lettersQueryOne = $db_connect->prepare("UPDATE `subscribe_letter` SET `is_sended` WHERE `id`=?");
                        $lettersQueryOne->bindParam(1, $letters['id']);
                        $lettersQueryOne->execute();
 //Выбираем сообщение для отправки                       
                            $messageOne = $db_connect->prepare("SELECT * FROM `subscribe_messages` WHERE `id`=?");
                            $messageOne->execute(array($letters['message_id']));
                            $message = $messageOne->fetch();
//выбираем данные пользователя согласно идентификатора из таблицы с пользователями                            
                            $userOne = $db_connect->prepare("SELECT * FROM `sf_guard_user` WHERE `id`=?");
                            $userOne->execute(array($letters['user_id']));
                            $user = $userOne->fetch();
//Формируем тело письма                            
                            $messageId = $message['id'];
                            $body = $message['body'];
                            $subject = $message['title'];
//Проверка кода отказа от подписки, если нет, то формируется новый код через отдельную функцию                            
                            if (empty($user['unsubscribe_code']))
                                {
                                  $userOneUnsubscribe = $db_connect->prepare("UPDATE `sf_guard_user` SET `unsubscribe_code`=? WHERE `id`=?");
                                  $unsubscribeCode = generateRandomKey($user['id']);
                                  $userOneUnsubscribe->bindParam(1, $unsubscribeCode);
                                  $userOneUnsubscribe->bindParam(2, $user['id']);
                                  $userOneUnsubscribe->execute();
                                  $user['unsubscribe_code'] = $unsubscribeCode;
                                }
//Замена маркеров в сообщение индивидуально, для каждого адресата                             
                            $markers['#UNSUBSCRIBE_URL#'] = sprintf('%s/subscribe/unsubscribe/%s', $url, $user['unsubscribe_code']);
                            $markers['#STATISTIC_URL#'] = sprintf('%s/subscribe/%s/%s/', $url, $messageId, $user['id']);
                            $markers['#USER_NAME#'] = iconv('utf-8','windows-1251','Уважаемый');
                            $markers['#USER_SRNAME#'] = iconv('utf-8','windows-1251','пользователь');
                            
                            foreach($markers as $key => $value)
                            {
                $body = str_replace($key, $value, $body);
                            }
  //Опять же замена                          
                            $body = replaceMarkers($body,$user['id'],$message['deal_id'], $db_connect);
                            $subject = replaceMarkers($subject,$user['id'],$message['deal_id'], $db_connect);
 
                             try {
                $result = mail($user['username'],$subject, $body, $headers);//$user['username']
                             
            } catch (PDOException $e) {
                echo $e->getMessage()."\n";
                $result = true;
            }
                        if ($result) {                            
    //Запись в лог соответственно
                            $emailLogOne = $db_connect->prepare("INSERT INTO `email_log`(`email`,`title`,`body`,`created_at`,`updated_at`) VALUES(?,?,?,NOW(),NOW())");
                            $emailLogOne->bindParam(1, $user['username']);
                            $emailLogOne->bindParam(2, $subject);
                            $emailLogOne->bindParam(3, $body);
                            $emailLogOne->execute();
            }
                            
                    }
          $db_connect = NULL;
Да и дубликаты приходят не на се адреса. Только лишь на некоторые. Может ли это зависеть напрямую от работы сервера? Возможна ли причина в формируемой сервером очереди на отправку, т.е. происходит глюк в отправке, поэтому выполнение скрипта накрывается медным тазом, в итоге повторная отправка. Хотя в списках письмо отмечается как "ОТПРАВЛЕНО" еще ДО вызова mail().
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.02.2013, 21:47
Ответы с готовыми решениями:

Не приходят письма на mail.ru
Здравствуйте! вот такая проблема на сайте есть форма обратной связи и php который должен отправлять письмо мне на mail.ru, но письма не...

Не приходят письма на mail.ru
Не понимаю в чем дело. На яндекс письма приходят, а вот на мail нет. Что за конфиг необходимо править? function maill($to, $title,...

Не приходят письма на mail.ru
Не приходят письма на маил, меняю на яндекс почту все приходит как надо, в чем может быть проблема? $name =...

8
 Аватар для Sam1
14 / 14 / 1
Регистрация: 07.02.2013
Сообщений: 88
14.02.2013, 21:57
BaNdErOzZzZz, убери 60-ую строку
Цитата Сообщение от BaNdErOzZzZz Посмотреть сообщение
$result = true;
и попробуй, должно получится
0
7 / 7 / 3
Регистрация: 28.01.2013
Сообщений: 70
14.02.2013, 22:03  [ТС]
Спасибо. Так уже делал)) Беда остается. Может мне в очередь формировать сразу готовые сообщения и адреса, а не ID ? А потом просто осуществлять отправку. Может большая нагрузка на мускул... А не может быть проблемы в самом сервере ?? (FreeBSD)
0
 Аватар для Sam1
14 / 14 / 1
Регистрация: 07.02.2013
Сообщений: 88
14.02.2013, 22:15
Цитата Сообщение от BaNdErOzZzZz Посмотреть сообщение
Может большая нагрузка на мускул...
это исключено, бивало и больше


Цитата Сообщение от BaNdErOzZzZz Посмотреть сообщение
А не может быть проблемы в самом сервере ?? (FreeBSD)
ну врятли такое может быть
попробуй изменить 56 ую строку на
PHP
56
$result = "mail($user['username'],$subject, $body, $headers)";//$user['username']
уверен получится
0
7 / 7 / 3
Регистрация: 28.01.2013
Сообщений: 70
14.02.2013, 22:32  [ТС]
Прошу прощения закинул не тот код. Т.е. неполный. Вот нормальный вариант. Там в комментариях отмечены исправления. Спасибо. Сейчас попробую... И еще вопрос. Скажите какую нагрузку по письмам выдержит mail() ? С учетом несуществующих ящиков...
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// Проверка на наличие подготовленных писем
 $lettersQueryOne = $db_connect->prepare("SELECT `user_id`,`id`,`message_id`,`is_sended` FROM `subscribe_letter` WHERE `is_sended`=0 ORDER BY `id` ASC LIMIT 300");
                    $lettersQueryOne->execute();
                    $lettersQuery = $lettersQueryOne->fetchAll(PDO::FETCH_ASSOC);
   
                    if(empty($lettersQuery)){
//Если очередь пуста устанавливаем для письма значение ОТПРАВЛЕНО
                        $subscribeMessageSet = $db_connect->prepare("UPDATE `subscribe_messages` SET `is_sended`=1 WHERE `to_all`=1 AND `letters_created`=1 AND `is_sended`=0");
                        $subscribeMessageSet->execute();
//Очищаем очередь                        
                        $truncate = $db_connect->query("TRUNCATE TABLE `subscribe_letter`");
                    }
                    foreach ($lettersQuery as $key => $letters) {
//---------ИСПРАВЛЕНО---------Устанавливаем для выбранного адресата значение отправлено в очереди, дабы не слать дубликат(В ПРЕДЫДУЩЕМ ВАРИАНТЕ НЕ БЫЛО `is_sended`=1)
                        $lettersQueryOne = $db_connect->prepare("UPDATE `subscribe_letter` SET `is_sended`=1 WHERE `id`=?");
                        $lettersQueryOne->bindParam(1, $letters['id']);
                        $lettersQueryOne->execute();
 //Выбираем сообщение для отправки                       
                            $messageOne = $db_connect->prepare("SELECT * FROM `subscribe_messages` WHERE `id`=?");
                            $messageOne->execute(array($letters['message_id']));
                            $message = $messageOne->fetch();
//выбираем данные пользователя согласно идентификатора из таблицы с пользователями                            
                            $userOne = $db_connect->prepare("SELECT * FROM `sf_guard_user` WHERE `id`=?");
                            $userOne->execute(array($letters['user_id']));
                            $user = $userOne->fetch();
//Формируем тело письма                            
                            $messageId = $message['id'];
                            $body = $message['body'];
                            $subject = $message['title'];
//Проверка кода отказа от подписки, если нет, то формируется новый код через отдельную функцию                            
                            if (empty($user['unsubscribe_code']))
                                {
                                  $userOneUnsubscribe = $db_connect->prepare("UPDATE `sf_guard_user` SET `unsubscribe_code`=? WHERE `id`=?");
                                  $unsubscribeCode = generateRandomKey($user['id']);
                                  $userOneUnsubscribe->bindParam(1, $unsubscribeCode);
                                  $userOneUnsubscribe->bindParam(2, $user['id']);
                                  $userOneUnsubscribe->execute();
                                  $user['unsubscribe_code'] = $unsubscribeCode;
                                }
//Замена маркеров в сообщение индивидуально, для каждого адресата                             
                            $markers['#UNSUBSCRIBE_URL#'] = sprintf('%s/subscribe/unsubscribe/%s', $url, $user['unsubscribe_code']);
                            $markers['#STATISTIC_URL#'] = sprintf('%s/subscribe/%s/%s/', $url, $messageId, $user['id']);
                            $markers['#USER_NAME#'] = iconv('utf-8','windows-1251','Уважаемый');
                            $markers['#USER_SRNAME#'] = iconv('utf-8','windows-1251','пользователь');
                            
                            foreach($markers as $key => $value)
                            {
                $body = str_replace($key, $value, $body);
                            }
  //Опять же замена                          
                            $body = replaceMarkers($body,$user['id'],$message['deal_id'], $db_connect);
                            $subject = replaceMarkers($subject,$user['id'],$message['deal_id'], $db_connect);
 
                             try {
                $result = mail($user['username'],$subject, $body, $headers);//$user['username']
                             
            } catch (PDOException $e) {
                echo $e->getMessage()."\n";
                $result = true;
            }
                        if ($result) {        
//------(Исправлено)------------Ставит в столбце "Отправлено" - 2, что значит отправлено окончательно
                            $lettersOne = $db_connect->prepare("UPDATE `subscribe_letter` SET `is_sended`=2,`sended_at`=NOW() WHERE `id`=?");
                            $lettersOne->execute(array($letters['id']));                    
    //Запись в лог соответственно
                            $emailLogOne = $db_connect->prepare("INSERT INTO `email_log`(`email`,`title`,`body`,`created_at`,`updated_at`) VALUES(?,?,?,NOW(),NOW())");
                            $emailLogOne->bindParam(1, $user['username']);
                            $emailLogOne->bindParam(2, $subject);
                            $emailLogOne->bindParam(3, $body);
                            $emailLogOne->execute();
            }
                            
                    }
          $db_connect = NULL;
0
 Аватар для Sam1
14 / 14 / 1
Регистрация: 07.02.2013
Сообщений: 88
14.02.2013, 22:50
BaNdErOzZzZz, смотря на мошность сервера, число сообшеный за раз и тд.
сколько оперативки на серваке, частота проца какая? сколько сообщеный собираешся отправлять за раз?
0
7 / 7 / 3
Регистрация: 28.01.2013
Сообщений: 70
14.02.2013, 23:08  [ТС]
Нет доступа у меня к "телу" сервера. Пока столько хватает. По 300 в 2 минуты. Ограничений не стоит на отправку. Попробую переделать формирование списка отправки. Разгружу этот скрипт.
Я так понимаю ВООБЩЕ для рассылок лучше использовать сокеты, SMTP. Хотя функция mail() же сама не отправляет письма, а только передает почтовому клиенту в очередь, если я все правильно понимаю...
0
 Аватар для Sam1
14 / 14 / 1
Регистрация: 07.02.2013
Сообщений: 88
14.02.2013, 23:13
Цитата Сообщение от BaNdErOzZzZz Посмотреть сообщение
Пока столько хватает. По 300 в 2 минуты. Ограничений не стоит на отправку.
да так нагрузки не будет.

Цитата Сообщение от BaNdErOzZzZz Посмотреть сообщение
Приходят дубликаты писем mail()
проблема решилась?
0
7 / 7 / 3
Регистрация: 28.01.2013
Сообщений: 70
15.02.2013, 21:33  [ТС]
Приходят дубликаты. Периодами. Бывает что может и 17 штук прислать на один адрес. Звонили - жаловались. По логам по 2 раза прогоняет некоторые адреса.
PHP
1
$result = "mail($user['username'],$subject, $body, $headers)"
Так-то оно вообще не отправиться )) Может все-таки в сервере проблема ??

Добавлено через 4 часа 18 минут
и может ли заключаться проблема в том, что в кроне не php вызов, а wget ???
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
15.02.2013, 21:33
Помогаю со студенческими работами здесь

Функция mail() - письма не приходят на почту
Всем привет. Делаю простенькую форму с отправкой на почту на сайте. Она аяксовая. Она вроде как работает (после отправки формы приходит...

Используя функцию mail() не приходят письма
всем привет, столкнулся с такой проблемой , что используя функцию mail() не приходят письма, но функция сама отрабатывает $headers =...

Отправка писем через функцию mail();
всем привет!... встал вопрос отправки писем по базе зарегистрированных пользователей которые имеются на сайте. создал код - все...

Отправка писем через функцию mail();
всем привет!... столкнулся с такой проблемой то, что не могу отправить письма по всей базе данных! в базе 10 348 электронных ящиков....

Функция mail() .Отправка писем со множеством вложений
Здравствуйте, Никак не могу понять ,как отправить письмо со множеством (неопределенным) вложений. Суть следующая: Имеется некая...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru