Основы PHP
  Что такое PHP?
  Возможности PHP
  Преимущества PHP
  История развития
  Что нового в PHP5?
  «Движок» PHP
  Переход на PHP 5.3
New Переход на PHP 5.6
  Введение в PHP
  Изучение PHP
  Основы CGI
  Синтаксис PHP
  Типы данных PHP
  Переменные в PHP
  Константы PHP
  Выражения PHP
  Операторы PHP
  Конструкции PHP
  Ссылки в PHP
  PHP и ООП
  Безопасность
  Функции PHP
  Функции по категориям
  Функции по алфавиту
  Стандартные функции
  Пользовательские
  PHP и HTTP
  Работа с формами
  PHP и Upload
  PHP и Cookies
  PHP и базы данных
  PHP и MySQL
  Документация MySQL
  Учебники
  Учебники по PHP
  Учебники по MySQL
  Другие учебники
  Уроки PHP
  Введение
  Самые основы
  Управление
  Функции
  Документация
  Математика
  Файлы
  Основы SQL
  Дата и время
  CURL
  Изображения
  Стили
  Безопасность
  Установка
  Проектирование БД
  Регулярные выражения
  Подготовка к работе
  Быстрый старт
  Установка PHP
  Установка MySQL
  Конфигурация PHP
  Download / Скачать
  Скачать Apache
  Скачать PHP
  Скачать PECL
  Скачать PEAR
  Скачать MySQL
  Редакторы PHP
  Полезные утилиты
  Документация
  PHP скрипты
  Скачать скрипты
  Инструменты
  PHP в примерах
  Новости портала
 Главная   »  Сборник статей
 
 

Отправка почты средствами PHP

Автор: Войцеховский Александр

Источник: phpclub.ru

1. Как отправить письмо средствами PHP

Самый простой способ отправить письмо при помощи PHP - воспользоваться стандартной функцией mail. Она имеет следующий синтаксис:

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

Обязательные параметры:

  • E-mail получателя
  • Заголовок письма
  • Текст письма

Необязательные параметры:

  • Дополнительные заголовки письма
  • Дополнительные параметры командной строки

Возвращаемое значение::

  • true, если письмо было принято к доставке
  • false, в противном случае.

Простейший пример ее использования выглядит так:

<?php
mail
("joecool@example.com", "My Subject", "Line 1\nLine 2\nLine 3");
?>

Если у Вас на экране появилась ошибка "Fatal error: Call to undefined function: mail()", это значит, что либо PHP собран без поддержки функции mail, либо она запрещена настройками сервера. Такая практика в последнее время широко распространена на бесплатных хостинговых серверах. Если Вы столкнулись с такой проблемой, воспользуйтесь возможностью отправки писем при помощи сокетов (sockets), детально описанной в разделе "альтернативные способы отправки писем". В случае, если Вы администратор системы, обратитесь к разделу "Как настроить сервер" и попробуйте устранить эту проблему как таковую.

Дополнительные заголовки письма (additional headers) могут использоваться для указания кодировки письма, адреса отправителя, обратного адреса и множества других опций. Они должны быть разделены переводом строк: комбинацией "\r\n". Например, так:

<?php
mail
("nobody@example.com", "the subject", $message,
     
"From: webmaster@ example.com \r\n"
    
."X-Mailer: PHP/" . phpversion());
?>

Перейдем к более сложному примеру. Предыдущие скрипты работали с форматом text/plain, теперь же попробуем отправить почту в формате HTML нескольким адресатам с указанием кодировки:

<?php
$to  
= "Mary &lt;mary@example.com>, " ;
$to .= "Kelly &lt;kelly@example.com>";

$subject = "Birthday Reminders for August";

$message = '
<html>
    <head>
        <title>Birthday Reminders for August</title>
    </head>
    <body>
        <p>Here are the birthdays upcoming in August!</p>
    </body>
</html>'
;

$headers  = "Content-type: text/html; charset=windows-1251 \r\n";
$headers .= "From: Birthday Reminder <birthday@example.com>\r\n";
$headers .= "Bcc: birthday-archive@example.com\r\n";

