2013-11-19 6 views
4

Я нашел несколько старых тем, имеющих аналогичную проблему, но у большинства из них не было ответов или если они были, предложения не были актуальны в моем случае.PHPMailer, использующий SMTP медленный SMTP при отправке писем

У меня была полная настройка в один момент с функцией почты PHP, и она отлично работала. Мне пришлось отформатировать жесткий диск в один момент и настроить сервер с нуля. Впоследствии функция почты PHP стала медленной. Изучая решения для этого, я обнаружил, что большинство людей рекомендуют PHPMailer. Я переключился на это, но проблема все еще сохранялась.

В большинстве случаев я отправляю по меньшей мере два письма на страницу с разными телами, но используя один и тот же объект. Задержка составляет около 3-4 секунд. Пожалуйста, найдите соответствующий код ниже ($ EMAIL1 и $ email2 массивов, содержащих действительные адреса электронной почты):

function sendEmail ($email1, $subject1, $message1, $email2, $subject2, $message2) 
{ 
    require_once('../PHPMailer/class.phpmailer.php'); 

    $mail = new PHPMailer(); 
    $mail->IsSMTP(); 
    $mail->SMTPDebug = 0; 
    $mail->SMTPAuth = true; 
    $mail->SMTPSecure = 'ssl'; 
    $mail->Host = "smtp.gmail.com"; 
    $mail->Port = 465; 
    $mail->IsHTML(true); 
    $mail->Username = $gmail_username; 
    $mail->Password = $gmail_password; 
    $mail->SetFrom($gmail_address,$email_title); 

    $mail->Subject = $subject1; 
    $mail->Body = $message1; 
    foreach($email1 as $k => $v) { $mail->AddAddress($v); }  
    if(!$mail->Send()) { $emailreturn['cust'] = 0; } else { $emailreturn['cust'] = 1; } 
    $mail->ClearAddresses(); 

    $mail->Subject = $subject2; 
    $mail->Body = $message2; 
    foreach($email2 as $k => $v) { $mail->AddAddress($v); } 
    if(!$mail->Send()) { $emailreturn['partner'] = 0; } else { $emailreturn['partner'] = 1; } 
    $mail->ClearAddresses(); 
} 

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

Что я пробовал:

  • Я выключил брандмауэр просто чтобы проверить его, и это то же самое.
  • Перешел на «ДУС», что сделало его еще более медленным
  • Направлен каждое письмо, используя объект, который дал на 3-4 секундную задержку для каждого сообщения электронной почты
  • поиграл с дополнительной конфигурацией, закомментируйте или установить ложь, все с тем же результатом

Есть ли что-либо еще в настройках почтовой программы или есть какая-то закулисная конфигурация, которую я должен проверить? Thanks

ответ

0

Одним из решений для удаления ожидания от клиента к серверу является перемещение отправки электронной почты в crontab. Поэтому, когда клиент нажимает на отправку, php добавляет электронную почту и сообщение в очередь, а затем каждую минуту вы отправляете сообщения в очереди cron.

Кроме того, вы можете добавить информацию об отладке в свой скрипт, указав $start = microtime(true); в верхней части скрипта и повторяя echo "Line ".__LINE__.":"round(microtime(true) - $start, 3)."sec<br>"; в каждой строке.

6

Если задержка между отправкой электронных сообщений является действительно важной проблемой, считаете ли вы, что вы используете форму многопоточности? Задержка на сообщение может быть одинаковой, но по существу она будет сокращена пополам, если вы отправите по два гвоздя за раз.

Простым способом сделать это будет реализация очереди, и сообщение отправляется через неблокирующий вызов HTTP/SQL. Таким образом, вы можете отправить столько, сколько хотите, с минимальной задержкой.

Я также предлагаю, если возможно, найти сервер gmail с наименьшей задержкой и добавить его в файл hosts, чтобы устранить поиск DNS.

Также некоторые подсказки о производительности: вам нужно всего лишь require_once() для включенного файла, но вы требуете его на каждом вызове (в противном случае include_once() работает быстрее). Почему бы не создать объект $ mail только один раз и повторно использовать его, когда вам нужно позвонить sendemail()?

Также почему бы не передать сообщение1, subject1 и т. Д. Как один массив и message2, subject2 и т. Д. Как второй массив? Передача меньших параметров во время вызовов процедур вообще (по крайней мере, в классическом программировании) имеет тенденцию ускорять процесс.

В стороне - не знаю, возможно ли это - Возможно, существует способ поддерживать постоянную связь с smtp.gmail.com. Это также устранит много накладных расходов.

Кроме того, передается ли ваше сообщение через ваш собственный сервер? Это устранит задержку.

