Балада про php та електронну пошту.

Опубліковано: 2009-01-15   01:51:05

PHPДосить давно зіткнувся з проблемою відправки електронної пошти з php. З того часу знайшов декілька підходів до вирішення цієї проблеми та дізнався про різноманітні підводні камені, що можуть Вам, Шановний Читач, зустрітись в повсякденній роботі.

Розпочну я з того, яким чином просто можна відправляти повідомлення за допомогою php

Функція mail()

Найпростішим способом для надсилання пошти є використання стандартної для *nix систем утилітки sendmail вірніше різноманітних її замінників, що можуть бути присутні в системі. Проте, для написання програмного коду на php здавалось би не мало б бути жодної різниці. Що до проблем, які можуть виникати я ще повернусь. Одразу скажу, що з першого погляду їх не повинно бути та так воно й є в більшості випадків.

В php присутня функція mail(), що дозволяє відправляти листи на вказану адресу:

bool mail ( string to, string subject, string message [, string additional_headers [, string additional_parameters]])

Обов'язковими параметрами є:

  • email отримувача;
  • заголовок листа;
  • текст повідомлення.

А необов'язкові:

  • додаткові заголовки;
  • додаткові параметри командного рядка.

Якщо лист було поставлено в чергу для надсилання, то функція mail() повертає true. В противному разі false. Найбільш простий приклад її використання:

mail('test@grandse.org.ua', 'Subject', "Line 1\nLine 2\nLine 3");

А що ж тоді робити з додатковими параметрами? Ну про другий я нічого розповідати не буду, оскільки можливі значення та правила роботи будуть залежати суто від конкретної реалізації утиліти для надсилання пошти на сервері. До того ж я ще жодного разу не чув про випадок, коли використання цього параметра було б необхідним чи взагалі про те, щоб ним хтось скористався. Однак не завадить знати, що є й така можливість.

А ось на заголовках листа я зупинюсь детальніше.

Заголовки для повідомлення

Додаткові заголовки листа можуть бути використані для опису параметрів листа, вказуючи властивості інформації, що в ньому зберігається. Вони мають бути розділені переходом на новий рядок шляхом використання комбінації "\r\n". Наприклад так:

mail('test@grandse.org.ua', 'subject', 'Some text message',
'From: grandse@grandse.org.ua '."\r\n".'X-Mailer: PHP/'. phpversion());

Для отримувача лист матиме вигляд:

From: grandse@grandse.org.ua
To: test@grandse.org.ua
Subject: Hello from John!
Date: Wed, 14 Jan 2009 22:18:47 -0300
X-Mailer: PHP/5.2.4
Message-ID: <1234@local.machine.example>
Some text message

Фактично кожен лист, що відправляється повинен мати подібний вигляд. Як можна побачити функція mail() спрощує генерацію листа. Правила оформлення листів електронної пошти описані стандартом RFC-822. На деяких можливостях я зупинюсь детальніше.

From - адреса відправника листа у форматі:

