Отправка e-mail в русской кодировке средствами PHP

Стандартная функция отправки почты в PHP не заботится о кодировке письма, а специальные классы отправки писем могут показаться слишком тяжеловесным решением. В настоящей статье приведена простая функция, которая позволяет отправлять MIME-совместимые письма на русском языке.

Тело письма может быть текстом в любой кодировке. Немного сложнее дело обстоит с составляющими заголовка письма (Subject, From, To), они по стандарту должны быть в US-ASCII. Использование в заголовках кодированного текста регламентируется стандартом RFC-2047. Стандарт задает две возможные формы кодирования — BASE64 и Quoted-Printable. BASE64 более универсальна и работает в том числе для кодировки UTF-8, поэтому мы выбрали именно эту форму. MIME-совместимый почтовый клиент обязан уметь читать обе формы.

Далее код функции, который достаточно схематичен:

<?php

function send_mime_mail($name_from, // имя отправителя
                        $email_from, // email отправителя
                        $name_to, // имя получателя
                        $email_to, // email получателя
                        $data_charset, // кодировка переданных данных
                        $send_charset, // кодировка письма
                        $subject, // тема письма
                        $body // текст письма
                        ) {
  $to = mime_header_encode($name_to, $data_charset, $send_charset)
                 . ' <' . $email_to . '>';
  $subject = mime_header_encode($subject, $data_charset, $send_charset);
  $from =  mime_header_encode($name_from, $data_charset, $send_charset)
                     .' <' . $email_from . '>';
  if($data_charset != $send_charset) {
    $body = iconv($data_charset, $send_charset, $body);
  }
  $headers = "From: $fromrn";
  $headers .= "Content-type: text/plain; charset=$send_charsetrn";

  return mail($to, $subject, $body, $headers);
}

function mime_header_encode($str, $data_charset, $send_charset) {
  if($data_charset != $send_charset) {
    $str = iconv($data_charset, $send_charset, $str);
  }
  return '=?' . $send_charset . '?B?' . base64_encode($str) . '?=';
}

?>

Мы определили собственную функцию mime_header_encode() для преобразования каждого заголовка в MIME-совместимый формат, несмотря на то, что в PHP предусмотрена аналогичная функция mb_encode_mimeheader(). От встроенной функции нам пришлось отказаться, так как на нашем сервере (PHP 5.1.6) она работает некорректно (возвращает неверный результат).

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

<?php
send_mime_mail('Автор письма',
               'sender@site.ru',
               'Получатель письма',
               'recepient@site.ru',
               'CP1251',  // кодировка, в которой находятся передаваемые строки
               'KOI8-R', // кодировка, в которой будет отправлено письмо
               'Письмо-уведомление',
               "Здравствуйте, я Ваша программа!");
?>