mail($to, $subject, $message, $headers);
?>

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

В нашем примере переменная $headers состоит из четырех строк: в первых двух мы указываем тип отправляемого письма - HTML - и его кодировку. В следующих двух строках мы указываем адрес отправителя и адрес, по которому следует отправить скрытую копию письма.

Одна из часто возникающих проблем при отправке почты в koi8 - это формирование заголовка письма. Для ее решения необходимо воспользоваться следующим кодом, который переводит строку в кодировке win-1251 в понятный большинству почтовых клиентов koi8 заголовок.

<?php
$subject
= '=?koi8-r?B?'.base64_encode(convert_cyr_string($subject, "w","k")).'?=';
?>

К примеру, заголовок "Почтовое уведомление" будет выглядеть как

=?koi8-r?B?8M/e1M/Xz8Ug1dfFxM/NzMXOycU=?=

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

<?php
if (mail("nobody@example.com", "the subject", "Example message",  
"From: webmaster@example.com \r\n")) {
    echo
"messege acepted for delivery";
} else {
    echo
"some error happen";
}
?>

В случае если уже на этом шаге Вы получили ошибку, это может означать, что у Вас либо не запущен sendmail (или другой транспортный агент), либо он неправильно настроен, либо существуют ошибки в php.ini. К примеру, в последнее время распространено правило не принимать письма, в которых не указан правильный заголовок Mail-from.

В случае, если сообщение было принято к отправке, попробуйте посмотреть файл /var/log/mail или попросить об этом Вашего администратора, так как для этого требуются права суперюзера (root). Это можно сделать при помощи команды tail /var/log/mail. В случае успешной отправки письма в log-файле должны появится строки нижеприведенного типа либо сообщение об ошибке:

Oct 2 00:21:02 l72 sendmail[131]: h91LL1DG000131: to=root, ctladdr=root (0/0), delay=00:00:01, xdelay=00:00:01, mailer=relay, pri=30225, relay=[127.0.0.1] [127.0.0.1], dsn=2.0.0, stat=Sent (h91LL1g1000134 Message accepted for delivery)
Oct 2 00:21:18 l72 sendmail[137]: h91LL1g1000134: to=<ROOT@L72.UTEL.US>, ctladdr=<ROOT@L72.UTEL.US> (0/0), delay=00:00:17, xdelay=00:00:16, mailer=local, pri=30774, dsn=2.0.0, stat=Sent

В любом случае попробуйте посмотреть раздел "Как настроить сервер".

2. Как отправить письмо c вложением (attachment)

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

В связи с этим дальнейшие примеры кода будут базироваться на готовом решении, взятом из PEAR (репозиторий приложений и модулей PHP). Пакет, который будет использован в примерах, называется Mail_Mime. Скачать последнюю версию пакета и получить исчерпывающую документацию можно по адресу http://pear.php.net/package/Mail_Mime. Рассмотрим пример его использования:

<?php
include('Mail.php');
include(
'Mail/mime.php');

$text = 'Text version of email';
$html = '<html><body>HTML version of email</body></html>';
$file = '/home/richard/example.php';
$crlf = "\r\n";
$hdrs = array(
              
'From'    => 'you@yourdomain.com',
              
'Subject' => 'Test mime message'
              
);

$mime = new Mail_mime($crlf);

$mime->setTXTBody($text);
$mime->setHTMLBody($html);
$mime->addAttachment($file, 'text/plain');

$body = $mime->get();
$hdrs = $mime->headers($hdrs);

$mail =& Mail::factory('mail');
$mail->send('postmaster@localhost', $hdrs, $body);
?>

Приведенный код довольно понятен, но все же несколько слов о нем.

Переменная $mime является экземпляром класса Mail_mime. В его конструктор мы передали необязательный параметр, определяющий, какой именно перевод строки будет использован: "\n" или "\r\n". Данный класс предназначен для формирования тела и заголовков отправляемого письма. При помощи метода setTXTBody мы определяем текстовую часть письма. В качестве параметра метод принимает строку или имя файла, который будет использован. Аналогично при помощи метода setHTMLBody мы задаем содержимое HTML-версии письма.