"Ім'я та прізвище" <адреса-електронної-пошти>
У прикладах використовується спрощений формат, що містить лише адресу електронної пошти. Лапками навколо імені також можна знехтувати. To - електронна адреса отримувача у форматі аналогічному до попереднього заголовку. Якщо адресатів декілька, то можна їх перерахувати через кому. Ручного встановлення цей заголовок не потребує, потрібно лише вказати адресу отримувача під час виклику функції mail(). Subject - тема листа. Тут все має бути зрозумілим без зайвих пояснень. Як і адреса отримувача є аргументом функції mail(). Date - дата та час, коли повідомлення було надіслане. Генерується автоматично під час надсилання. Message-ID - унікальний ідентифікатор повідомлення. Використовується для доступу до листа. Генерується автоматично. MIME-Version - номер версії розширення стандарту RFC-822 для листів. Зазвичай 1.0. X-Mailer - поштовий клієнт. Може бути довільним. Content-Type - тип контенту та залежні від типу параметри (кодування, ім'я файлу, чи щось інше. Так Вам і імена файлів теж можуть вказуватись, бо функція mail() дозволяє надсилати файли). Приклади:
Content-Type: text/plain; charset="iso-8859-1" Content-Type: multipart/mixed; boundary="ZEND-12345" Content-Type: text/html; charset=windows-1251
Про надсилання листів, що містять в собі не лише текст можна написати окрему статтю, тому не буду на цьому зупинятись. Скажу лишень, що для відправки листів з форматуванням можна вільно використовувати html-розмітку, лишень треба вказати Content-Type: text/html; charset=... Здається нічого важливого не забув. Додам лишень, що більшість заголовків не є обов'язковими.

Проблема перша - кирилічні символи

Перша проблема з якою стикався мабуть кожен, хто працював напряму з функцією mail() - проблеми з кирилічними символами. Вірніше з кодуванням. Першим правилом, що дозволить уникнути проблем з кодуванням буде використання додаткового заголовка Content-Type. Нагадаю, що завдяки ньому ми можемо вказати тип листа та для тексту та html його кодування, що нам і потрібне. Правило елементарне: кодування тексту повідомлення має збігатись з кодуванням вказаним у листі. Як дізнатись кодування тексту, яке Ви додаєте у лист? Якщо текст береться з бази даних, або генерується самим php, то скоріш за все кодування буде тим самим, що базове для системи. Для кирилычноъ Windows це cp1251 (windows-1251), для більшості сучасних Linux - utf8. Якщо ж текст береться з даних переданим користувачем, то орієнтуватись тут слід на кодування встановлене в html через тег meta. Щоб виникало менше проблем я завжди використовує теж саме кодування в html, що і у всій системі. Останнім часом це завжди UTF-8. тому заголовок листа матиме вигляд: // To send HTML mail, the Content-type header must be set
$headers = 'MIME-Version: 1.0'."\r\n";
$headers .= 'Content-type: text/html; charset=utf8;'."\r\n";
$headers .= 'X-Mailer: PHP v.'.phpversion()."\r\n";
$headers .= 'From: '.$from."\r\n";
Однак, коли заголовок має теж бути кирилічним, то треба виконувати ще одну маніпуляцію для уникнення проблем, оскільки вказане в Content-Type кодування не розповсюджується на заголовок. Однак достатньо скористатись функцією base64_encode(): $subject = '=?utf8?B?'.base64_encode('Тема листа').'?=';
Звернніть увагу на '=?utf8?B?' - у Вас може вийти щось на зразок '=?kio8-r?B?', чи '=?windows-1251?B?' в залежності від кодування, в якому представлені дані.

Ще не кінець

Як Ви могли зрозуміти, це коротенький огляд простого способу надісилання листа з php. Далі буде складніше та для декого цікавіше. А розповім я детально про причини проблеми, яка в мене виникла з деякими поштовими сервісами та два шляхи її вирішення. Так що слідкуйте за оновленнями через RSS. Дякую всім за увагу! Вітаю зі Старим Новим Роком!

Теги: php , mail
Коментарі: 4
 

Коментарі:

virua2009-01-16 12:59:34 :

Шкода, що твого посту не було десь-так 2,5 роки тому, коли я його потребував ;) Тоді я знайшов відповіді на свої питання (кодування, HTML-вигляд листа), ось, тут - http://www.spravkaweb.ru/php/sovet/mail

 
GrAndSE2009-01-16 15:12:00 :

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

 
virua2009-01-16 16:04:18 :

Так і буде. Одній і ті ж запитання задають з дня в день. Це нормально. Головне - це написати матеріал (відповідь на питання) простішим і легшим для засвоєння.

Я свого часу чимало прочитав вступних статей до AJAX. Читав-читав, а воно якось так складно виглядало... А тоді натрапив на "нормальну" статтю і все одразу прояснилося.

 
TerranImrie2009-05-12 22:24:34 :

Якби воно працювало, то був би не РНР ^_^

 

Додати коментар

user

email

url

text

Повідомляти про новікоментарі