Я пытаюсь внедрить систему списков рассылки для своего приложения. В настоящее время я использую Zend_Mail_Transport_Smtp('localhost')
качестве своего транспорта, просматривая список подписчиков и отправляя новый Zend_Mail
каждому. Тем не менее, я замечаю, что длительность времени, которое требуется для завершения сценария, увеличивается по мере увеличения количества подписчиков.
Я уверен, что для этого требуется более профессиональный подход, связанный с очередью электронных писем. Я предполагаю, что идеальный подход состоял бы в том, чтобы пользователь заполнил форму, щелкнул отправить и сразу получил ответ, в котором говорилось, что отправляются электронные письма, а не ждать, пока сотни писем будут отправлены.
Я понимаю, что Zend_Mail
не выполняет сортировку почтовых очередей. Может ли кто-нибудь, кто имеет опыт работы с этим, дать мне обзор того, как это можно сделать? Я ничего не знаю о cron / crontab / cronjobs, поэтому, если это связано с этим, пожалуйста, объясните этот процесс.
Чтобы надежно отправлять большое количество писем с использованием PHP, вам нужно использовать механизм очередей. Как было предложено другими, процесс использования очереди выглядит примерно так:
Есть несколько библиотек, которые вы можете использовать для этого, PEAR Mail Queue (с Mail_Mime) и SwiftMailer позволяют создавать и размещать электронные письма в очереди. Пока Zend Mail предоставляет только создание электронных писем, а не очередей (подробнее об этом позже).
У меня есть опыт в основном с PEAR Mail Queue, и есть несколько ошибок. Если вы пытаетесь разместить в очереди большое количество электронных писем (например, зацикливая более 20 000 пользователей и пытаясь получить их в очередь в разумные сроки), использование реализаций кодировки с использованием кавычек Mail Mime выполняется очень медленно. Вы можете ускорить это, переключившись на base64-кодирование.
Что касается Zend Mail, вы можете написать объект Zend Mail Transport, который помещает ваши объекты Zend Mail в очередь PEAR Mail. Я сделал это с некоторым успехом, но для его исправления требуется немного времени. Для этого увеличьте Zend Mail Transport Abstract, внедрите метод _sendMail (в котором вы поместите свой объект Zend Mail в очередь почты) и передайте экземпляр вашего транспортного объекта методу send () вашего объекта Zend Mail или по Zend Mail :: setDefaultTransport ().
Суть в том, что есть много способов сделать это, но от вашего имени потребуются некоторые исследования и обучение. Однако это очень разрешимая проблема.
ПРИМЕЧАНИЕ. Когда я впервые прочитал ваш вопрос, я подумал, что он сказал сразу сотни тысяч писем. Когда я дважды проверял, я заметил, что это на самом деле говорило от сотен до тысяч. Я слишком ленив, чтобы изменить свой пост сейчас, так что вот некоторые предостережения: по моему опыту, вы, вероятно, можете нормально работать без коммерческого инструмента примерно до 40K. Примерно в 10K вы захотите следить за «минимальным» списком, чтобы предотвратить большую боль, когда вы начнете достигать больших размеров списка. Я действительно рекомендую все это сразу сделать.
Я уже говорил об этом, есть две стороны для отправки электронной почты:
Я не рекомендую писать собственный отправитель. Я уверен, что PHP может отлично справиться, но вы, вероятно, должны провести время в другом месте. Два продукта, которые я использовал в прошлом и рекомендую, это Strongmail и PowerMTA. Будьте осторожны – у них высокая цена, но я могу почти гарантировать, что вы потратите больше средств на собственное решение в долгосрочной перспективе.
Одной областью, в которой вы будете прибиты к написанию своего собственного PHP, является дросселирование / детонация. Почтовые серверы начнут добавлять во сне (30) после того, как вы отправите несколько сообщений, чтобы замедлить работу и остановить вас от спама.
Как правило, эти коммерческие массовые отправители запускают протокол SMTP для организации очередей. Вы продолжаете использовать Zend_Mail, но жесткий код для подключения к вашему серверу. Он будет отправлять почту в очередь так же быстро, как вы можете отправить ее, а затем использовать свой собственный движок для отправки почты в свои адресаты.
В списке 100K вам нужно будет использовать лучшие практики электронной почты. Как минимум, вам понадобятся:
Наконец, если вы действительно серьезно относитесь к отправке электронной почты, вам понадобятся другие инструменты, такие как Return Path.
Из документации PHP.net.
Примечание. Стоит отметить, что функция mail () не подходит для больших объемов электронной почты в цикле. Эта функция открывает и закрывает SMTP-сокет для каждого письма, что не очень эффективно.
Для отправки большого количества электронной почты см. Пакеты « PEAR :: Mail» и « PEAR :: Mail_Queue» .
Класс Zend Mail, вероятно, довольно хорош (большая часть материала Zend хороша) Но если вы хотите другие варианты. Вот они.
Используйте Zend_Queue, чтобы поместить электронные письма в очередь для асинхронной обработки фона. Для обработки очереди в фоновом режиме вам понадобится задание cron.
protected function _enqueueEmail(WikiEmailArticle $email) { static $intialized = false; if (!$initialized) { $this->_initializeMailQueue("wikiappwork_queue"); $initialized = true; } $this->_mailQueue->send(serialize($email)); } protected function _initializeMailQueue() { /* See: 1.) http://framework.zend.com/manual/en/zend.queue.adapters.html and * 2.) Zend/Queue/Adapter/Db/mysql.sql. */ $ini = Zend_Controller_Front::getInstance()->getParam('bootstrap') ->getOptions(); $queueAdapterOptions = array( 'driverOptions' => array( 'host' => $ini['resources']['multidb']['zqueue']['host'], 'username' => $ini['resources']['multidb']['zqueue']['username'], 'password' => $ini['resources']['multidb']['zqueue']['password'], 'dbname' => $ini['resources']['multidb']['zqueue']['dbname'], 'type' => $ini['resources']['multidb']['zqueue']['adapter'] ), 'name' => $ini['resources']['multidb']['zqueue']['queueName'] ); $this->_mailQueue = new Zend_Queue('Db', $queueAdapterOptions); }
Затем для задания cron скрипт вроде
<?php use \Wiki\Email\WikiEmailArticle; // Change this define to correspond to the location of the wikiapp.work/libary define('APPLICATION_PATH', '/home/kurt/public_html/wikiapp.work/application'); set_include_path(implode(PATH_SEPARATOR, array( APPLICATION_PATH . '/../library', get_include_path(), ))); // autoloader (uses closure) for loading both WikiXXX classes and Zend_ classes. spl_autoload_register(function ($className) { // Zend classes need underscore converted to PATH_SEPARATOR if (strpos($className, 'Zend_' ) === 0) { $className = str_replace('_', '/', $className ); } $file = str_replace('\\', '/', $className . '.php'); // search include path for the file. $include_dirs = explode(PATH_SEPARATOR, get_include_path()); foreach($include_dirs as $dir) { $full_file = $dir . '/'. $file; if (file_exists($full_file)) { require_once $full_file; return true; } } return false; }); // Load and parese ini file, grabing sections we need. $ini = new Zend_Config_Ini(APPLICATION_PATH . '/configs/application.ini', 'production'); $queue_config = $ini->resources->multidb->zqueue; $smtp_config = $ini->email->smtp; $queueAdapterOptions = array( 'driverOptions' => array( 'host' => $queue_config->host, 'username' => $queue_config->username, 'password' => $queue_config->password, 'dbname' => $queue_config->dbname, 'type' => $queue_config->adapter), 'name' => $queue_config->queuename); $queue = new Zend_Queue('Db', $queueAdapterOptions); $smtp = new Zend_Mail_Transport_Smtp($smtp_config->server, array( 'auth' => $smtp_config->auth, 'username' => $smtp_config->username, 'password' => $smtp_config->password, 'port' => $smtp_config->port, 'ssl' => $smtp_config->ssl )); Zend_Mail::setDefaultTransport($smtp); $messages = $queue->receive(10); foreach($messages as $message) { // new WikiEmailArticle. $email = unserialize($message->body); try { $email->send(); } catch(Zend_Mail_Exception $e) { // Log the error? $msg = $e->getMessage(); $str = $e->__toString(); $trace = preg_replace('/(\d\d?\.)/', '\1\r', $str); } // end try $queue->deleteMessage($message); } // end foreach
Вы должны хорошо использовать PHP в тысячах получателей, хотя избегайте почты (), как отмечали другие. Я видел несколько систем, предназначенных для большого количества почты (100 000+ получателей), которые перешли в обход стандартных функций рассылки и пытались работать более непосредственно с MTA. Даже тогда мне было непонятно, что требовалось.
Создание почтового клиента больше связано с тем, что форматирование является хорошим (HTML и простой текст, когда это возможно), люди могут легко отказаться от подписки, исправления обрабатываются правильно, на почтовом сервере имеются все необходимые DNS-записи, а конфигурация сервера не работает, t нарушают правила любой крупной системы черного списка. Язык, на котором вы пишете приложение, не является основным фактором в нескольких сотнях или даже нескольких тысячах сообщений.
Я реализовал массовую рассылку в php, где каждое электронное письмо было настроено для отдельного человека. Это было не сложно и не занимало слишком много времени. Я использовал swiftmailer и cron. Возможно, Zend Mail тоже в порядке. Я начал с очереди сообщений PEAR, но очередность сообщений электронной почты была слишком медленной.
Процесс очередей электронной почты шел следующим образом:
Я использовал задание cron для отправки партий писем. Временной интервал cron и количество отправленных сообщений в рассылке были важны, так как я был на общем узле с ограничениями. Сценарий, который был вызван работой cron, был доступен только cron. Сценарий читает x количество сообщений электронной почты из таблицы, упорядоченной с помощью идентификатора пакета и, при необходимости, приоритета. Если письмо было успешно отправлено, оно было удалено из очереди базы данных. Если электронное письмо не может быть отправлено, оно оставалось в очереди, и счетчик был увеличен для этой записи. Если счетчик превысил установленное число, тогда сообщение было удалено из очереди.
Класс Zend Mail выглядит хорошо и прост в использовании, он также позволяет отправлять простой текст и HTML-версию электронного письма, что в маркетинге электронной почты очень важно.
Если вы знакомы с работой рамы, я буду придерживаться ее.
Важные моменты, которые следует учитывать при отправке писем на большие объемы людей:
Если ответ отрицательный или ваш неуверенный, использование теста apache должно быть в состоянии помочь вам разобраться, если это возможно. Если вы все еще не уверены, всегда лучше всего отправлять электронные письма (которые могут быть синхронизированы с помощью crontab) для распространения нагрузки.
Надеюсь, это поможет.
Я разработал систему управления рассылкой новостей с Swiftmailer, и ее очень легко реализовать. Он поддерживает SMTP, шифрование, вложения, пакетную передачу, …