Phpmailer настройка


Добрый день!
Наверное все, кому приходилось отправлять почту из кода на PHP через SMTP, знакомы с классом PHPMailer.
В статье я расскажу о том, как можно в несколько строк кода научить PHPMailer принимать в качестве дополнительного параметра IP адрес сетевого интерфейса, с которого мы хотим осуществить отправку. Естественно, что эта возможность будет полезна только на серверах с несколькими белыми IP адресами. А в качестве небольшого дополнения мы отловим достаточно неприятного жучка из кода PHPMailer`а.

Обзор архитектуры PHPMailer

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

Фронтэнд PHPMailer предоставляет поля и методы по установке параметров письма (localhost, return-path, AddAdress(), body, from и пр.), выбору способа отправки и способа аутентификации (SMTPSecure, SMTPAuth, IsMail(), IsSendMail(), IsSMTP() и пр.), а также метод Send().


Установив параметры письма и указав способ отправки (возможно выбрать из следующих: mail, sendmail, qmail или smtp), необходимо вызвать метод класса PHPMailer Send(), который, в свою очередь, делегирует вызов внутреннему методу, отвечающему за отправку почты тем или иным способом. Так как нас интересует именно SMTP, то далее в основном мы будем рассматривать плагин SMTP из файла class.smtp.php.

При использовании метода PHPMailer::IsSMTP() метод PHPMailer::Send() вызовет защищенный метод PHPMailer::SmtpSend($header, $body), передав ему сформированные заголовки и тело письма.

Метод PHPMailer::SmtpSend() попытается подключиться к удаленному SMTP-серверу получателя (если это уже не первая отправка письма объектом PHPMailer, то скорее всего соединение уже было установлено и этот шаг будет пропущен) и инициировать с ним стандартную SMTP-сессию (HELLO/EHLO, MAIL TO, RCPT, DATA и т.д.).

Соединение с SMTP-сервером происходит в публичном методе PHPMailer::SmtpConnect(). Так как для одного домена может быть сразу несколько MX-записей с различными приоритетами, то метод PHPMailer::SmtpConnect() попытается последовательно соединиться с каждым из SMTP-серверов, указанных при конфигурировании PHPMailer.

Жучок в коде

А теперь внимательно посмотрим на код PHPMailer::SmtpConnect():

/**  * Initiates a connection to an SMTP server.  * Returns false if the operation failed.  

@uses SMTP * @access public * @return bool */ public function SmtpConnect() { if(is_null($this->smtp)) { $this->smtp = new SMTP(); } $this->smtp->do_debug = $this->SMTPDebug; $hosts = explode(';', $this->Host); $index = 0; $connection = $this->smtp->Connected(); // Retry while there is no connection try { while($index < count($hosts) && !$connection) { $hostinfo = array(); if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) { $host = $hostinfo[1]; $port = $hostinfo[2]; } else { $host = $hosts[$index]; $port = $this->Port; } $tls = ($this->SMTPSecure == 'tls'); $ssl = ($this->SMTPSecure == 'ssl'); if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) { $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname()); $this->smtp->Hello($hello); if ($tls) { if (!$this->smtp->StartTLS()) { throw new phpmailerException($this->Lang('tls')); } //We must resend HELO after tls negotiation $this->smtp->Hello($hello); } $connection = true; if ($this->SMTPAuth) { if (!$this->smtp->Authenticate($this->Username, $this->Password)) { throw new phpmailerException($this->Lang('authenticate')); } } } $index++; if (!$connection) { throw new phpmailerException($this->Lang('connect_host')); } } } catch (phpmailerException $e) { $this->smtp->Reset(); if ($this->exceptions) { throw $e; } } return true; }

В коде $this->smtp — это объект класса-плагина SMTP.

Постараемся разобраться, что же авторы имели в виду. Для начала выполняется проверка, создан ли внутренний объект, умеющий работать с SMTP и выполняется его создание, если это первый вызов метода SmtpConnect() объекта класса PHPMailer (на самом деле еще метод PHPMailer::Close() может превратить $this->smtp в null).

Затем поле PHPMailer::Host разбивается по разделителю ‘;’ и в итоге получается массив MX-записей для домена получателя. Если в Host была всего одна запись (например, ‘smtp.yandex.ru’), то в массиве будет всего один элемент.

Далее выполняется проверка, а не подключены ли мы уже к серверу получателя. Если это первый вызов SmtpConnect(), то очевидно, что $connection будет false.

Вот мы и добрались до самого интересного. Начинается цикл по всем MX-записям, в каждой итерации которого производится попытка подключения к очередному MX. Но что будет, если выполнить в голове алгоритм этого цикла, представив, что для первой MX-записи if ($this->smtp->Connect(($ssl? ‘ssl://’:»).$host, $port, $this->Timeout)) вернула false? Окажется, что цикл бросит исключение, которое будет перехвачено уже за циклом. Т.е. все остальные MX-записи не будут проверены на доступность и мы поймаем исключение.

Но это еще не самое неприятное. PHPMailer умеет работать в двух режимах — бросать исключения, либо же тихо умирать с записью сообщения об ошибке в поле ErrorInfo. Так вот в случае использования тихого режима ($this->exceptions == false, причем это режим по умолчанию) SmtpConnect() вернет true!


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

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

public function SmtpConnect()  {  if(is_null($this->smtp)) {  $this->smtp = new SMTP();  }   $this->smtp->do_debug = $this->SMTPDebug;  $hosts = explode(';', $this->Host);  $index = 0;  $connection = $this->smtp->Connected();   // Retry while there is no connection  try {  while($index < count($hosts) && !$connection) {  $hostinfo = array();  if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {  $host = $hostinfo[1];  $port = $hostinfo[2];  } else {  $host = $hosts[$index];  $port = $this->Port;  }   $tls = ($this->SMTPSecure == 'tls');  $ssl = ($this->SMTPSecure == 'ssl');   $bRetVal = $this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout);  if ($bRetVal) {  $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());  $this->smtp->Hello($hello);   if ($tls) {  if (!$this->smtp->StartTLS()) {  throw new phpmailerEx.  

sage()); if ($this->smtp->Connected()) $this->smtp->Reset(); if ($this->exceptions) { throw $e; } return false; } return true; }

Расширяем PHPMailer для работы с несколькими сетевыми интерфейсами

Плагин SMTP PHPMailer`а работает с сетью через fsockopen, fputs и fgets. Если на нашей машине несколько сетевых интерфейсов, смотрящих в Интернет, fsockopen в любом случае создаст сокет на первом соединении. Нам же необходимо уметь создавать на любом.

Первая мысль, которая пришла в голову — это использовать стандартную связку классических сокетов socket_create, socket_bind, socket_connect, которая в socket_bind позволяет указать с каким сетевым интерфейсом связать сокет, указав его IP адрес. Как оказалось, мысль не совсем удачная. В результате пришлось переписать практически весь плагин PHPMailer`а SMTP, заменив в нем fputs и fgets на socket_read и socket_write, потому что fputs и fgets не умеют работать с ресурсом, созданным socket_create. Заработало, но на душе остался осадок.

Следующая мысль оказалась удачнее. Существует же функция stream_socket_client, создающая потоковый сокет, который можно благополучно читать fgets`ом! В результате, заменив всего один метод в плагине SMTP, можно научить PHPMailer отсылать почту с явным указанием сетевого интерфейса, и при этом практически не трогать код разработчиков.

Наш плагин выглядит следующим образом:

 