Рассмотрим метод addAttachment подробнее. Принимаемые параметры:

  • string $data

    Полный путь к прикрепляемому файлу на сервере либо его содержимое. Обязательный параметр.

  • string $c_type

    Значение заголовка Сontent-type, который будет отправлен. Необязательный параметр, значение по умолчанию - application/octet-stream.

  • string $name

    Имя прикрепляемого файла. Будет использован только в случае, если первый параметр ($data) является содержимым файла.

  • boolean $isfile

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

  • string $encoding

    Значение заголовка Content-Transfer-Encoding, определяющего формат, в котором будет отправлено приложение. Необязательный параметр. Допустимые значения: base64 (используется для двоичных файлов), quoted-printable(используется для текстовых файлов). Значение по умолчанию: base64.

Таким образом, есть два способа применения данного метода.

  1. указывая путь к файлу на сервере:
    $mime->addAttachment('/home/user/report.txt', 'text/plain');
  2. указывая содержимое файла (в таком случае третий и четвертый параметры необходимо указывать принудительно):
    $mime->addAttachment($contentFile, 'text/plain', 'report.txt', false);

Переходим к формированию заголовка и тела письма. Это все еще обязанности экземпляра класса Mail_mime. Для формирования тела письма применяется метод get, который в качестве необязательного параметра принимает ассоциативный массив. Ключами могут выступать следующие значения: text_encoding, html_encoding, 7bit_wrap, text_charset, html_charset. Для формирования заголовков используется метод headers. В качестве необязательного параметра принимает хеш-массив. Для более детального ознакомления с допустимыми значениями данного параметра обратитесь к RFC-822.

Вызов метода get() должен осуществиться до того, как будет вызван метод headers(). Убедитесь, что в Вашем коде это условие соблюдено.

Сам процесс отправки уже сформированного письма возложен на класс Mail. Вначале необходимо при помощи статического вызова метода factory создать экземпляр данного класса. В нашем примере он принимает единственный параметр - строку 'mail'. Более детально принимаемые параметры и их значения описаны ниже в статье, где описываются альтернативные способы отправки почты.

Процесс отправки почты завершается вызовом метода send, принимающего в качестве входящего параметра список адресатов, заголовки письма и его тело.

Проверку на ошибки, во время отправки письма, можно реализовать используя следующий код:

<?php
$status
=$mailer->send('user@your.domain.com', $headers, 'your message');
if (
PEAR::isError($status)) {
      print(
"***ERROR");
}
?>

Для дальнейшего ознакомления с возможностями классов Mail и Mime_mail ознакомьтесь с разделами "Как отправить письмо с картинками", "Альтернативные способы отправки писем"

3. Как отправить письмо c картинками

Отправка письма с вложением и отправка HTML-письма с вложением существенно отличаются по своей природе. Конечно же, и те и те находятся в теле письма, закодированы в base64, но используемые в обоих случаях заголовки различаются. В данном разделе описывается, как отправить HTML-файл с внедренными (в отличие от прикрепленных) изображениями, используя класс Mime_mail. Подразумевается, что предыдущий раздел Вы уже прочитали.

<?php
include('Mail.php');
include(
'Mail/mime.php');

$text = 'Text version of email';
$html = '<html><body>HTML version of email<img src="image.jpg"></body></html>';
$file = '/tmp/image.jpg';
$crlf = "\r\n";
$hdrs = array(
              
'From'    => 'you@yourdomain.com',
              
'Subject' => 'Test mime message'
              
);

$mime = new Mail_mime($crlf);

$mime->setTXTBody($text);
$mime->addHTMLImage ($file, 'image/jpeg');
$mime->setHTMLBody($html);

$body = $mime->get();
$hdrs = $mime->headers($hdrs);


$mail =& Mail::factory('mail');
$mail->send('postmaster@localhost', $hdrs, $body);
?>

Отличие этого примера от приведенного в предыдущей главе - использование функции addHTMLImage. Она принимает следующие параметры:

  • string $data

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

  • string $c_type

    значение заголовка Сontent-type, который будет отправлен. Необязательный параметр, значение по умолчанию: application/octet-stream.

  • string $name

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

  • boolean $isfile

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

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

