Отправка email при помощи PHP

Отправка email при помощи PHP

Сегодня мы поговорим о том, как отправлять email письма с помощью встроенных php функций. Казалось бы — что тут проще? Берёшь функцию mail(), задаёшь ей 3-5 параметров и всё. А вот и нет — тут не всё так просто и при детальном рассмотрении возникает просто огромнейшее количество подводных камней:

  • Кириллица в теме, в тексте письма, в имени отправителя
  • Отправка писем в другой кодировке
  • Использование вложений
  • HTML вёрстка, вставка изображений в тело письма

Не стоит унывать, если у вас что-то из этого не работает. Для начала, давайте, разберёмся с первыми двумя проблемами. Если написать, например, mail('test@example.com','Привет!','Привет! Как дела?'), то адресат, скорее всего, получит кракозябры.

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

Content-type: <тип письма>; charset=<кодировка>
тип письма: text/plain или text/html
с кодировкой, я думаю, понятно.

Но! Даже если вы указали кодировку письма в заголовках, то этот приём не работает для темы письма, имени отправителя или получателя, названий вложенных файлов.

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

=?<кодировка>?B?<текст в base64>?=

Поскольку кодировка php (обычно это utf-8) и кодировка писем (обычно это windows-1251) часто отличаются, то ещё и желательно их перекодировать. Вот функция, которая проводит все необходимые манипуляции:

  1. function mime_header_encode($str, $data_charset, $send_charset){
  2.   if($data_charset != $send_charset)
  3.     $str=iconv($data_charset,$send_charset.'//IGNORE',$str);
  4.   return ('=?'.$send_charset.'?B?'.base64_encode($str).'?=');
  5.   }

Я всегда был за расширяемость кода, поэтому отправку писем оформил в отдельный класс:

  1. class TEmail{
  2.   public $from_email;
  3.   public $from_name;
  4.   public $to_email;
  5.   public $to_name;
  6.   public $subject;
  7.   public $data_charset='UTF-8';
  8.   public $send_charset='windows-1251';
  9.   public $body='';
  10.   public $type='text/plain';
  11.   function send(){
  12.     $dc=$this->data_charset;
  13.     $sc=$this->send_charset;
  14.     //Кодируем поля адресата, темы и отправителя
  15.     $enc_to=mime_header_encode($this->to_name,$dc,$sc).' <'.$this->to_email.'>';
  16.     $enc_subject=mime_header_encode($this->subject,$dc,$sc);
  17.     $enc_from=mime_header_encode($this->from_name,$dc,$sc).' <'.$this->from_email.'>';
  18.     //Кодируем тело письма
  19.     $enc_body=$dc==$sc?$this->body:iconv($dc,$sc.'//IGNORE',$this->body);
  20.     //Оформляем заголовки письма
  21.     $headers='';
  22.     $headers.="Mime-Version: 1.0\r\n";
  23.     $headers.="Content-type: ".$this->type."; charset=".$sc."\r\n";
  24.     $headers.="From: ".$enc_from."\r\n";
  25.     //Отправляем
  26.     return mail($enc_to,$enc_subject,$enc_body,$headers);
  27.     }
  28.   }

Вот так мы будем отправлять письма:

  1. //Текстовое письмо
  2.   echo('Plain text email - sending...<br>');
  3.   $email=new TEmail;
  4.   $email->from_email='noreply@konservs.com';
  5.   $email->from_name='Автор ІЇҐЭЄ іїґэє';
  6.   $email->to_email='******@gmail.com';
  7.   $email->to_name='Для Васі';
  8.   $email->subject='Тема ІЇҐЭЄ іїґэє';
  9.   $email->body='Текстовий тестовий лист. Тест: ІЇҐЭЄ іїґэє';
  10.   if($email->send())
  11.     echo('Plain text email - OK.<br>'); else
  12.     echo('Plain text email - Error!<br>');
  13.   //HTML письмо
  14.   echo('HTML email - sending...<br>');
  15.   $email=new TEmail;
  16.   $email->from_email='noreply@konservs.com';
  17.   $email->from_name='Автор ІЇҐЭЄ іїґэє';
  18.   $email->to_email='******@gmail.com';
  19.   $email->to_name='Для Васі';
  20.   $email->subject='Тема ІЇҐЭЄ іїґэє';
  21.   $email->type='text/html';
  22.   $email->body='Тестовий лист в HTML.
  23.     <h1>Header 1 (Заголовок 1)</h1>
  24.     <h2>Header 2 (Заголовок 2)</h2>
  25.     <h3>Header 3 (Заголовок 3)</h3>
  26.     <h4>Header 4 (Заголовок 4)</h4>
  27.     <h5>Header 5 (Заголовок 5)</h5>
  28.     Тест: ІЇҐЭЄ іїґэє';
  29.   if($email->send())
  30.     echo('HTML email - OK.<br>'); else
  31.     echo('HTML email - Error!<br>');

Знаете, почему я кирилические письма отправляю в Windows-1251? Да потому что mail.ru не корректно принимает письма в utf-8, а в KOI-8 нет украинских букв(«і»,«ї»,«ґ»,«є»).

Проверяем отправку. Мне на почту пришло таких вот два письма:

Пришло письмо в текстовом формате Пришло письмо в HTML формате

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

Комментарии

22.11.2012 09:51:36
Avatar of ВасяВася
Спасибо за статью. Всё работает.
24.07.2013 12:02:43
Avatar of ДмитрийДмитрий
Напишите пожалуйста про то как правильно отправлять почту чтобы она в гмэйле не в спам падала)
25.07.2013 02:22:02
Avatar of КонсервКонсерв
Спам-фильтр Gmail (да и не только gmail) зависит от многих параметров.

В первую очередь - это контент. Если тема письма - "Увеличь *** за 3 дня!", то оно почти наверняка попадёт в спам. Текст тоже имеет значение. Исходя из моего опыта, массовые рассылки ни к чему хорошему не приводят. Лучше чтобы письма отправлялись не все сразу, а через определённый промежуток времени (например, 1 письмо в минуту) да и контент хоть немного отличался.

Далее - статистика рассылок с почтового сервера. Если с вашего сервера (имеет значение IP-адрес и доменное имя) регулярно отправляется спам, то он попадает в "чёрный список". На многих хостингах используется один или несколько почтовых серверов для всех сайтов, так что спам может отправлять ваш "сосед", а санкции понесут все. Обычно хостинги банят за спам. Можно сменить хостинг. Если вам надо 100% решение - закажите VDS или VPS и поднимите свой почтовый сервер.

Ещё один фактор (довольно важный) - действия пользователей. Если хотя бы несколько адресатов с похожими письмами (например, в случае рассылки) нажали кнопку "это спам", то остальные письма рассылки (с похожим текстом) тоже попадают в спам. Желательно чтобы письма рассылки были более-менее уникальными (например, если вам надо отправить список новых статей на сайте за неделю, то можно отправлять не весь список, а ссылки только на те статьи, которые по тематике подходят данному пользователю).

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

Если коротко, то рецепт один: если хотите, чтобы письма не попадали в папку "Спам", не пишите спам! :-)
26.08.2013 05:53:25
Avatar of mindnomindmindnomind
Спасибо, добрый человек!
16.12.2014 02:15:32
Avatar of ЕвгенийЕвгений
Спасибо огромное. Письма отправлял на два ящика, заказчику и себе. В ящик pop3 приходило в нормальном виде, в ящик для заказов, он подключен по imap, валились кракозябры. Все заработало как надо.
19.08.2015 05:38:07
Avatar of КонсервКонсерв
@Евгений
Пожалуйста :-)
Captcha Обновить
Go Top