1. Как отправить письмо средствами PHP
2. Как отправить письмо c вложением (attachment), обзор PEAR
3. Как отправить письмо c картинками
4. Альтернативные способы отправки писем
5. Как настроить сервер
6. MIME в разрезе
7. Примеры исходных кодов
2. Как отправить письмо c вложением (attachment), обзор PEAR
3. Как отправить письмо c картинками
4. Альтернативные способы отправки писем
5. Как настроить сервер
6. MIME в разрезе
7. Примеры исходных кодов
1. Как отправить письмо средствами PHP
Самый простой способ отправить письмо при помощи PHP - воспользоваться стандартной функцией mail. Она имеет следующий синтаксис:
Если у Вас на экране появилась ошибка "Fatal error: Call to undefined function: mail()", это значит, что либо PHP собран без поддержки функции mail, либо она запрещена настройками сервера. Такая практика в последнее время широко распространена на бесплатных хостинговых серверах. Если Вы столкнулись с такой проблемой, воспользуйтесь возможностью отправки писем при помощи сокетов (sockets), детально описанной в разделе "альтернативные способы отправки писем". В случае, если Вы администратор системы, обратитесь к разделу "Как настроить сервер" и попробуйте устранить эту проблему как таковую.
Дополнительные заголовки письма (additional headers) могут использоваться для указания кодировки письма, адреса отправителя, обратного адреса и множества других опций. Они должны быть разделены переводом строк: комбинацией "\r\n". Например, так:
Перейдем к более сложному примеру. Предыдущие скрипты работали с форматом text/plain, теперь же попробуем отправить почту в формате HTML нескольким адресатам с указанием кодировки:
Комментарии к примеру: вначале мы определяем, кому адресовано письмо. Если получателей несколько, их адреса указываются в одной строке и разделяются запятыми. При задании заголовка и тела письма следите, чтобы кодировка, в которой они действительно написаны, совпадала с заявленной в заголовке charset.
В нашем примере переменная $headers состоит из четырех строк: в первых двух мы указываем тип отправляемого письма - HTML - и его кодировку. В следующих двух строках мы указываем адрес отправителя и адрес, по которому следует отправить скрытую копию письма.
Одна из часто возникающих проблем при отправке почты в koi8 - это формирование заголовка письма. Для ее решения необходимо воспользоваться следующим кодом, который переводит строку в кодировке win-1251 в понятный большинству почтовых клиентов koi8 заголовок.
К примеру, заголовок "Почтовое уведомление" будет выглядеть как
В случае если уже на этом шаге Вы получили ошибку, это может означать, что у Вас либо не запущен sendmail (или другой транспортный агент), либо он неправильно настроен, либо существуют ошибки в php.ini. К примеру, в последнее время распространено правило не принимать письма, в которых не указан правильный заголовок Mail-from.
В случае, если сообщение было принято к отправке, попробуйте посмотреть файл /var/log/mail или попросить об этом Вашего администратора, так как для этого требуются права суперюзера (root). Это можно сделать при помощи команды tail /var/log/mail. В случае успешной отправки письма в log-файле должны появится строки нижеприведенного типа либо сообщение об ошибке:
В связи с этим дальнейшие примеры кода будут базироваться на готовом решении, взятом из PEAR (репозиторий приложений и модулей PHP). Пакет, который будет использован в примерах, называется Mail_Mime. Скачать последнюю версию пакета и получить исчерпывающую документацию можно по адресу http://pear.php.net/package/Mail_Mime. Рассмотрим пример его использования:
Приведенный код довольно понятен, но все же несколько слов о нем.
Переменная $mime является экземпляром класса Mail_mime. В его конструктор мы передали необязательный параметр, определяющий, какой именно перевод строки будет использован: "\n" или "\r\n". Данный класс предназначен для формирования тела и заголовков отправляемого письма. При помощи метода setTXTBody мы определяем текстовую часть письма. В качестве параметра метод принимает строку или имя файла, который будет использован. Аналогично при помощи метода setHTMLBody мы задаем содержимое HTML-версии письма.
Рассмотрим метод addAttachment подробнее. Принимаемые параметры:
Вызов метода get() должен осуществиться до того, как будет вызван метод headers(). Убедитесь, что в Вашем коде это условие соблюдено.
Сам процесс отправки уже сформированного письма возложен на класс Mail. Вначале необходимо при помощи статического вызова метода factory создать экземпляр данного класса. В нашем примере он принимает единственный параметр - строку 'mail'. Более детально принимаемые параметры и их значения описаны ниже в статье, где описываются альтернативные способы отправки почты.
Процесс отправки почты завершается вызовом метода send, принимающего в качестве входящего параметра список адресатов, заголовки письма и его тело.
Проверку на ошибки, во время отправки письма, можно реализовать используя следующий код:
Для дальнейшего ознакомления с возможностями классов Mail и Mime_mail ознакомьтесь с разделами "Как отправить письмо с картинками", "Альтернативные способы отправки писем"
Отличие этого примера от приведенного в предыдущей главе - использование функции addHTMLImage. Она принимает следующие параметры:
Особенность этого метода заключается в том, что каждому изображению при помощи заголовка Content-ID: <8820c4185> ставиться в соответствие уникальный ключ. После этого все ссылки на прикрепляемое изображение заменяются ссылками на его ключ. В результате, в пришедшем к получателю письме будет строка вида
, которую почтовый клиент проанализирует, извлечет содержимое из соответствующей секции письма и "покажет картинку".
Более детальное описание MIME - заголовков предоставлено в разделе "MIME в разрезе".
В приложении к данной статье приведены примеры исходных кодов, реализовывающие все перечисленные способы отправки почты без применения класса PEAR::Mail.
Не стоит забывать, что отправка почты при помощи сокетов не требует установленного 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му порту прошла успешно, попробуйте провести следующий сеанс:
Если с командной строки письма успешно отправляются, а при помощи php нет, попробуйте поэкспериментировать с четвертым параметром функции mail либо с настройкой sendmail_path, находящейся в файле php.ini
Дальнейшее инструкции относятся только к тем, кто решил использовать свой персональный PC как сервер исходящей почты.
Проверьте, отвечает ли кто-либо на 25м порту. Это можно сделать, выполнив `telnet localhost 25`. Если вы получили "Connection refused", это означает, что у вас не запущен почтовый агент, и, вероятнее всего, не установлен. В таком случае Вам необходимо посетить один из следующих ресурсов:
К примеру, приведем инструкцию по настройке первого из них:
На любом из них вы найдете все необходимые скрипты и детальную инструкцию по инсталляции и настройке.
Вначале письмо понималось как линейное текстовое послание, содержимое которого можно прочитать, просмотрев его исходный код. Расширение MIME позволяет определить внутри письма специфические атрибуты: тип передаваемой информации, способ его кодирования и рекомендации к отображению. Также позволяет разбивать письмо на независимые секции и выставлять индивидуальные атрибуты для каждой из них.
Чтобы наглядно показать разницу, рассмотрим два примера, содержащие одно и то же письмо в двух различных представлениях: обыкновенное письмо по стандарту RFC-822 и то же письмо, но с использованием MIME
Если у Вас возникает задача отправить несколько различных объектов в одном письме (к примеру, текстовая часть и прикрепленная картинка) необходимо использовать заголовок Content-Type:multipart/mixed, обозначающий, что письмо состоит из нескольких сегментов. Так же необходимо определить параметр boundary, который будет обозначать границу между фрагментами. В преобладающем большинстве случаев его реальное значение можно выбирать произвольно. Каждый фрагмент комплектуется отдельным набором заголовков. Заметим, что заголовок MIME-Version должен быть один на все письмо и не может встречаться ни в одной из его частей. Приведем пример письма, состоящего их двух частей: текстового сообщения и прикрепленного изображения:
При использовании составного письма, следует помнить:
Второй сегмент письма содержит дополнительный заголовок Content-Disposition. Он используется для того, чтобы сообщить почтовой программе клиента, как визуально следует отобразить данный сегмент письма. Он может принимать значение как attachment (не является частью письма, прикрепленный документ), так и inline (включение, непосредственно связанное с телом письма, например картинка, вставленная в HTML). Также допустимо использование заголовка Content-Description для краткого описания прикрепленного файла.
Значение multipart/alternative атрибута Content-Type по синтаксису абсолютно идентично multipart/mixed, описанному выше. Его назначение - обеспечить несколько вариантов отображения одного и того же содержания (вместо соединения трех различных документов, как в предыдущем случае). Рассмотрим пример письма, отправленного в трех форматах:
Не случайно самый примитивный способ отображения письма был поставлен первым. Это сделано с учетом того, что почтовый клиент пользователя может не поддерживать формат MIME.
Очевидно, что заголовок multipart/alternative предоставляет возможность отправлять письма в формате text/plain и text/html одновременно, например:
. В случае, если в момент открытия такого письма пользователь находиться в on-line и данное действие не запрещено настройками его почтового клиента, содержимое картинки будет запрошено у сервера, и она будет отображена. Плюсом данного способа является малый размер отправляемого письма. Минусом - необходимость наличия on-line и зависимость от настроек почтового клиента. Второй способ - использовать заголовок Content-ID. Он используется для сопоставления каждой секции письма уникального идентификатора. В общем случае, такой заголовок может быть указан для каждой секции письма, но на практике это имеет смысл только если Вам потребуется сослаться на этот фрагмент в теле письма либо в других фрагментах. Примером могут служить картинки, flash-анимации, ролики. И, таким образом, Вы получаете возможность ссылаться не на внешний источник, а на секцию письма по ее идентификатору. В разрезе это выглядит так:
, где внешний источник был заменен указанием локального идентификатора. Фактическое значение, указываемое в заголовке Content-ID, может быть произвольно, как и в случае с boundary. Главное требование - его уникальность в переделах письма. Используя такую методику прикрепления файлов, Вы можете комплектовать полноценный пакет документов, таких, как html-содержимое письма, файлы стилей, картинки, офисные документы, текстовая версия, и отправлять его одним письмом. Правда, при этом не стоит забывать, что большинство пользователей имеют канал с малой пропускной способностью и, скорее всего, просто не захотят получать письмо большого размера.
Приведем ссылки на некоторые более "продвинутые" классы:
Либо даже так
bool mail ( string to, string subject, string message [, string additional_headers [, string additional_parameters]])
Обязательные параметры:
- E-mail получателя
- Заголовок письма
- Текст письма
Необязательные параметры:
- Дополнительные заголовки письма
- Дополнительные параметры командной строки
Возвращаемое значение::
- true, если письмо было принято к доставке
- false, в противном случае.
mail("joecool@example.com", "My Subject", "Line 1\nLine 2\nLine 3"); ?>
Дополнительные заголовки письма (additional headers) могут использоваться для указания кодировки письма, адреса отправителя, обратного адреса и множества других опций. Они должны быть разделены переводом строк: комбинацией "\r\n". Например, так:
mail("nobody@example.com", "the subject", $message,
"From: webmaster@ example.com \r\n"
."X-Mailer: PHP/" . phpversion()); ?>
$to = "Mary <mary@example.com>, " ; $to .= "Kelly <kelly@example.com>";
$subject = "Birthday Reminders for August";
$message = '
Birthday Reminders for August
Here are the birthdays upcoming in August!
';
$headers = "Content-type: text/html; charset=windows-1251 \r\n"; $headers .= "From: Birthday Reminder \r\n" ; $headers .= "Bcc: birthday-archive@example.com\r\n";
mail($to, $subject, $message, $headers); ?>
Комментарии к примеру: вначале мы определяем, кому адресовано письмо. Если получателей несколько, их адреса указываются в одной строке и разделяются запятыми. При задании заголовка и тела письма следите, чтобы кодировка, в которой они действительно написаны, совпадала с заявленной в заголовке charset.
В нашем примере переменная $headers состоит из четырех строк: в первых двух мы указываем тип отправляемого письма - HTML - и его кодировку. В следующих двух строках мы указываем адрес отправителя и адрес, по которому следует отправить скрытую копию письма.
Одна из часто возникающих проблем при отправке почты в koi8 - это формирование заголовка письма. Для ее решения необходимо воспользоваться следующим кодом, который переводит строку в кодировке win-1251 в понятный большинству почтовых клиентов koi8 заголовок.
$subject = '=?koi8-r?B?'.base64_encode(convert_cyr_string($subject, "w","k")).'?='; ?>
=?koi8-r?B?8M/e1M/Xz8Ug1dfFxM/NzMXOycU=?=Если Вы все сделали правильно, а получатель письмо не получает (помните, что временные издержки на доставку письма зависят от многих факторов и могут колебаться от нескольких минут до нескольких часов), убедитесь в том, что оно действительно отправилось. Это необходимо сделать в 2 этапа. Вначале попробуйте выполнить код:
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";
} ?>
В случае, если сообщение было принято к отправке, попробуйте посмотреть файл /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=, ctladdr= (0/0), delay=00:00:17, xdelay=00:00:16, mailer=local, pri=30774, dsn=2.0.0, stat=Sent
В любом случае попробуйте посмотреть раздел "Как настроить сервер".Oct 2 00:21:18 l72 sendmail[137]: h91LL1g1000134: to=
2. Как отправить письмо c вложением (attachment)
С такой задачей сталкивалось огромнейшее количество разработчиков и, как следствие, существует огромнейшее количество готовых решений. Большинство из них содержит различного рода ошибки, реализовывает не всю функциональность или сложны в применении. Но самый весомый минус - подавляющая масса разработчиков после написания класса, отвечающего его личным потребностям сегодняшнего дня, никогда более не возвращаются к поддержке и доработке исходных кодов.В связи с этим дальнейшие примеры кода будут базироваться на готовом решении, взятом из PEAR (репозиторий приложений и модулей PHP). Пакет, который будет использован в примерах, называется Mail_Mime. Скачать последнюю версию пакета и получить исчерпывающую документацию можно по адресу http://pear.php.net/package/Mail_Mime. Рассмотрим пример его использования:
include('Mail.php');
include('Mail/mime.php');
$text = 'Text version of email'; $html = 'HTML version of email'; $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.
- указывая путь к файлу на сервере:
$mime->addAttachment('/home/user/report.txt', 'text/plain');
- указывая содержимое файла (в таком случае третий и четвертый параметры необходимо указывать принудительно):
$mime->addAttachment($contentFile, 'text/plain', 'report.txt', false);
Вызов метода get() должен осуществиться до того, как будет вызван метод headers(). Убедитесь, что в Вашем коде это условие соблюдено.
Сам процесс отправки уже сформированного письма возложен на класс Mail. Вначале необходимо при помощи статического вызова метода factory создать экземпляр данного класса. В нашем примере он принимает единственный параметр - строку 'mail'. Более детально принимаемые параметры и их значения описаны ниже в статье, где описываются альтернативные способы отправки почты.
Процесс отправки почты завершается вызовом метода send, принимающего в качестве входящего параметра список адресатов, заголовки письма и его тело.
Проверку на ошибки, во время отправки письма, можно реализовать используя следующий код:
$status =$mailer->send('user@your.domain.com', $headers, 'your message');
if (PEAR::isError($status)) {
print("***ERROR");
} ?>
3. Как отправить письмо c картинками
Отправка письма с вложением и отправка HTML-письма с вложением существенно отличаются по своей природе. Конечно же, и те и те находятся в теле письма, закодированы в base64, но используемые в обоих случаях заголовки различаются. В данном разделе описывается, как отправить HTML-файл с внедренными (в отличие от прикрепленных) изображениями, используя класс Mime_mail. Подразумевается, что предыдущий раздел Вы уже прочитали.include('Mail.php');
include('Mail/mime.php');
$text = 'Text version of email'; $html = 'HTML version of email
'; $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); ?>
- string $dataполный путь к прикрепляемому изображению на сервере либо его содержимое. Обязательный параметр.
- string $c_typeзначение заголовка Сontent-type, который будет отправлен. Необязательный параметр, значение по умолчанию: application/octet-stream.
- string $nameимя прикрепляемого изображения. Будет использовано только в случае, если первый параметр ($data) является содержимым файла.
- boolean $isfileопределяет, является ли первый параметр путем к изображению. Необязательный параметр, значение по умолчанию: true.
Особенность этого метода заключается в том, что каждому изображению при помощи заголовка Content-ID: <8820c4185> ставиться в соответствие уникальный ключ. После этого все ссылки на прикрепляемое изображение заменяются ссылками на его ключ. В результате, в пришедшем к получателю письме будет строка вида
Более детальное описание MIME - заголовков предоставлено в разделе "MIME в разрезе".
4. Альтернативные способы отправки писем
На сегодняшний день распространены следующие способы отправки писем из php-скриптов:- Посредством вызова функции mail
- Непосредственно вызовом sendmail-а
- При помощи сокетов
- Используя COM-объект
- Значение 'mail' - отправка при помощи вызова стандартной функции, дополнительные параметры отсутствуют
- Значение 'sendmail' - отправка непосредственно вызовом sendmail-а. Доступные дополнительные параметры:
- sendmail_path - путь к программе на сервере;
- sendmail_args - дополнительные параметры для командной строки.
- Значение 'smtp' - отправка почты при помощи сокетов. Доступные дополнительные параметры:
- host - IP адрес или доменное имя сервера, на котором запущен почтовый транспортый агент, готовый принимать почту, например localhost (для локального сервера) или mxs.mail.ru (для публичного сервера);
- port - порт на котором он запущен, как правило 25-тый;
- auth - логическое значение, которое указывает на необходимость SMTP авторизации, значение по умолчанию - false;
- username - используется только при наличии SMTP авторизации, логин на сервере;
- password - используется только при наличии SMTP авторизации, пароль на сервере.
$mail =& Mail::factory('smtp', array('host' => 'localhost', 'port' => 25)); $mail->send('postmaster@localhost', $hdrs, $body); ?>
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", это означает, что у вас не запущен почтовый агент, и, вероятнее всего, не установлен. В таком случае Вам необходимо посетить один из следующих ресурсов:
- http://www.argosoft.com/applications/mailserver/
- http://courierms.narod.ru/
- http://www.indigostar.com/sendmail.htm
К примеру, приведем инструкцию по настройке первого из них:
- Скачать и проинсталлировать ArGoSoft Mail Server
- Запустить приложение и выбрать Tools > Options
- Выбрать DNS сервер либо предоставить возможность определять его автоматически
- В закладке "IP Homes" вести 127.0.0.1
- Стартовать сервис ArGoSoft Mail Server и убедиться, что не было сообщений об ошибках
- В файле 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"To: Joe Users Subject: Hello from John! Date: Wed, 20 Jun 2001 20:18:47 -0400 Message-ID: <1234@local.machine.example> Наше вам с кисточкой!
From: "John Coggeshall"Разница в приведенных письмах очевидна: во втором примере используются три дополнительных заголовка. Обязательным из них является только первый: MIME-Version. Наибольший интерес для нас представляет заголовок Content-Type, изменяя который мы можем передавать произвольные типы документов.To: Joe Users 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 Наше вам с кисточкой!
From: "John Coggeshall"Сами данные base64 в примере были опущены. Недостаток приведенного примера - невозможность вставить текстовую часть, так как все нижеследующие данные трактуются как данные рисунка.To: Joe Users 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
Если у Вас возникает задача отправить несколько различных объектов в одном письме (к примеру, текстовая часть и прикрепленная картинка) необходимо использовать заголовок Content-Type:multipart/mixed, обозначающий, что письмо состоит из нескольких сегментов. Так же необходимо определить параметр boundary, который будет обозначать границу между фрагментами. В преобладающем большинстве случаев его реальное значение можно выбирать произвольно. Каждый фрагмент комплектуется отдельным набором заголовков. Заметим, что заголовок MIME-Version должен быть один на все письмо и не может встречаться ни в одной из его частей. Приведем пример письма, состоящего их двух частей: текстового сообщения и прикрепленного изображения:
From: "John Coggeshall"Это простейший пример MIME-письма, состоящего из нескольких частей. Первая из них имеет тип text/plain и содержит реальное содержание письма. Вторая часть имеет тип image/jpeg и содержит закодированную base64 картинку, с названием zendlogo.jpgTo: Joe Users 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--
При использовании составного письма, следует помнить:
- Первичный заголовок content-type имеет значение multipart/mixed. Он сообщает клиентской почтовой программе, что письмо состоит из нескольких сегментов, каждый из которых имеет свой заголовок content-type;
- Значение атрибута boundary определенного в первичном заголовке content-type используется для разделения сегментов письма (так называемый маркер границы).
Второй сегмент письма содержит дополнительный заголовок Content-Disposition. Он используется для того, чтобы сообщить почтовой программе клиента, как визуально следует отобразить данный сегмент письма. Он может принимать значение как attachment (не является частью письма, прикрепленный документ), так и inline (включение, непосредственно связанное с телом письма, например картинка, вставленная в HTML). Также допустимо использование заголовка Content-Description для краткого описания прикрепленного файла.
Значение multipart/alternative атрибута Content-Type по синтаксису абсолютно идентично multipart/mixed, описанному выше. Его назначение - обеспечить несколько вариантов отображения одного и того же содержания (вместо соединения трех различных документов, как в предыдущем случае). Рассмотрим пример письма, отправленного в трех форматах:
From: "John Coggeshall"В приведенном письме содержатся три фрагмента. Первый их них содержит данные text/plain для отображения письма в виде текста. Второй фрагмент содержит те же данные в формате text/enriched (если Вы хотите узнать подробней о формате, обратитесь к RFC 1896). Третий фрагмент содержит некий произвольный формат application/x-myapplication с base64 содержимым письма. Согласно с установленным заголовком multipart/alternative адресат увидит ту часть письма, которую его почтовый агент сможет отобразить визуально наилучшим образом. Это означает, что если пользователь имеет приложение, способное отобразить тип документа application/x-myapplication, тогда именно этот фрагмент будет показан пользователю. В противном случае будет произведена попытка отобразить тип text/enriched. И в случае неудачи будет отображена секция, содержащая письмо в формате text/plain.To: Joe Users 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 Hello! Here is thatblueZend.com ! -John --ZEND-12345 Content-Type: application/x-myapplication Content-Transfer-Encoding: base64--ZEND-12345--
Не случайно самый примитивный способ отображения письма был поставлен первым. Это сделано с учетом того, что почтовый клиент пользователя может не поддерживать формат MIME.
Очевидно, что заголовок multipart/alternative предоставляет возможность отправлять письма в формате text/plain и text/html одновременно, например:
From: "John Coggeshall"И в завершение несколько слов про отправку писем с внедренными изображениями. Существует несколько способов реализовать такую возможность. В секции, содержащей HTML-код можно написать следующее:To: Joe Users 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 Zend's website. Here's the address: Code Gallery -John --ZEND-12345--

From: "John Coggeshall"Новизна этого примера в строкеTo: Joe Users 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: --ZEND-12345 Content-Type: image/jpeg Content-Transfer-Encoding: base64 Content-ID: ZendImage12345
--ZEND-12345--
7. Примеры исходных кодов
7.1 Отправка писем с вложениями
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);
} ?>
- http://renoir.vill.edu/~ylee/mailfile.txt
- http://irbp.ru/mime_mail-imgs.html
- http://php.spb.ru/php/mail.html
7.2 Использование сокетов
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
$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
@$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(); ?>