Особенность этого метода заключается в том, что каждому изображению при помощи заголовка Content-ID: <8820c4185> ставиться в соответствие уникальный ключ. После этого все ссылки на прикрепляемое изображение заменяются ссылками на его ключ. В результате, в пришедшем к получателю письме будет строка вида <IMG SRC="cid: 8820c4185">, которую почтовый клиент проанализирует, извлечет содержимое из соответствующей секции письма и "покажет картинку".

Более детальное описание MIME - заголовков предоставлено в разделе "MIME в разрезе".

4. Альтернативные способы отправки писем

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

  • Посредством вызова функции mail
  • Непосредственно вызовом sendmail-а
  • При помощи сокетов
  • Используя COM-объект

Первые три способа реализованы в классе PEAR::Mail, о котором было рассказано выше. Экземпляр этого класса должен создаваться посредством статического вызова метода factory (так называемый "паттерн фабрика"). Первый параметр метода определяет способ отправки письма, он может принимать одно из следующих значений: mail, sendmail, smtp. Второй параметр - массив, содержание которого зависит от значения первого параметра:

  • Значение 'mail' - отправка при помощи вызова стандартной функции, дополнительные параметры отсутствуют
  • Значение 'sendmail' - отправка непосредственно вызовом sendmail-а. Доступные дополнительные параметры:
    • sendmail_path - путь к программе на сервере;
    • sendmail_args - дополнительные параметры для командной строки.
  • Значение 'smtp' - отправка почты при помощи сокетов. Доступные дополнительные параметры:
    • host - IP адрес или доменное имя сервера, на котором запущен почтовый транспортый агент, готовый принимать почту, например localhost (для локального сервера) или mxs.mail.ru (для публичного сервера);
    • port - порт на котором он запущен, как правило 25-тый;
    • auth - логическое значение, которое указывает на необходимость SMTP авторизации, значение по умолчанию - false;
    • username - используется только при наличии SMTP авторизации, логин на сервере;
    • password - используется только при наличии SMTP авторизации, пароль на сервере.

Пример использования класса PEAR::Mail

<?php
$mail
=& Mail::factory('smtp', array('host' => 'localhost', 'port' => 25));
$mail->send('postmaster@localhost', $hdrs, $body);
?>

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

5. Как настроить сервер

5.1 Как настроить Linux-сервер

Если вы подошли к чтению этого раздела, это означает, что вы решили производить отправку почты посредством транспортного почтового агента (MTA), установленного на Вашем сервере, и столкнулись с проблемами.

Не стоит забывать, что отправка почты при помощи сокетов не требует установленного MTA, а позволяет использовать любой доступный для вас сервер, готовый принимать почту, к примеру, mxs.mail.ru.

Если у вас на экране появилось ошибка "Fatal error: Call to undefined function: mail()", это значит, что либо PHP собран без поддержки функции mail, либо она запрещена настройками сервера. Первое может возникнуть в том случае, если во время сборки скрипт configure не смог найти sendmail. Убедитесь, что путь к sendmail прописан в переменной окружения PATH, и попробуйте пересобрать PHP. Также посмотрите значение переменной disable_functions в файле php.ini.

В случае, если письма принимаются к отправке, но на этом все заканчивается, убедитесь в том, что у вас запущен Sendmail (либо любой другой MTA). Для этого попробуйте выполнить `telnet localhost 25` и если вы в ответ получаете "telnet: connect to address 127.0.0.1: Connection refused" вместо ожидаемого " Connected to localhost.", это означает, что у вас проблемы с MTA. Установка и настройка постовых транспортных агентов не описывается в данной статье, воспользуйтесь специализированными руководствами.

В случае, если попытка обратиться к 25му порту прошла успешно, попробуйте провести следующий сеанс:

l72:~ # telnet localhost 25
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 utel.us ESMTP Sendmail /8.12.7/Linux 0.6; Wed, 22 Oct 2003 16:10:45 +0300
helo localhost
250 72.utel.us Hello localhost [127.0.0.1], pleased to meet you
mail from: nobody@localhost
250 2.1.0 nobody@localhost... Sender ok
rcpt to: nobody@localhost
250 2.1.5 nobody@localhost... Recipient ok
DATA
354 Enter mail, end with "." on a line by itself
Helo world
.
250 2.0.0 h9MDAj1B009029 Message accepted for delivery
quit
Connection closed by foreign host.

Приведенный пример демонстрирует успешный сеанс отправки письма. В случае возникновения ошибок (например, требуется корректный адрес отправителя в строке "mail from"), sendmail выдаст предупреждение, и попросит повторить введенную строку.

Если с командной строки письма успешно отправляются, а при помощи php нет, попробуйте поэкспериментировать с четвертым параметром функции mail либо с настройкой sendmail_path, находящейся в файле php.ini

5.2 Как настроить Windows-сервер

Вначале необходимо определится, какой SMTP-сервер вы хотите использовать. Это может быть как ваш персональный PC, так и любой другой. Какой бы способ вы не выбрали, вам необходимо установить переменные SMTP, smtp_port, определяющие настройки сервера, отправляющего почту. Также установите переменную sendmail_from, определяющую обратный адрес отправителя.

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

Проверьте, отвечает ли кто-либо на 25м порту. Это можно сделать, выполнив `telnet localhost 25`. Если вы получили "Connection refused", это означает, что у вас не запущен почтовый агент, и, вероятнее всего, не установлен. В таком случае Вам необходимо посетить один из следующих ресурсов:

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

К примеру, приведем инструкцию по настройке первого из них:

  1. Скачать и проинсталлировать ArGoSoft Mail Server
  2. Запустить приложение и выбрать Tools > Options
  3. Выбрать DNS сервер либо предоставить возможность определять его автоматически
  4. В закладке "IP Homes" вести 127.0.0.1
  5. Стартовать сервис ArGoSoft Mail Server и убедиться, что не было сообщений об ошибках
  6. В файле php.ini указать SMTP = localhost

5.3 Как сделать WEB-доступ к почте

Посетите один из следующих ресурсов:

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

6. MIME в разрезе

 По мотивам вольного перевода статьи "Sending MIME e-mail from PHP"

 Более подробно о MIME Вы можете прочитать тут http://book.itep.ru/4/4/mime.htm.

Изначально, когда почта только зарождалась, никакого MIME не существовало. Он появился несколько позже как расширение к стандарту RFC-822. В настоящее время любое отправленное письмо, даже если оно не содержит никаких вложений, так или иначе использует MIME.

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

Чтобы наглядно показать разницу, рассмотрим два примера, содержащие одно и то же письмо в двух различных представлениях: обыкновенное письмо по стандарту RFC-822 и то же письмо, но с использованием MIME

From: "John Coggeshall" <john@zend.com>
To: Joe Users <joe@user.net>
Subject: Hello from John!
Date: Wed, 20 Jun 2001 20:18:47 -0400
Message-ID: <1234@local.machine.example>
Наше вам с кисточкой!
From: "John Coggeshall" <john@zend.com>
To: Joe Users <joe@user.net>
Subject: Hello from John!
Date: Wed, 20 Jun 2001 20:18:47 -0400
Message-ID: <1234@local.machine.example>
MIME-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Наше вам с кисточкой!

Разница в приведенных письмах очевидна: во втором примере используются три дополнительных заголовка. Обязательным из них является только первый: MIME-Version. Наибольший интерес для нас представляет заголовок Content-Type, изменяя который мы можем передавать произвольные типы документов.

From: "John Coggeshall" <john@zend.com>
To: Joe Users <joe@user.net>
Subject: Hello from John!
Date: Wed, 20 Jun 2001 20:18:47 -0400
Message-ID: <000d01c0f9e7$bee1bb00$8a22f340@oemcomputer>
MIME-Version: 1.0
Content-Type: image/jpeg; name='zendlogo.jpg' 
Content-Transfer-Encoding: base64
<base64 encoded data for the zendlogo.jpg image>