Наконец, я наткнулся на этот ответ от Google: [Gmail Sending Limits `

Thank you for your message. 

    I understand you have a query regarding the Google Apps for Business sending limits. As 
mentioned  in our Help Center article at http://support.google.com/a/bin/answer.py?hl=en& 
answer=166852,  the daily limitation is 2000 messages in a 24-hour period not day. In general, our 
servers can tolerate one message per second until sending limits are hit. We really don't 
have an hourly or minute limitation for sending. If you send messages too quickly you may  
get rate-limited but the account should not lock out. 

By rate-limt, since in general one message per second, if you try to send too many messages per second 
you may get a message telling you that the message cannot be send or you must wait before sending a 
message. 

` 

Я был бы счастлив, чтобы написать класс, который соответствует этим пределам, если вам нужен. Пожалуйста, дайте мне знать, не стоит слишком долго.

Рекомендации: Используйте другой адрес электронной почты хоста/реле

+0

+1, хотя я совершенно уверен, что нет никакого способа, чтобы иметь постоянное соединение с SMTP, специально не с Gmail, ни другого аналогичные компании. – tftd

+0

Да, есть; это называется keepalive. Вы можете отправлять несколько сообщений во время одного соединения. Существует пример использования его в примере списка рассылки, предоставленном PHPMailer. – Synchro

0

Из вашего описания я предполагаю, что это выглядит как вопрос кэширования DNS возможно. Вы можете исследовать более детально времени тратится разрешить запись DNS

  • использование curl_getinfo для получения подробной информации о времени тратится на подключение Fo SMTP Google, например время поиска имени, разрешение и т. д. см. http://www.php.net/manual/en/function.curl-getinfo.php. Это поможет вам изолировать ту часть поиска, которая является проблематичной.
  • Чтобы исключить проблемы DNS, вы можете настроить DNS-сервер DNS на Общий DNS-сервер Google 8.8.8.8 или 8.8.4.4 - см. https://developers.google.com/speed/public-dns/. Если проблема по-прежнему сохраняется, возможно, вы неправильно настроили свою сеть, а затем попробуйте подключиться к SMTP-gmail с другого компьютера или хостинга, чтобы проверить время ожидания.

С точки зрения применения, было бы целесообразно для вас отправлять электронную почту асинхронно, а не синхронно, то есть с помощью фона, например, CRON-задание. Это решение подходит, если вы отправляете более 10 писем в час. Обеспечивает полный контроль над очередью стека электронной почты, ошибками отслеживания, отсутствием латентности или сбоями страниц для внешних пользователей.

1

От сервера, где Вы имеете PHPMailer размещенную, попробуйте:

telnet smtp.gmail.com 465 

Вы увидите, сколько времени потребовалось, чтобы установить соединение между сервером и smtp.gmail.com

+0

Я пробовал это, когда у меня возникла проблема, но он сказал, что соединение закрыто иностранным хостом. В чем причина? –

2

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

Другим вариантом (и это мой предпочтительный вариант) является использование слоя обмена сообщениями, такого как Rabbit MQ (возможно, более хорошие книги/сообщения по теме) или Zero MQ (если вы более прочный программист). В этом случае вы создаете событие «send-email» и выталкиваете его в очередь. Есть несколько слушателей очереди. Как только ваш PHP-скрипт выталкивает электронное письмо для отправки в очередь, оно выполняется и перемещается. Один из слушателей очереди поднимает сообщение и отправляет электронное письмо.

Это может позволить вам большую гибкость при построении решения. Поскольку большую часть времени отправлять электронную почту, похоже, является временем ожидания, вы можете запустить 10 потребительских программ для отправки электронной почты, зная, что большую часть времени отдельные отправители будут бездействовать. (Это был мой опыт отправки электронной почты - это долгое время ожидания, но не высокая загрузка процессора). Запуская определенное количество потребителей (ваш PHP-скрипт является производителем), вы можете снизить скорость отправки почтовых/посвященных системных ресурсов при отправке почты.

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

17

Медленность (или отказ из-за тайм-аутов) заключается в том, что Google поддерживает адресацию IPv6, но ваша сеть этого не делает. (например, Digital Ocean еще не поддерживает IPv6 для трафика SMTP). Так, используйте:

$mail->Host = gethostbyname("smtp.gmail.com"); 

gethostbyname() возвращает адрес IPv4.

Для меня, мой PHPMailer сценарий пошел от ~ 2 минут времени выполнения в < 4 секунды

+2

Любовь, которую я имею для вас –

+5

Этот ответ верный, но вход в систему через TLS (и, возможно, SSL) терпит неудачу, так как Host теперь всего лишь ip-адрес. Вы также должны изменить SMTPOptions: '$ mail-> SMTPOptions = array ('ssl' => array ('verify_peer_name' => false));'. – Scott

+0

Он дает следующую ошибку '2017-11-24 12:35:13 SMTP ERROR: Не удалось подключиться к серверу: (0)' – silverFoxA

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