require_once 'class.smtp.php'; class SMTPX extends SMTP { public function __construct() { parent::__construct(); } public function Connect($host, $port = 0, $tval = 30, $local_ip) { // set the error val to null so there is no confusion $this->error = null; // make sure we are __not__ connected if($this->connected()) { // already connected, generate error $this->error = array("error" => "Already connected to a server"); return false; } if(empty($port)) { $port = $this->SMTP_PORT; } $opts = array( 'socket' => array( 'bindto' => "$local_ip:0", ), ); // create the context... $context = stream_context_create($opts); // connect to the smtp server $this->smtp_conn = @stream_socket_client($host.':'.$port, $errno, $errstr, $tval, // give up after ? secs STREAM_CLIENT_CONNECT, $context); // verify we connected properly if(empty($this->smtp_conn)) { $this->error = array("error" => "Failed to connect to server", "errno" => $errno, "errstr" => $errstr); if($this->do_debug >= 1) { echo "SMTP -> ERROR: " .

his->error["error"] . ": $errstr ($errno)" . $this->CRLF . '<br />'; } return false; } // SMTP server can take longer to respond, give longer timeout for first read // Windows does not have support for this timeout function if(substr(PHP_OS, 0, 3) != "WIN") socket_set_timeout($this->smtp_conn, $tval, 0); // get any announcement $announce = $this->get_lines(); if($this->do_debug >= 2) { echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '<br />'; } return true; } }

На самом деле реализация метода Connect() тоже изменилась минимально. Заменены лишь строки, создающие непосредственно сокет и в сигнатуру добавлен еще одни параметр — IP адрес сетевого интерфейса.

Чтобы использовать этот плагин, нужно расширить класс PHPMailer следующим образом:

require_once 'class.phpmailer.php';  class MultipleInterfaceMailer extends PHPMailer {  /**  * IP адрес сетевого интерфейса, с которого нужно  * подключаться к удаленному SMTP-серверу.  * Используется при работе через плагин SMTPX.  * @var string  */  public $Ip = '';   public function __construct($exceptions = false)  {  parent::__construct($exceptions);  }   /**  * Метод для работы с плагином SMTPX.  * @param string $ip IP адрес сетевого интерфейса с доступом в Интернет.  

/ public function IsSMTPX($ip = '') { if ('' !== $ip) $this->Ip = $ip; $this->Mailer = 'smtpx'; } protected function PostSend() { if ('smtpx' == $this->Mailer) { $this->SmtpSend($this->MIMEHeader, $this->MIMEBody); return; } parent::PostSend(); } /** * Внесены изменения, касающиеся отправки писем с явным указанием * IP адреса сетевого интерфейса компьютера. * @param string $header The message headers * @param string $body The message body * @uses SMTP * @access protected * @return bool */ protected function SmtpSend($header, $body) { require_once $this->PluginDir . 'class.smtpx.php'; $bad_rcpt = array(); if(!$this->SmtpConnect()) { throw new phpmailerException($this->Lang('connect_host'), self::STOP_CRITICAL); } $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; if(!$this->smtp->Mail($smtp_from)) { throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL); } // Attempt to send attach all recipients foreach($this->to as $to) { if (!$this->smtp->Recipient($to[0])) { $bad_rcpt[] = $to[0]; // implement call back function if it exists $isSent = 0; $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body); } else { // implement call back function if it exists $isSent = 1; $this->doCallback($isSent, $to[0], '', '', $this->Subject, $body); } } foreach($this->cc as $cc) { if.

$isSent = 0; $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body); } else { // implement call back function if it exists $isSent = 1; $this->doCallback($isSent, '', '', $bcc[0], $this->Subject, $body); } } if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses $badaddresses = implode(', ', $bad_rcpt); throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses); } if(!$this->smtp->Data($header . $body)) { throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL); } if($this->SMTPKeepAlive == true) { $this->smtp->Reset(); } return true; } /** * Внесены изменения, расширяющие класс PHPMailer для * работы с плагином SMTPX. * @uses SMTP * @access public * @return bool */ public function SmtpConnect() { if(is_null($this->smtp) || !($this->smtp instanceof SMTPX)) { $this->smtp = new SMTPX(); } $this->smtp->do_debug = $this->SM.

= $this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout, $this->Ip); if ($bRetVal) { $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname()); $this->smtp->Hello($hello); if ($tls) { if (!$this->smtp->StartTLS()) { throw new phpmailerException($this->Lang('tls')); } //We must resend HELO after tls negotiation $this->smtp->Hello($hello); } if ($this->SMTPAuth) { if (!$this->smtp->Authenticate($this->Username, $this->Password)) { throw new phpmailerException($this->Lang('authenticate')); } } $connection = true; break; } $index++; } if (!$connection) { throw new phpmailerException($this->Lang('connect_host')); } } catch (phpmailerException $e) { $this->SetError($e->getMessage()); if ($this->smtp->Connected()) $this->smtp->Reset(); if ($this->exceptions) { throw $e; } return false; } return true; } }

В класс MultipleInterfaceMailer добавлено новое открытое поле Ip, которое должно быть установлено строковым представлением IP адреса сетевого интерфейса, с которого мы хотим отправлять почту. Также добавлен метод IsSMTPX(), указывающий, что письма нужно отправлять с использованием нового плагина. Методы PostSend(), SmtpSend() и SmtpConnect() также переделаны для использования плагина SMTPX. При этом объекты класса MultipleInterfaceMailer можно спокойно использовать с существующим клиентским кодом, который, например, отправляет почту через sendmail или через оригинальный плагин SMTP, так как ни процедура использования, ни интерфейс класса не изменились.

Далее небольшой пример использования нового класса:

function getSmtpHostsByDomain($sRcptDomain) {  if (getmxrr($sRcptDomain, $aMxRecords, $aMxWeights)) {  if (count($aMxRecords) > 0) {  for ($i = 0; $i < count($aMxRecords); ++$i) {  $mxs[$aMxRecords[$i]] = $aMxWeights[$i];  }   asort($mxs);   $aSortedMxRecords = array_keys($mxs);  $sResult = '';  foreach ($aSortedMxRecords as $r) {  $sResult .= $r . ';';  }   return $sResult;  }  }   //Функция getmxrr возвращает только почтовые сервера, найденные в DNS,  //однако, согласно RFC 2821, когда в списке нет почтовых серверов,  //необходимо использовать только $sRcptDomain в качестве почтового сервера с  //приоритетом 0.  return $sRcptDomain; }   require 'MultipleInterfaceMailer.php';   $mailer = new MultipleInterfaceMailer(true); $mailer->IsSMTPX('192.168.1.1'); //Здесь необходимо указать IP адрес желаемого интерфейса //$mailer->IsSMTP(); а можно и по старинке $mailer->Host = getSmtpHostsByDomain('email.net'); $mailer->Body = 'blah-blah'; $mailer->From ='no-replay@yourdomain.net'; $mailer->AddAddress('sucreface@email.net');  $mailer->Send();

Заключение

Подведем краткий итог:

  1. Исправлен баг в PHPMailer, из-за которого SmtpConnect() всегда возвращал true, даже в случае неудачной попытки подключения к SMTP-серверу.
  2. SmtpConnect() стал по-честному проверять все переданные ему MX-записи до первой удачной попытки.
  3. Написан новый плагин, с помощью которого можно отправлять почту через SMTP явно указывая какой сетевой интерфейс отправляющего сервера использовать.
  4. PHPMailer безболезненно для старого клиентского кода расширен для использования нового плагина SMTPX.

Удачи в ваших начинаниях, друзья!

habr.com

Приветствую на страницах блога перфекциониста. Сегодня мы снова будем программировать, и да — снова на PHP (уж очень я его люблю;)).
Недавно мне потребовалось расширить функционал моего скрипта интернет-эквайринга, а именно — добавить возможность автоматической отправки почты с деталями платежа после завершения оплаты.
В PHP, начиная с версии 4, есть специальная функция mail() которая, в принципе, справляется с этой задачей, но ничего так просто в этом мире не бывает и эта функция не стала исключением. Проблема даже кроется не в самой функции, а в том, что большинство провайдеров и хостеров распознают, что письмо было отправлено с ее помощью, и, как правило, в лучшем случае письмо попадает в папку «СПАМ» или же вовсе не доходит до адресата, т.к. сервер почтовика его забраковал — это далеко не всегда так, да, бывают и исключения. К тому же, если вы используете локальный сервер — у вас есть полный доступ к его настройкам, а следовательно и настройкам функции mail(). Но все это частные случаи, их я разбирать не буду, т.к. я люблю чтоб все работало везде и всегда (хотя это, конечно, тоже не реально, но к этому нужно стремиться).

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

SMTP (англ.Simple Mail Transfer Protocol — простой протокол передачи почты) — это широко используемый сетевой протокол, предназначенный для передачи электронной почты в сетях TCP/IP.

© Wikipedia

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

Итак, начнем с того, что скачаем PHPMailer и поместим его в отдельную одноименную папку на нашем сервере. Далее создадим 2 файла — один файл будет содержать конфигурационные данные и функции, второй будет отправлять нашу почту (короче говоря — пример). Размяли пальцы — и погнали.

Открываем первый файл в редакторе — mail.class.php  и пишем примерно следующее:

 class mail{  private $smtp_data = array( 	"host"			=> 'smtp.mail.ru',	// SMTP сервер  	"debug"			=> 0,	// Уровень логирования (0 выкл, 1 - вывод ошибок, 2- полный лог)  	"debugoutput"		=> 'html',	//формат вывода лога, если включено логирование  	"auth"			=> true,	// Авторизация на сервере SMTP. Если ее нет - false  	"port"			=> 587,	// Порт SMTP сервера  	"username"		=> 'noreply@mail.ru',	// Логин на SMTP сервере  	"password"		=> '1234567890',	// Пароль на SMTP сервере  	"fromname"		=> 'Почтовый робот',	// Отображаемое имя отправителя  	"replyto"		=> array(  		"address"	=> 'my@site.ru',	// адрес почты для ответа  		"name"		=> 'My Name'	//отображаемое имя владельца ящика  		),  	"notification"	=> array(  		"address"	=> 'my@site.ru',	// Почта оповещения админа (не оповещать- оставить пустым)  		"name"		=> 'My Name'	//отображаемое имя владельца ящика  		),  	"secure"			=> 'tls',	// Тип шифрования. Например ssl или tls  	"charset"		=> 'UTF-8',	//кодировка отправляемых писем  	"verify"			=> '0'	// Верификация сертификата. 0 -выкл, 1 - вкл (выключить при возникновении ошибок связанных с SSL сертификатами при отправке)  ); 

Пока все думаю понятно. Все настройки с комментарием, так что сложностей возникнуть не должно. Двигаемся дальше. Так, как мы будем отправлять сообщение в автоматическом режиме, то содержимое пиcем будет примерно одинаковым, кроме данных платежа (в нашем случае). Значит нам нужен некий шаблон, который можно будет редактировать без затруднений и поисков по коду. Создадим еще один массив с данными шаблона:

 private $mail_content = array(  	'title'		=> 'Детали платежа с сайта fussraider.ru', 	'header'		=> 'Добрый день! Была произведена оплата на сайте fussraider.ru
Данные платежа:
', 'footer' => '

С Уважением,
Администрация a href="fussraider.ru">fussraider.ru
Это сообщение отправлено автоматически, на него не нужно отвечать.
' );

Тут мы будем задавать тему письма, его начало и конец. А все динамичные данные будут между шапкой и подвалом. Для упрощения добавим приватную функцию, которая будет приклеивать шапку и подвал сообщения и возвращать полный текст:

 private function fullText($text) {  if(!empty($text))  {  return $this->mail_content['header'] . $text . $this->mail_content['footer'];  }  else  {  die("Отсутствует текст письма");  } } 

Вот. Теперь переходим к основной части — функции отправки письма. Сам код функции выглядит вот так:

 public function send($message_data) {  require_once('./PHPMailer/PHPMailerAutoload.php'); // подключаем PHPMailer  $mail = new PHPMailer;  $mail->isSMTP();  if($this->smtp_data['verify'] == 0)  {  $mail->SMTPOptions = array(  'ssl' => array(  'verify_peer' => false,  'verify_peer_name' => false,  'allow_self_signed' => true  ));  }   $mail->Host = $this->smtp_data['host'];  $mail->SMTPDebug = $this->smtp_data['debug'];  $mail->Debugoutput = $this->smtp_data['debugoutput'];  $mail->SMTPAuth = $this->smtp_data['auth'];  $mail->Port = $this->smtp_data['port'];  $mail->Username = $this->smtp_data['username'];  $mail->Password = $this->smtp_data['password'];  $mail->SMTPSecure = $this->smtp_data['secure'];  $mail->CharSet = $this->smtp_data['charset'];  $mail->setFrom($this->smtp_data['username'], $this->smtp_data['fromname']);  $mail->addReplyTo($this->smtp_data['replyto']['address'], $this->smtp_data['replyto']['name']);  if(!empty($this->smtp_data['notification']['address']))  {  $mail->addAddress($this->smtp_data['notification']['address'], $this->smtp_data['notification']['name']);  }  $mail->addAddress($message_data['to'], $message_data['to_name']);  $mail->Subject = $this->mail_content['title'];  $mail->msgHTML($this->fullText($message_data['text']));  $mail->AltBody = strip_tags($this->fullText($message_data['text']));   if (!$mail->send())   {  die("Mailer Error: " . $mail->ErrorInfo);  }   else   {  return 0;  } } 

Тут вместо комментариев поясню отдельно. Функция принимает на вход некоторые данные $message_data — это массив данных, который имеет строгую структуру:

 $message_data = array(  'to' => 'to@mail.ru',   'to_name' => 'Василий Пупкин',   'text' => 'ТЕКСТ ПИСЬМА'  ); 

Здесь я думаю тоже все понятно. Функция построена таким образом, что к тексту из массива, принимаемого функцией, приклеивается начало и конец письма функцией fullText, которую я писал выше.

Вот в принципе и все содержимое нашего класса. Теперь давайте откроем второй файл — index.php и попробуем уже отправить письмо. Для примера отправим письмо на мой ящик (он не существует в реальности, так что спамеры — идите на… гуляйте)

 require_once('mail.class.php'); //подключаем наш класс $message_data = array( //задаем данные для отправки  'to' => 'admin@fussraider.ru',   'to_name' => 'Константин',   'text' => 'Ура! Оно работает!'  ); $mailer = new mail; //создаем экземпляр нашего класса  $sendmail = $mailer->send($message_data); //отправляем наше письмо  if($sendmail == 0) //проверяем, отправилось ли оно вообще {  echo "Письмо успешно отправлено"; } else {  echo "Письмо не отправлено" . $sendmail; } 

Теперь, если запустить выполнение скрипта — отправится письмо на ящик admin@fussraider.ru, но не дойдет, по указанным выше причинам. Для проверки можете указать свой ящик.

Добавлю еще, что этот скрипт умеет оповещать помимо адресата еще кого-то, например админа сайта. В конфигурации вы могли увидеть массив notification — если его заполнить, при отправке письма оно будет отправляться также и по адресу, который вы там укажете. Если эта функция вам не нужна — просто оставьте значение address пустым.

Ну вот как-то вот так. На сегодня все. Спасибо за внимание и до новых встреч!

UPD (08.07.2016):
добавил архив с исходниками и примером использования.

fussraider.ru

При работе моих скриптов происходят разные события о которых я бы хотел бы знать. Один из вариантов таких оповещений это отправка сообщения на электронную почту. В этой заметке я бы хотел бы рассказать как происходит средствами php отправка почты.

В моих скриптах средствами php отправка email происходит с помощью всем известного класса phpmailer и удалённого smtp сервера. Я использую smtp сервер google. Ну а теперь обо всём по порядку.

Smtp google

Ничего сложного в настройке и подключении smtp сервер google нет. Что бы получить к нему доступ достаточно создать ящик электронной почты в gmail. Логин и пароль доступа к ящику будет подходить и к серверу. Важно только знать основные google smtp настройки, которые мы будем использовать в phpmailer.

  • адрес smtp сервера — smtp.gmail.com
  • тип соединения — ssl
  • порт сервера — 465
  • логин — адрес ящика
  • пароль — ваш пароль от ящика электронной почты

Phpmailer

Phpmailer это всем известный php класс для отправки email. Скачать его можно c github здесь. Обычно я скачиваю файлы class.phpmailer.php, class.pop3.php, class.smtp.php и складываю их в корень сайта. Теперь поговорим о подключении и настройке Phpmailer. Создадим в корне сайта файл index.php, в нём мы создадим подключение и настройки.

   //подключаем phpmailer    require_once('class.phpmailer.php');  //получаем экземпляр   $mail = new PHPMailer();  //задаём как работать с SMTP сервером   $mail->IsSMTP();  //адрес smtp сервера   $mail->Host = "smtp.gmail.com";  //сообщения дебагера, 0-не показываем    $mail->SMTPDebug = 0;  //если сервер требует авторизации    $mail->SMTPAuth = true;  //тип шифрования   $mail->SMTPSecure = "ssl";  //порт сервера   $mail->Port = 465;  //приоритет почты, 3 - нормально    $mail->Priority = 3;  //кодировка   $mail->CharSet = 'UTF-8';   $mail->Encoding = '8bit';  //тема письма   $mail->Subject = "Тест php mailer";   $mail->ContentType = "text/html; charset=utf-8rn";  //адрес почтового ящика gmail   $mail->Username = "ваш_почтовый_ящик";  //ваш пароль от ящика   $mail->Password = *************;   $mail->isHTML(true);  //текст письма    $mail->Body = "привет от Phpmailer";   $mail->WordWrap = 50;  //адрес, на котоый нужно отправить письмо   $mail->AddAddress("адрес_получателя");   if(!$mail->send()) {   echo 'ошибка';   exit;   }   echo 'сообщение отправлено';  

Из листинга я думаю всё понятно. Если правильно прописать все настройки и запустить файл index.php, то мы отправим на указанный email сообщение «привет от Phpmailer». В принципе мне данного функционала хватает, для того что бы силами php отправить email , так что дальше копаться в классе не стал. Вот наверное и всё, по традиции написал небольшой пример, и разобрал его.

В примере имеем файл index.php. В нём есть поле с указанием email, куда надо отправить письмо и поле с текстом письма. Через ajax проискодит отправка данных из полей в файл send.php. В send.php подключается phpmailer и происходит средствами php отправка email. Так же к index.php подключается файл myjs.js. В нём происходит проверка правильности заполнения полей формы, а так же отправка данных ajax в send.php и получение ответа об отправке письма или ошибке. Пример я писал используя bootstrap для вёрстки. Классы бутстрап я убрал из листинга что бы было меньше кода. И так основной кусок index.php.

   <form>   <div>   <label for="email">Ваш email</label>   <div>   <input type="text" id="email" placeholder="Введите email на который отправляете письмо" name="email"/>   </div>   </div>   <div>   <div class="emailalert">   <!-- сюда выводим сообщение ошибки заполнения -->    </div>   </div>   <div class="form-group">   <label for="body">Ваше сообщение</label>   <div>   <textarea rows="5" id="body" placeholder="Введите текст вашего письма" name="body"></textarea>   </div>   </div>   <div>   <div class="bodyalert">   <!-- сюда выводим сообщение ошибки заполнения -->   </div>   </div>  </form>  <div>   <button class="submit">Отправить письмо</button>  </div>  <div class="load" style="display: none;">    <img class="img-responsive" src="/css/preload.gif">  </div>  <!-- Modal bootstrap-->  <div id="myModal">   <div class="modal-dialog">   <div class="modal-content">   <div class="modal-header" style="border: none;">   <button type="button">×</button>   </div>   <div class="modal-body">   <div id='result'>  <!-- сюда выводим сообщение об отправке письма -->    </div>   </div>   </div>   </div>  </div>  

Будем считать что myjs.js подключён к index.php. Листинг myjs.js

  $(document).ready(function(){  //обработка клика по кнопке отправить   $('.submit').click(function(){   //стираем старый алерт   $('.emailalert').html(' ');   //получаем значение поля ввода   var em=$("#email").val();   //alert(em);   //шаблон регулярного выражения    //для проверки правильности ввода email   var emRegExp=/^w+@[a-zA-Z_]+?.[a-zA-Z]{2,3}$/;   //проверка через ф-ю .test()    //соотнош рег выражения и данных в форме   if(!emRegExp.test(em)){   var eReg='<div>Неправильный email адрес</div>';   $('.emailalert').html(eReg);   }   //если поле пустое   if(em==''){   var e='<div>заполните поле с адресом электронной почты</div>';   //выводим предупреждение   $('.emailalert').html(e);   }   //стираем старый алерт   $('.bodyalert').html(' ');   var bd=$("#body").val();   //если поле пустое   if(bd==''){   var b='<div>Заполните поле с текстом письма</div>';   //выводим предупреждение   $('.bodyalert').html(b);   }  //если все поля заполнены правильно   //отсылаем данные ajax в send.php   if(emRegExp.test(em)&&!em==''&&!bd==''){   $.ajax({   //как будем передавать данные   type: "POST",   //куда передаём   url: "send.php",   //какие данные передаём   data: {email: em, body: bd},   //событие перед отправкой ajax   beforeSend: function(){   //стираем старый вывод   $('#result').html(' ');   //выводим гифку   $(".load").show();   },   //событие после получения ответа,    //получаем массив в data   success: function(data){   //скрываем гифку   $(".load").hide();   $('#result').html(data);   //выводим модальное окно   //эта ф-я из бутстрап   $('#myModal').modal();   }   });   }   })  })   

И наконец send.php

   //подключаем phpmailer  require_once('class.phpmailer.php');  /*ф-я фильтрации*/  function myclear($dt){   $dt=stripslashes($dt);   $dt=strip_tags($dt);   $dt=trim($dt);   return $dt;  }  if($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') {   $email = myclear($_POST['email']);//фильтруем   $body = myclear($_POST['body']);   $mail = new PHPMailer();   $mail->IsSMTP();   $mail->Host = "smtp.gmail.com";    $mail->SMTPDebug = 0;    $mail->SMTPAuth = true;   $mail->SMTPSecure = "ssl";   $mail->Port = 465;   $mail->Priority = 3;   $mail->CharSet = 'UTF-8';   $mail->Encoding = '8bit';   $mail->Subject = "Тест php mailer";   $mail->ContentType = "text/html; charset=utf-8rn";   $mail->Username = "мой почтовый ящик";   $mail->Password = "мой пароль";   $mail->isHTML(true);    $mail->Body = $body;   $mail->WordWrap = 50;   $mail->AddAddress($email);   if(!$mail->send()) {   echo 'Ваше сообщение не отправлено';   exit;   }   echo 'Ваше сообщение отправлено';  }  

Вот такой вот не хитрый пример как делается отправка сообщения на почту php.

aweb34.ru

 function sendemail_to_all($fromemail, $fromname, $subject, $message, $data) {

date_default_timezone_set("Europe/Moscow"); // временная зона

require "PHPMailerAutoload.php"; // подключили скрипт

$mail = new PHPMailer(); // инициализация класса

file_exists("/language/phpmailer.lang-ru.php") ? $mail->SetLanguage("ru", "/language/") : $mail->SetLanguage("en", "/language/"); // языковой пакет

$mail->isSMTP(); // указали, что работаем по протоколу смтп

$mail->Host = "smtp.yordomain.ru"; // хост

$mail->Port = "25"; // порт

$mail->SMTPAuth = true; // аутентификация включена

$mail->Username = "name@yourdomain.ru"; // реальный ящик, желательно совпадающий с вашим доменным именем

$mail->Password = "123456789"; // пароль от ящика

$mail->CharSet = "UTF-8"; // кодировка

$mail->setFrom($fromemail, $fromname); // от кого

$mail->addReplyTo($fromemail, $fromname); // кому ответить

$mail->Subject = $subject; // тема письма (заголовок)

$plain = $mail->html2text($message); // тело альтернативного письма

$mail->isHTML(true);

$img_path = "/images/mylogo.png"; // адрес логотипа

$img_cid = md5($img_path); // сид логотипа

$img_name = "mylogo"; // имя логотипа

$mail->addEmbeddedImage($img_path, $img_cid, $img_name); // добавили в тело письма логотип

$body = "<!DOCTYPE html>"; // создаем тело письма

$body .= "<html><head>"; // структуру я минимизирую, шаблонов в сети много, либо создайте свой

$body .= "<meta charset='UTF-8' />";

$body .= "<title>".$subject."</title>";

$body .= "</head><body>";

$body .= "<table><tr><td>";

$body .= "<table style='width:600px'><tr><td>";

$body .= "<a href='http://www.meweb.ru/' title='MeWEB' target='_blank'><img src='cid:".$img_cid."' alt='MeWEB' /></a></td>"; // указали место, где будет отображен логотип

$body .= "<td>";

$body .= "<a href='http://www.meweb.ru/' title='MeWEB' target='_blank'>MeWEB</a><br /><br /><a href='mailto:".$fromemail."'>".$fromemail."</a></td></tr>";

$body .= "<tr><td colspan='2'>&nbsp;</td></tr>";

$body .= "<tr><td colspan='2'><h3 syle='text-align:center'>Здравствуйте, {USER_NAME} !</h3>".nl2br($message)."<br /><br />Чтобы отписаться от рассылки, перейдите по ссылке <a href='http://www.meweb.ru/mailer/unsubscribe.php?delete={USER_ID}' target='_blank'>Отписаться</a></td></tr>"; // вывели в тело имя пользователя и само сообщение с ссылкой для отписки

$body .= "<tr><td colspan='2'><em>All rights reserved | Copyright &copy; <a href='http://www.meweb.ru/' title='MeWEB' target='_blank'>MeWEB</a> ".date("Y")."</em></td></tr>";

$body .= "</table></td></tr></table>";

$body .= "</body></html>";

$mail->msgHTML($body); // формируем тело

$mail->AltBody = $plain; // альтернативное тело письма

$i = 0;

foreach ($data as $row) { // проход по массиву из бд

unset($user); // вначале каждый раз очищаем переменную

$user = $row['user_id']; // уникальный id пользователя

$mail->addCustomHeader("Precedence", "bulk"); // добавили заголовок, чтобы дать понять почтовым сервисам, что это рассылка

$mail->AddCustomHeader("List-Unsubscribe", "<http://www.meweb.ru/mailer/unsubscribe.php?delete=".$user.">"); // добавили заголовок с ссылкой для отписки от рассылки

$mail->addAddress($row['user_email'], $row['user_name']); // добавили адрес и имя получателя

$mail->Body = str_replace(array("{USER_NAME}", "{USER_ID}"), array($row['user_name'], $user), $body); // вставляем в сообщение имя пользователя и уникальный id для ссылки

$mail->AltBody = str_replace(array("{USER_NAME}", "{USER_ID}"), array($row['user_name'], $user), $plain); // аналогично для альтернативного сообщения

if (!$mail->send()) { // если письмо не отправлено

$return[] = "ierror | ".$row['user_name']." | ".str_replace("@", "&#64", $row['user_email'])." ".$mail->ErrorInfo." | ".date("d-m-Y в H:i:s"); // возвращаем массив с ошибкой

break; // останавливаем перебор массива

} else { // если отправка прошла удачно

$return[] = "isuccess | ".$row['user_name']." | ".str_replace("@", "&#64", $row['user_email'])." | ".date("d-m-Y в H:i:s"); // возвращаем массив с отчетом

($i % 2 == 0) ? sleep(0.2) : sleep(0.4); // делаем паузу при рассылке между сообщениями

}

$mail->clearAddresses(); // в цикле чистим адрес, чтобы при новом проходе добавить другой

$mail->clearCustomHeaders(); // чистим в цикле заголовки, чтобы при новом проходе добавить новые

$i++;

}

$mail->clearAttachments();

$mail->clearReplyTos(); // очищаем

return $return; // функция возвращает нам результат в массиве

}


www.meweb.ru

Библиотека PHPMailer. Отправка почты через SMTP

От автора: отправка почты с сайта на email – это довольно обыденная и несложная задача. Для этого в PHP предусмотрена функция mail(), которой достаточно передать несколько параметров, и ваше письмо уйдет на указанную электронную почту. Но вот дойдет ли?

Именно на этот вопрос мы и попробуем найти ответ в этом уроке.

Причина, по которой отправленное письмо может быть не получено адресатом – это антиспамовые фильтры. Почтовые сервисы, как могут, пытаются бороться с получением спама. Также антиспамовые фильтры не очень «любят» письма, отправленные функцией mail(). В результате этого письмо попадет в папку Спам, в лучшем случае, или же попросту будет удалено антиспамовым фильтром.

Как же здесь быть? Выход прост: можно отправлять почту через SMTP популярных почтовых сервисов. Например, через gmail.com. Для этого всего-то нужно иметь почтовый ящик того почтового сервиса, протокол которого будем использовать. В уроке я буду использовать сервис mail.ru, поскольку там гораздо проще завести тестовый почтовый ящик. Однако, если вы захотите использовать сервис gmail.com, то порядок действий будет одним и тем же.

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

В видео версии урока вы найдете подробное комментирование процесса отправки почты. Для примера мы отправим 2 типа писем на различные почтовые сервисы: это будет письмо формата HTML и письмо с вложением. Как вы увидите, процесс использования библиотеки PHPMailer предельно прост.

На этом я с вами прощаюсь. Удачи и до новых встреч!

Phpmailer настройка

webformyself.com

Отправка почты средствами PHP может быть очень простой, а может быть очень сложной, это зависит от того, что и как отправлять
Простое электронное письмо – это обычный текст, и не составляет большого труда для отправки, но когда требуется отправить HTML письмо или письмо с вложенным файлом требуется указать MIME заголовки, писать содержимое файла в письмо и еще целая куча не очень приятных действий и может стать сложной задачей для разработчика.

Но используя класс PHPMailer, отправка писем становится довольно простой задачей. Этот класс берет на себя всю рутинную работу по отправки письма и представляет очень удобный интерфейс для работы с ним, к тому же и бесплатен.

Скачать PHPMailer для PHP4:
phpmailer_v2.0.4_php4

Скачать PHPMailer для PHP5/6:
phpmailer_v5.1_php5_php6

PHPMailer позволяет:

* Посылать письма с множественными: адресатами (TO), копиями (CC), скрытыми копиями (BCC) и устанавливать атрибут REPLY-TO;
* Совмещение нескольких сообщений и вложений файлов;
* Отправка сообщений в виде HTML;
* Многослойные/альтернативные сообщения для клиентов, которые не могут читать HTML письма;
* Перенос строк по словам (word wrap);
* Отправка сообщений через sendmail, PHP mail() или непосредственно по протоколу SMTP
* Библиотека проверена на множестве SMTP серверах: Sendmail, qmail, Postfix, Imail, Exchange, Mercury, Courier;
* Поддержка 8 бит, base64, бинарного режима, и пригодного для печати формата;
* Работает на любой win32 и *nix платформе;

Методы:
void AddAddress (string $address, [string $name = »]) — Добавление адресов получателей письма
bool AddAttachment (string $path, [string $name = »], [string $encoding = ‘base64’], [string $type = ‘application/octet-stream’]) — Прикрепляет файл к письму
void AddBCC (string $address, [string $name = »]) — Добавляет адрес кому отправится скрытая копия
void AddCC (string $address, [string $name = »]) — добавляет адрес кому отправится копия письма
void AddCustomHeader (mixed $custom_header) — Добавление пользовательский заголовок к письму
bool AddEmbeddedImage (string $path, string $cid, [string $name = »], [string $encoding = ‘base64’], [string $type = ‘application/octet-stream’]) — Прикрепляет к письму картинку
void AddReplyTo (string $address, [string $name = »]) — Адрес для ответа на ваше письмо. По умолчанию, адрес для ответа совпадает с адресом, с которого вы отослали письмо (FROM)
void AddStringAttachment (string $string, string $filename, [string $encoding = ‘base64’], [string $type = ‘application/octet-stream’]) — Прикрепляет файл содержимое которого находится в строке
void ClearAddresses () — Удаляет всех занесенных получателей письма
void ClearAllRecipients () — Удаляет всех получателей в том числе и кому копии должны прийти и скрытых получателей
void ClearAttachments () — Удаляет все прикрепленные файлы из письма
void ClearBCCs () — Очищает список скрытых получателей письма
void ClearCCs () — Очищает получателей копий письма
void ClearCustomHeaders () — Удаляет установленные пользовательские заголовки
void ClearReplyTos () — Удаляет адреса для ответов на письмо
void getFile (string $filename)void HeaderLine (mixed $name, mixed $value)bool IsError () — Возвращает true, если произошла ошибка
void IsHTML (bool $bool) —  Устанавливает что письмо в HTML формате
void IsMail () — Устанавливает флаг что письмо будет отправлено через PHP mail() функцию
void IsQmail () — Устанавливает флаг что письмо будет отправлено через Qmail MTA.
void IsSendmail () — Устанавливает флаг что письмо будет отправлено через программу Sendmail.
void IsSMTP () — Устанавливает флаг что письмо будет отправлено через SMTP протокол.
bool Send () — Создает сообщение и отправляет его если сообщение не было отправлено, то возвращает false и в переменной ErrorInfo описание ошибки
bool SetLanguage (string $lang_type, [string $lang_path = ‘language/’]) — Устанавливает язык сообщений об ошибках возвращает false если не может загрузить языковой файл
void SmtpClose () — Закрывает SMTP сессию, если таковая существует

Свойства:
string $AltBody — Устанавливает тело сообщения для тех клиентов которые не поддерживают HTML
mixed $attachment — Массив Прикрепленных файлов
mixed $bcc — Массив адресов кому отправится скрытая копия письма
string $Body — Устанавливает тело сообщения может быть в HTML или текстовом виде
mixed $boundarymixed $cc — Массив адресов кому отправится копия письма
string $CharSet — Устанавливает кодировку письма
string $ConfirmReadingTo — Устанавливает адрес кому будет отправлено подтверждение о прочтении
string $ContentType — Устанавливает Content-type письма.
mixed $CustomHeader — Массив пользовательских заголовков
string $Encoding — Устанавливает как кодировку письма. Возможные варианты «8bit», «7bit», «binary», «base64», and «quoted-printable».
string $ErrorInfo — Содержит последнее сообщение об ошибке
mixed $error_countstring $From — Устанавливает адрес отправителя
string $FromName — Устанавливает имя отправителя
string $Helostring $Host — Список SMTP хостов все хосты должны быть разделены точкой с запятой, также можно указать порт например (smtp1.example.com: 25; smtp2.example.com)
string $Mailer — Метод отправки письма: («mail», «sendmail», or «smtp»)
string $MessageID — Устанавливает идентификатор сообщения, которые будут использоваться в заголовке Message-Id
string $Password — SMTP пароль
string $PluginDir — Путь к PHPMailer плагинам. Сейчас используется если SMTP класс не в каталоге include_path.
int $Port — Устанавливает порт для SMTP сервера
int $Priority — Приоритет письма (1 = Высокий, 3 = Нормальный, 5 = Низкий).
mixed $ReplyTo — Массив адресов для ответа на письмо
string $Sender
string $Sendmail — Установка пути к Sendmail
mixed $sign_cert_file
mixed $sign_key_file
mixed $sign_key_pass
bool $SingleTo
mixed $smtp
bool $SMTPAuth — Вкличает или отключает SMTP авторизацию использует Username и Password
bool $SMTPDebug — Вкличает или отключает отладку SMTP
bool $SMTPKeepAlive — Если установлено в true то необходимо явно закрыть SMTP соединение SmtpClose ()
string $SMTPSecure — Устанавливает префикс соединения «», «ssl» или «tls»
string $Subject — Устанавливает тему письма
int $Timeout — Устанавливает timeout для SMTP соединения. Не работает в win32
mixed $to — Массив адресов кому отправится письмо
string $Username — Устанавливает SMTP пользователя
string $Version — Версия PHPMailer-a
int $WordWrap — Устанавливает количество символов в строке и если необходимо переносит на новую строку

Пример:

www.webmancer.org

Введение

Рассылка сообщений посредствам PHP может быть очень простой, а может быть очень сложной, все зависит от того, что и как вы собираетесь посылать.

Стандартное электронное письмо – это обычный текст, что и используется большинством разработчиков, поэтому создание MIME заголовков для HTML писем может стать сложным процессом. Теперь трудности вам не грозят, потомучто у вас есть чудесная библиотека PHPMailer, которая, к тому же, бесплатна.

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

Требования

Требования у данной библиотеки очень скромны. Вам нужен только PHP и возможность отсылать письма посредствам команды mail() или через SMTP соединение.

Также вы должны понимать основы объектно-ориентированного программирования (ООП), или, по крайней мере, понимать как правильно применять данные ниже примеры.

Не переживайте! Этот курс достаточно прост!

О PHPMailer

Это класс, обеспечивающий полную функциональность при отправке почтовых сообщений на PHP. Я назвал бы его самым лучшим из всех, которые я когда-либо использовал. Его популярность очень быстро росла. С момента появления, 7 декабря 2004 года, его скачали уже более 100 000 раз! Я надеюсь, что вы захотите увеличить это число после прочтения данного обучающего курса, и, что еще более важно, вы узнаете, как использовать те возможности по работе с почтой, о которых вы только мечтали.

Что может PHPMailer

На момент написания этого обучающего курса PHP Mailer умел:

  • посылать письма с множественными: адресатами (TO), копиями (CC), BCC и REPLY-TO;
  • избыточные SMTP серверы;
  • многослойные/альтернативные сообщения для клиентов, которые не могут читать HTML письма;
  • поддержка 8 бит, base64, бинарного режима, и пригодного для печати формата;
  • Использовать все теже самые методы, что и популярный AspEmail активный сервер (COM);
  • авторизация SMTP;
  • перенос слов (word wrap);
  • сообщения в виде HTML;
  • библиотека проверена на множестве SMTP серверах: Sendmail, qmail, Postfix, Imail, Exchange, Mercury, Courier;
  • работает на любой win32 и *nix платформе;
  • гибкость отладки;
  • определяемые вручную заголовки писем;
  • совмещение нескольких сообщений и вложений;
  • встроенная поддержка изображений.

Разработчики PHPMailer

  • Brent R. Matzelle
  • Patrice Fournier
  • Chris Ryan
  • Cem Hurturk
  • Tom Klingenberg
  • Jaime Bozza

Я выражаю этим людям свою признательность, потомучто они столько сделали, чтобы ускорить развитие моих проектов, включая PHPFreaks.com!

Готовим PHPMailer для использования

Скачать и распаковать

Первое, что вы должны сделать, это, конечно же, скачать PHPMailer! Вы можете найти его здесь: https://github.com/PHPMailer/PHPMailer/. После того, как вы скачаете файл, распакуйте его в каталог. В нашем учебнике мы предположим, что ваш сайт находится здесь: /home/mywebsite/public_html/. Теперь необходимо создать несколько директорий, чтобы упорядочить структуру проекта. Я обычно помещаю библиотеки в каталог 'lib', а затем их название. Таким образом, извлекаем PHPMailer сюда: /home/mywebsite/public_html/lib/phpmailer. Вот пример из командной строки:

 /home/mywebsite/public_html/lib /home/mywebsite/public_html/lib/phpmailer /home/mywebsite/public_html/lib/phpmailer/docs /home/mywebsite/public_html/lib/phpmailer/docs/extending.html /home/mywebsite/public_html/lib/phpmailer/docs/faq.html /home/mywebsite/public_html/lib/phpmailer/docs/timeoutfix.diff /home/mywebsite/public_html/lib/phpmailer/language /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-br.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-cz.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-de.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-en.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-es.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-fr.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-it.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-nl.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-no.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-se.php /home/mywebsite/public_html/lib/phpmailer/language/phpmailer.lang-tr.php /home/mywebsite/public_html/lib/phpmailer/phpdoc /home/mywebsite/public_html/lib/phpmailer/phpdoc/allclasses-frame.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/deprecated-list.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/help-doc.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/index-all.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/index.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/overview-tree.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/packages.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/phpmailer.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/serialized-form.html /home/mywebsite/public_html/lib/phpmailer/phpdoc/stylesheet.css /home/mywebsite/public_html/lib/phpmailer/test /home/mywebsite/public_html/lib/phpmailer/test/phpmailer_test.php /home/mywebsite/public_html/lib/phpmailer/test/phpunit.php /home/mywebsite/public_html/lib/phpmailer/test/rocks.png /home/mywebsite/public_html/lib/phpmailer/ChangeLog.txt /home/mywebsite/public_html/lib/phpmailer/class.phpmailer.php /home/mywebsite/public_html/lib/phpmailer/class.smtp.php /home/mywebsite/public_html/lib/phpmailer/LICENSE /home/mywebsite/public_html/lib/phpmailer/README

Теперь, когда все файлы на своих местах, давайте создадим файл конфигурации нашего проекта.

Создание и использование файла конфигурации

Одна из главных вещей, которую я люблю делать перед созданием сайта – это написание файла конфигурации, он будет содержать настройки к которым я, возможно, буду обращаться много раз. И так, я создаю файл с название config.php в /home/mywebsite/public_html/config.php. Создаем внем массив с названием $site с моими ключами и значениями, которые я буду использовать в дальнейшем. В этом руководстве я опишу переменные, которые мы будем использовать в классе PHPMailer. Вот пример моего файла config.php:

 // Настройки для MY site  // Настройки Email $site['from_name'] = 'мое имя'; // from (от) имя $site['from_email'] = 'email@mywebsite.com'; // from (от) email адрес // На всякий случай указываем настройки // для дополнительного (внешнего) SMTP сервера. $site['smtp_mode'] = 'disabled'; // enabled or disabled (включен или выключен) $site['smtp_host'] = null; $site['smtp_port'] = null; $site['smtp_username'] = null;

Этот пример очень прост, чтобы объяснять его. Далее мы продолжим свою работу и будем брать эти настройки по мере надобности.

Создаем класс, расширяющий PHPMailer

Сразу подчеркну, что вы должны создать класс расширения, это позволит упростить вам жизнь, далее я покажу как.

Класс расширения вызовет класс PHPMailer() и установит начальные значения, такие, как Email адрес от имени которого вы будете посылать письма, настройки почтового сервера, и так далее.

Каждый из этих параметров берется по умолчанию из файла config.php, но вы также можете переписать их при вызове нашего класса расширения. Таким образом, если вы не переопределите какой-либо из параметров в классе расширения, то он будет взят поумолчанию из файла config.php, и вам не надо каждый раз переопределять эти параметры. В этом и красота данного подхода!

Взгляните на наш класс расширения:

 require_once($_SERVER['DOCUMENT_ROOT'].'/lib/phpmailer/class.phpmailer.php');  class FreakMailer extends PHPMailer {  var $priority = 3;  var $to_name;  var $to_email;  var $From = null;  var $FromName = null;  var $Sender = null;    function FreakMailer()  {  global $site;    // Берем из файла config.php массив $site    if($site['smtp_mode'] == 'enabled')  {  $this->Host = $site['smtp_host'];  $this->Port = $site['smtp_port'];  if($site['smtp_username'] != '')  {  $this->SMTPAuth = true;  $this->Username = $site['smtp_username'];  $this->Password = $site['smtp_password'];  }  $this->Mailer = "smtp";  }  if(!$this->From)  {  $this->From = $site['from_email'];  }  if(!$this->FromName)  {  $this-> FromName = $site['from_name'];  }  if(!$this->Sender)  {  $this->Sender = $site['from_email'];  }  $this->Priority = $this->priority;  } }

Далее мы рассмотрим этот код.

Разберем класс FreakMailer

Наш класс, показанный выше, очень прост. И вам необходимо обладать только базовыми навыками ООП, чтобы использовать его. Давайте разберемся.

Сначала нам необходимо подключить класс PHPMailer (файл class.phpmailer.php в директории lib). Это позволяет нам расширить класс PHPMailer, потому что делает объект доступным. Вы могли бы подключить его и в другом месте, но здесь это наиболее эффективно.

 require_once($_SERVER['DOCUMENT_ROOT'].'/lib/phpmailer/class.phpmailer.php');

Структура управления классом

Далее, мы определяем структуру управления классом и даем ему имя при расширении класса PHPMailer.

 class FreakMailer extends PHPMailer { 

Переменные класса

Идем дальше. Теперь мы определяем внутренние переменные. Большинство из них установлены поумолчанию в NULL, чтобы позже мы могли их переопределить, если есть необходимость заменить значения, установленные в config.php.

 var $priority = 3; var $to_name; var $to_email; var $From = null; var $FromName = null; var $Sender = null;

Давайте рассмотрим эти переменные:

  • $priority – это устанавливает приоритет почты поумолчанию: 1 – высоко, 3 – нормально, 5 – низко.
  • $to_name – Имя человека, которому вы посылаете сообщение.
  • $to_email – адрес этого человека.
  • $From – адрес, с которого вы хотите послать письмо.
  • $FromName – имя отправителя.

После определения переменных, мы с вами можем обсудить функцию FreakMailer().

Функция FreakMailer()

Эта функция, в основном, настраивает начальные значения для класса PHPMailer, чтобы посылать почту.

Сначала мы вызываем массив $site из файла config.php, чтобы иметь возможность использовать его в пределах данной функции и класса. Чтобы сделать это есть два способа: передать массив при вызове класса или сделать массив глобальным. Последний способ самый легкий и он работает, поэтому его и используем!

  function FreakMailer()  {  global $site; // Берем из файла config.php массив $site

Все дальнейшие действия – это, в основном, определение значений переменным класса PHPMailer. Если внутренняя переменная ($this->setting) не определена, мы берем значения из файла config.php. Я уже упоминал о том, что вы можете переопределить значения из config.php, здесь мы проверяем это.

 if($site['smtp_mode'] == 'enabled')  {  $this->Host = $site['smtp_host'];  $this->Port = $site['smtp_port'];  if($site['smtp_username'])  {  $this->SMTPAuth = true;  $this->Username = $site['smtp_username'];  $this->Password = $site['smtp_password'];  }  $this->Mailer = "smtp";  }    if(!$this->From)  {  $this->From = $site['from_email'];  }  if(!$this->FromName)  {  $this->FromName = $site['from_name'];  }  if(!$this->Sender)  {  $this->Sender = $site['from_email'];  }  $this->Priority = $this->priority;  } 

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

Теперь, когда мы достаточно имеем представление о классе расширения, давайте попробуем отправить почту!

Отправка электронной почты средствами PHPMailer

Предварительная работа сделана и теперь у нас есть все, чтобы посылать письма средствами PHPMailer.

Первоначальное испытание

Это испытание очень важно, потому что в рамках данной статьи мы будем постоянно возвращаться к приведенному здесь коду. Если данный код у вас не заработает, перечитайте этот материал сначала и снова попробуйте. Наш первый пример мы сохраним в файле mailtest.php, который положим в корень нашего проекта. Вот его содержимое:

 // Читаем настройки config require_once($_SERVER['DOCUMENT_ROOT'].'/config.php');  // Подключаем класс FreakMailer require_once($_SERVER['DOCUMENT_ROOT'].'/lib/MailClass.inc');  // инициализируем класс $mailer = new FreakMailer();  // Устанавливаем тему письма $mailer->Subject = 'Это тест';  // Задаем тело письма $mailer->Body = 'Это тест моей почтовой системы!';  // Добавляем адрес в список получателей $mailer->AddAddress('foo@host.com', 'Eric Rosebrock');  if(!$mailer->Send()) {  echo 'Не могу отослать письмо!'; } else {  echo 'Письмо отослано!'; } $mailer->ClearAddresses(); $mailer->ClearAttachments();

Давайте разберем этот код для лучшего его понимания.

Сначала мы подключаем наш конфигурационный файл, чтобы иметь доступ к массиву $site.

Далее, подключаем класс FreakMailer.

Теперь необходимо инициализировать наш класс расширения, а также класс PHPMailer.

 // Читаем настройки config require_once($_SERVER['DOCUMENT_ROOT'].'/config.php');  // Подключаем класс FreakMailer require_once($_SERVER['DOCUMENT_ROOT'].'/lib/MailClass.inc');  // инициализируем класс $mailer = new FreakMailer();

Теперь PHPMailer готов и мы идем дальше.

Задаем тему письма и его содержание.

 // Устанавливаем тему письма $mailer->Subject = 'Это тест';  // Задаем тело письма $mailer->Body = 'Это тест моей почтовой системы!';

Если вы используете в качестве письма обычный текст, то необходимо разделять строки или . И вы должны использовать двойные кавычки при определении переменной $mailer->Body. Если вы используете одинарные кавычки, то перенос текста с одной строки на другую возможен с помощью клавиши .

Теперь необходимо добавить адрес получателя.

 // Добавляем адрес в список получателей $mailer->AddAddress('foo@host.com', 'Eric Rosebrock');

Далее, посылаем сообщение и обрабатываем ошибки, если возникли.

В случае ошибки – вы увидите сообщение "Не могу отослать письмо!", в противном случае — "Письмо отослано!".

 if(!$mailer->Send()) {  echo 'Не могу отослать письмо!'; } else {  echo 'Письмо отослано!'; }

Далее, мы очищаем список адресатов и список вложений.

 $mailer->ClearAddresses(); $mailer->ClearAttachments();

Если вам только что пришло сообщение, которое вы отослали с помощью PHPMailer, – поздравляю!

Основные проблемы

Вот список некоторых (типичных) проблем, которые могут возникнуть у вас при отправлении почты при помощи PHPMailer (вероятнее всего, эти проблемы у вас возникли бы и при обычном отправлении писем):

  • на вашей машине не установлено или не запущено ни одного SMTP сервера;
  • неправильные настройки внутри PHP скрипта, перечитайте обучающий курс еще раз;
  • Сервер Apache не разрешает релей через SMTP сервер на локальной машине (типичный случай);
  • вы не правильно определили получателя письма.

Но, если у вас все заработало, давайте перейдем к отправке писем с определенными особенностями.

Использование дополнительных возможностей PHPMailer

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

PHPMailer имеет множество особенностей, например, добавление вложений, рассылка по списку адресатов и др. В этой части нашего материала мы с вами посмотрим, как это выглядит на практике.

Обработка адресов электронной почты

PHPMailer поддерживает много особенностей Адреса электронной почты, типа "Для" TO, "от" FROM и списков получателей, точная копия CC и Слепая точная копия BCC, Reply-TO и др. Давайте посмотрим, как использовать эти особенности.

Помните, что мы опираемся на основной пример, приведенный выше.

Добавление адреса отправителя (FROM)

В нашем основном примере адрес отправителя уже задан посредствам config.php и класса расширения, но вы в любой момент можете его переопределить. Например:

 $mailer->FromName = 'Ваше Имя'; $mailer->From = 'You@yourdomain.com';

Если не определить FromName, то большинство почтовых клиентов в качестве имени подставят емаил.

Добавление адреса для ответа (Reply-To)

Поумолчанию, адрес для ответа совпадает с адресом, с которого вы отослали письмо (FROM). Однако вы можете определить разные адреса для ответа на ваше письмо:

 $mailer->AddReplyTo('billing@yourdomain.com', 'Департаменту оплаты');

ЗАМЕЧАНИЕ:

Вы можете задать несколько адресов для ответа. Для этого необходимо продублировать приведенный выше код столько раз, сколько вы имеете адресов (не забудьте в примере менять адреса на нужные вам).

Добавление нескольких получателей

Этот метод позволяет вам добавить нескольких получателей для письма. Я не рекомендую этот способ для анонимных листов рассылки. Смотрите позже пример для списка рассылки.

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

 $mailer->AddAddress('recipient1@domain.com', 'Первый человек'); $mailer->AddAddress('recipient2@domain.com', 'Второй человек'); $mailer->AddAddress('recipient3@domain.com', 'Третий человек');

ЗАМЕЧАНИЕ:

Не рекомендуем пользоваться этим методом для рассылки по списку адресатов! Каждый получатель вашего письма будет видеть ВЕСЬ список получателей, а, затем, сможет использовать его по своему усмотрению. Позже мы расскажем как правильно отсылать письма по списку адресатов.

Добавить получателей точной копии (CC)

Вы можете добавить получателей точной копии точно также, как и предыдущих примерах, используя функцию AddCC.

 $mailer->AddCC('recipient1@domain.com', 'Первый человек');  // Если вам надо добавить более чем одного – просто повторяйте эту команду! $mailer->AddCC('recipient2@domain.com', 'Второй человек'); $mailer->AddCC('recipient3@domain.com', 'Третий человек'); 

Добавление получателей слепой точной копии (BCC)

Невидимых получателей или BCC можно добавить используя следущую функцию:

 $mailer->AddBCC('recipient1@domain.com', 'Первый человек');  // Если вам надо добавить более чем одного BCC, просто продолжайте! $mailer->AddBCC('recipient2@domain.com', 'Второй человек'); $mailer->AddBCC('recipient3@domain.com', 'Третий человек');

Требование подтверждения прочтения

Если вы хотите запросить у человека, читающего ваше письмо, подтверждение о прочтении, подайте следующую команду:

 $mailer->ConfirmReadingTo = 'you@youdomain.com';

Теперь, когда мы рассмотрели все адреса для отправки почты, давайте посмотрим, как посылать письма ввиде HTML!

Отправление писем ввиде HTML при помощи PHP и PHPMailer

Формирование HTML письма – это одна из самых сложных задач при отправке почты средствами PHP. Настройка MIME заголовков и построение HTML – нелегкая задача и требует дополнительных знаний и исследований. Однако, PHPMailer сделает вашу жизнь проще, далее, мы покажем как это реализуется.

Важное замечание относительно почты ввиде HTML

Прежде чем мы приступим к отправке таких писем, я хотел бы, чтобы вы поняли, что важно знать о том, каким образом должны подключаться изображения и стили CSS, и т.д. Простое правило состоит в том, чтобы хранить эти файлы на сервере, а в письме давать полные ссылки на них. Если вы сходите сума и добавляете все эти файлы к письму, то готовьтесь к головной боли. Например, тело моего письма выглядит примерно так:

www.sesmikcms.ru


You May Also Like

About the Author: admind

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Этот сайт использует Akismet для борьбы со спамом. Узнайте как обрабатываются ваши данные комментариев.