Сами данные base64 в примере были опущены. Недостаток приведенного примера - невозможность вставить текстовую часть, так как все нижеследующие данные трактуются как данные рисунка.

Если у Вас возникает задача отправить несколько различных объектов в одном письме (к примеру, текстовая часть и прикрепленная картинка) необходимо использовать заголовок Content-Type:multipart/mixed, обозначающий, что письмо состоит из нескольких сегментов. Так же необходимо определить параметр boundary, который будет обозначать границу между фрагментами. В преобладающем большинстве случаев его реальное значение можно выбирать произвольно. Каждый фрагмент комплектуется отдельным набором заголовков. Заметим, что заголовок MIME-Version должен быть один на все письмо и не может встречаться ни в одной из его частей. Приведем пример письма, состоящего их двух частей: текстового сообщения и прикрепленного изображения:

From: "John Coggeshall" <john@zend.com>
To: Joe Users <joe@user.net>
Subject: Hello from John!
Date: Wed, 20 Jun 2001 20:18:47 -0400
Message-ID: <000d01c0f9e7$bee1bb00$8a22f340@oemcomputer>
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="ZEND-12345";
Content-Transfer-Encoding: 7bit
This part of the E-mail should never be seen. If
you are reading this, consider upgrading your e-mail
client to a MIME-compatible client.
--ZEND-12345
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Hello! Here's that Zend.com logo!
-John
--ZEND-12345
Content-Type: image/jpeg; name="zendlogo.jpg";
Content-Transfer-Encoding: base64
Content-Disposition: attachment

--ZEND-12345--

Это простейший пример MIME-письма, состоящего из нескольких частей. Первая из них имеет тип text/plain и содержит реальное содержание письма. Вторая часть имеет тип image/jpeg и содержит закодированную base64 картинку, с названием zendlogo.jpg

При использовании составного письма, следует помнить:

  • Первичный заголовок content-type имеет значение multipart/mixed. Он сообщает клиентской почтовой программе, что письмо состоит из нескольких сегментов, каждый из которых имеет свой заголовок content-type;
  • Значение атрибута boundary определенного в первичном заголовке content-type используется для разделения сегментов письма (так называемый маркер границы).

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

Второй сегмент письма содержит дополнительный заголовок Content-Disposition. Он используется для того, чтобы сообщить почтовой программе клиента, как визуально следует отобразить данный сегмент письма. Он может принимать значение как attachment (не является частью письма, прикрепленный документ), так и inline (включение, непосредственно связанное с телом письма, например картинка, вставленная в HTML). Также допустимо использование заголовка Content-Description для краткого описания прикрепленного файла.

Значение multipart/alternative атрибута Content-Type по синтаксису абсолютно идентично multipart/mixed, описанному выше. Его назначение - обеспечить несколько вариантов отображения одного и того же содержания (вместо соединения трех различных документов, как в предыдущем случае). Рассмотрим пример письма, отправленного в трех форматах:

From: "John Coggeshall" <john@zend.com>
To: Joe Users <joe@user.net>
Subject: Hello from John!
Date: Wed, 20 Jun 2001 20:18:47 -0400
Message-ID: <000d01c0f9e7$bee1bb00$8a22f340@oemcomputer>
MIME-Version: 1.0
Content-Type: multipart/alternative; 
boundary="ZEND-12345";
Content-Transfer-Encoding: 7bit
This part of the E-mail should never be seen. If
you are reading this, consider upgrading your e-mail
client to a MIME-compatible client.
--ZEND-12345
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Hello! Here's that Zend.com!
-John
--ZEND-12345
Content-Type: text/enriched
<bold>Hello!</bold> Here is that <color><param>blue</param>Zend.com</color>!
-John
--ZEND-12345
Content-Type: application/x-myapplication
Content-Transfer-Encoding: base64
<base64 Content to display by the program that reads application/x-myapplication>
--ZEND-12345--

В приведенном письме содержатся три фрагмента. Первый их них содержит данные text/plain для отображения письма в виде текста. Второй фрагмент содержит те же данные в формате text/enriched (если Вы хотите узнать подробней о формате, обратитесь к RFC 1896). Третий фрагмент содержит некий произвольный формат application/x-myapplication с base64 содержимым письма. Согласно с установленным заголовком multipart/alternative адресат увидит ту часть письма, которую его почтовый агент сможет отобразить визуально наилучшим образом. Это означает, что если пользователь имеет приложение, способное отобразить тип документа application/x-myapplication, тогда именно этот фрагмент будет показан пользователю. В противном случае будет произведена попытка отобразить тип text/enriched. И в случае неудачи будет отображена секция, содержащая письмо в формате text/plain.

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

Очевидно, что заголовок multipart/alternative предоставляет возможность отправлять письма в формате text/plain и text/html одновременно, например:

From: "John Coggeshall" <john@zend.com>
To: Joe Users <joe@user.net>
Subject: Hello from John!
Date: Wed, 20 Jun 2001 20:18:47 -0400
Message-ID: <000d01c0f9e7$bee1bb00$8a22f340@oemcomputer>
MIME-Version: 1.0
Content-Type: multipart/alternative; 
boundary="ZEND-12345";
Content-Transfer-Encoding: 7bit
This part of the E-mail should never be seen. If
you are reading this, consider upgrading your e-mail
client to a MIME-compatible client.
--ZEND-12345
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: 7bit
Hey, Joe!
I heard you wanted to know where my column was on website. Here's the address:
/zend/spotlight/index.php
-John
--ZEND-12345
Content-Type: text/html
Content-Transfer-Encoding: 7bit
Hey, Joe!
I heard you wanted to know where my column was on 
  <A HREF="http://www.zend.com/">Zend's</A> website. 
Here's the address: 
  <A HREF=http://www.zend.com/zend/spotlight/index.php>Code Gallery</A>
-John
--ZEND-12345--

И в завершение несколько слов про отправку писем с внедренными изображениями. Существует несколько способов реализовать такую возможность. В секции, содержащей HTML-код можно написать следующее: <IMG SRC="http://www.zend.com/logo.jpg">. В случае, если в момент открытия такого письма пользователь находиться в on-line и данное действие не запрещено настройками его почтового клиента, содержимое картинки будет запрошено у сервера, и она будет отображена. Плюсом данного способа является малый размер отправляемого письма. Минусом - необходимость наличия on-line и зависимость от настроек почтового клиента. Второй способ - использовать заголовок Content-ID. Он используется для сопоставления каждой секции письма уникального идентификатора. В общем случае, такой заголовок может быть указан для каждой секции письма, но на практике это имеет смысл только если Вам потребуется сослаться на этот фрагмент в теле письма либо в других фрагментах. Примером могут служить картинки, flash-анимации, ролики. И, таким образом, Вы получаете возможность ссылаться не на внешний источник, а на секцию письма по ее идентификатору. В разрезе это выглядит так:

From: "John Coggeshall" <john@zend.com>
To: Joe Users <joe@user.net>
Subject: Hello from John!
Date: Wed, 20 Jun 2001 20:18:47 -0400
Message-ID: <000d01c0f9e7$bee1bb00$8a22f340@oemcomputer>
MIME-Version: 1.0
Content-Type: multipart/alternative; 
boundary="ZEND-12345";
Content-Transfer-Encoding: 7bit
This part of the E-mail should never be seen. If
you are reading this, consider upgrading your e-mail
client to a MIME-compatible client.
--ZEND-12345
Content-Type: text/html
Content-Transfer-Encoding: 7bit
This is the zend logo:
<IMG SRC="cid:ZendImage12345">
--ZEND-12345
Content-Type: image/jpeg
Content-Transfer-Encoding: base64
Content-ID: ZendImage12345
<base64 encoded logo.jpg file>
--ZEND-12345--
                  

Новизна этого примера в строке <IMG SRC="cid:ZendImage12345">, где внешний источник был заменен указанием локального идентификатора. Фактическое значение, указываемое в заголовке Content-ID, может быть произвольно, как и в случае с boundary. Главное требование - его уникальность в переделах письма. Используя такую методику прикрепления файлов, Вы можете комплектовать полноценный пакет документов, таких, как html-содержимое письма, файлы стилей, картинки, офисные документы, текстовая версия, и отправлять его одним письмом. Правда, при этом не стоит забывать, что большинство пользователей имеют канал с малой пропускной способностью и, скорее всего, просто не захотят получать письмо большого размера.

7. Примеры исходных кодов

7.1 Отправка писем с вложениями

<?php
function XMail( $from, $to, $subj, $text, $filename) {
    
$f         = fopen($filename,"rb");
    
$un        = strtoupper(uniqid(time()));
    
$head      = "From: $from\n";
    
$head     .= "To: $to\n";
    
$head     .= "Subject: $subj\n";
    
$head     .= "X-Mailer: PHPMail Tool\n";
    
$head     .= "Reply-To: $from\n";
    
$head     .= "Mime-Version: 1.0\n";
    
$head     .= "Content-Type:multipart/mixed;";
    
$head     .= "boundary=\"----------".$un."\"\n\n";
    
$zag       = "------------".$un."\nContent-Type:text/html;\n";
    
$zag      .= "Content-Transfer-Encoding: 8bit\n\n$text\n\n";
    
$zag      .= "------------".$un."\n";
    
$zag      .= "Content-Type: application/octet-stream;";
    
$zag      .= "name=\"".basename($filename)."\"\n";
    
$zag      .= "Content-Transfer-Encoding:base64\n";
    
$zag      .= "Content-Disposition:attachment;";
    
$zag      .= "filename=\"".basename($filename)."\"\n\n";
    
$zag      .= chunk_split(base64_encode(fread($f,filesize($filename))))."\n";
    
    return @
mail("$to", "$subj", $zag, $head);
}
?>

Приведем ссылки на некоторые более "продвинутые" классы:

7.2 Использование сокетов

<?php
function socketmail($server, $to, $from, $subject, $message) {
    
$connect = fsockopen ($server, 25, $errno, $errstr, 30);
    
fputs($connect, "HELO localhost\r\n");
    
fputs($connect, "MAIL FROM: $from\n");
    
fputs($connect, "RCPT TO: $to\n");
    
fputs($connect, "DATA\r\n");
    
fputs($connect, "Content-Type: text/plain; charset=iso-8859-1\n");
    
fputs($connect, "To: $to\n");
    
fputs($connect, "Subject: $subject\n");
    
fputs($connect, "\n\n");
    
fputs($connect, stripslashes($message)." \r\n");
    
fputs($connect, ".\r\n");
    
fputs($connect, "RSET\r\n");
}
?>

7.3 Использование sendmail

<?php
$sendmail
= "/usr/sbin/sendmail -t -f $sender -C /etc/sendmail.orig.cf";
$fd = popen($sendmail, "w");
fputs($fd, "To: recipient@example.com\r\n");
fputs($fd, "From: \"Sender Name\" <$sender>\r\n");
fputs($fd, "Subject: Finally\r\n");
fputs($fd, "X-Mailer: Mailer Name\r\n\r\n");
fputs($fd, $body);
pclose($fd);
?>

7.3 Использование ActiveX

<?php
@$CDONTS = new COM("CDONTS.NewMail");

@
$CDONTS->From = "from_user@domain.com";
@
$CDONTS->To = "to_user@domain.com";
@
$CDONTS->CC = "cc_user@domain.com";
@
$CDONTS->BCC = "bcc_user@domain.com";

@
$CDONTS->BodyFormat = 0;
@
$CDONTS->MailFormat = 0;

//@$CDONTS->AttachFile("c:\file.txt");

@$CDONTS->Subject = "Using CDONTS with PHP4 and IIS";
@
$CDONTS->Body = "Blah blah blah blah, bleh...";

@
$CDONTS->Send();
@
$CDONTS->Close();
?>

Либо даже так

<?
$objApp
= new COM("Outlook.Application");
$myItem = $objApp->CreateItem(olMailItem);
$a=$myItem->Recipients->Add("admin@purplerain.org");
$myItem->Subject="Subject";
$myItem->Body="This is a Body Section now.....!";
$myItem->Display();
$myItem->Send();
?>

 
 » Обсудить эту статью на форуме

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

 
Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS