Отправка email через php. Простейшая форма отправки данных на почту при помощи HTML и PHP

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

Общие возможности

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

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

Синтаксис функции mail():

Bool mail(string $to, string $subject, string $msg [, string $header]);

Чтобы было более понятно, что из себя представляют заголовки, и где они находятся в письме, откройте почтовый клиент и посмотрите на любое письмо в том виде, как оно пришло (Для Outlook это можно сделать нажав правой клавишей мыши на сообщение->Свойства->Подробно->Исходное сообщение ).

Как мы видим, письмо представляет простой текстовой файл, состоящий из двух общих разделов: Вверху идут заголовки письма, затем через две строки идет само письмо.

Заголовков письма достаточно много, но не все они используются при написании скрипта отправки почты.

Вот некоторые наиболее часто используемые:

  • From: "Имя пользователя отправителя" <Обратный адрес отправителя>
  • To: <Адрес, по которому отправляют письмо>
  • Subject: Тема письма

Решение проблемы кодировок

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

Кодировку письма задает заголовок Content-type :

$header="From: \"Evgen\" "; $header.="Content-type: text/plain; charset=\"windows-1251\""; $subject="Тема письма"; $msg="Сторака 1\nСтрока 2\nСтрока 3"; mail("

В заголовке мы указали, что тип письма будет простой текст, а кодировка - Windows.

Теперь наше письмо придет в понятной для почтового клиента кодировке.

Но стоит отметить, что в некоторых случаях в правильной кодировке будет отображено только само письмо. Заголовок же так и останется нечитаемым. Связано это с тем, где расположен заголовок Content-type относительно заголовка Subject , который и содержит тему письма. Дело в том, что существуют почтовые программы, которые понимают заголовок Content-type , но не понимают русский текст в поле Subject , если это поле стоит до Content-type . В то же время, другие почтовые программы обязывают нас задавать Content-type последним заголовком в списке. Чтобы обойти эти препятствия, можно разместить поле Content-type сразу в начале и в конце списка заголовков:

$subject="Тема письма"; $header="Content-type: text/plain; charset=\"windows-1251\""; $header.="From: Evgen "; $header.="Subject: $subject"; $header.="Content-type: text/plain; charset=\"windows-1251\""; $msg="Сторака 1\nСтрока 2\nСтрока 3"; mail(" ", $subject, $msg, $header);

Теперь это письмо прочтет любая почтовая программа!

Однако заметим, что это является извращением, и если это читает несколько кривых почтовых программ, которые нашли составители то это не значит что должны читать все.

Знакомство с php-функцией mail() и простейший пример её использования для отправки писем по электронной почте. Что лучше или Sendmail vs mail.

PHP-функция mail() позволяет вам отправлять письма на указанный адрес электронной почты.

Синтаксис :

Bool mail (string $to , string $subject , string $message [, string $additional_headers [, string $additional_parameters ]]);

Параметры :

  • to — адрес электронной почты получателя письма в соответствии с форматом RFC 2822. Например :
  • subject — тема отправляемого письма в соответствии с форматом RFC 2047
  • message — содержание отправляемого письма. Каждая строка должна быть не длиннее 70 символов и заканчиваться символом новой строки (\n).

    Только для Windows : Когда PHP обращается к SMTP серверу напрямую, точка в начале строки удаляется. Для борьбы с этим нюансом, следует использовать замену на двойную точку в начале строки.

    $message = str_replace ("\n.", "\n..", $message);

  • additional_headers (не обязательно) – строка, которая будет добавлена после заголовков письма. Обычно используется для добавления дополнительных заголовков (From, Cc и Bcc). Строки должны быть разделены CRLF (\r\n).
  • additional_parameters (не обязательно) – дополнительные параметры, используемые программой назначенной для отправки писем.

Возвращает : TRUE если письмо отправлено успешно или FALSE если нет. Следует отметить, если письмо успешно поставлено в очередь на отправление, это не значит, что оно достигнет адресата.

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

Пример : php-функция MIME base64 кодирования, с учетом кодировки

Function mime_base64($string, $charset="windows-1251") { return "=?" . $charset . "?B?" . base64_encode(trim($string)) . "?="; }

Одна из проблем, возникающих при отправке почты, заключается в формировании заголовка письма. В частности, заголовок, имена отправителя и получателя, написанные кириллицей могут быть распознаны почтовым клиентом получателя в искаженном виде. Для того чтобы избежать этой проблемы, можно воспользоваться MIME base64 кодированием, преобразующее последовательность байт в последовательность печатных ASCII символов.

Function is_email($string) { return preg_match("/^()+([\.a-zA-Z0-9_-])*@()+(\.+)*\.({2,6})$/", $string); }

С эти тоже разобрались. А теперь то, ради чего и писалась данная заметка.

Пример : отправка писем с помощью php-функции mail()

$charset = "windows-1251"; $from = mime_base64("Имя отправитель", $charset) . " "; $to = mime_base64("Имя получитель", $charset) . " "; $subject = mime_base64("Тема отправляемого письма", $charset); $message = "Содержание отправляемого письма."; $message = wordwrap($message, 70); $headers = "From: " . $from . "\r\n" . "Reply-To: " . $from . "\r\n" . "X-Mailer: PHP/" . phpversion(). "\r\n" . "MIME-Version: 1.0" . "\r\n" . "Content-type: text/plain; charset="" . $charset . """; if (mail($to, $subject, $message, $headers)) { echo "

Письмо отправлено.

"; } else { echo "

Произошла ошибка.

"; }

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

X-Sendmail-Cmdline: sendmail.pl -t -i To: =?windows-1251?B?yOz/IO/u6/P36PLl6/w=?= Subject: =?windows-1251?B?0uXs4CDu8u/w4OLr/+Xs7uPuIO/o8fzs4A==?= From: =?windows-1251?B?yOz/IO7y7/Dg4ujy5ev8?= Reply-To: =?windows-1251?B?yOz/IO7y7/Dg4ujy5ev8?= X-Mailer: PHP/5.3.3 MIME-Version: 1.0 Content-type: text/plain; charset="windows-1251"

Sendmail vs php mail()

Напоследок небольшой ликбез. Sendmail является одним из почтовых серверов (MTA), в то время как php-функция mail() просто реализует процесс отправки писем через SMTP соединение. Понятно, что использование php-функции является удобным, но далеко не оптимальным решением. Обычно mail() используется в тех случаях, когда речь не заходит о масштабных рассылках.

Содержит только текст (малый вес сообщения)

$name = "Пётр Петрович"; // необязательная переменная в качестве примера вставки в сообщение

$subject = "Тема сообщения"; //тема сообщения
$message = "Здравствуйте,".$name."!\n
Просто спросить как дела!\n
С уважением, Иван Иванович";//содержание сообщения
mail($email, $subject, $message, "From: [email protected]\nReply-To: [email protected]\nContent-type:text/plain; Charset=utf-8\r\n"); //отправляем сообщение
?>

2. Отправка письма mail php Тип text/html

Могут содержать графические html-элементы, сслыки и тп.
Больше объём передаваемой информации

// отправка нескольким адресатам
$to = "[email protected]" . ", "; // кому отправляем
$to .= "[email protected]" . ", "; // Внимание! Так пишем второй и тд адреса
// не забываем запятую. Даже в последнем контакте лишней не будет
// Для начинающих! $to .= точка в этом случае для Дописывания в переменную

// устанавливаем тип сообщения Content-type, если хотим
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type: text/html; charset=utf-8 \r\n";

// дополнительные данные
$headers .= "From: yournick \r\n"; // от кого
$headers .= "Cc: [email protected]" . "\r\n"; // копия сообщения на этот адрес
$headers .= "Bcc: [email protected]\r\n"; // скрытая копия сообщения на этот
mail($to, $subject, $message, $headers);
?>

3. Как использовать в письме CSS?

Тут я хочу сразу немного огорчить Вас - CSS в привычном для Вас виде не стоит использовать. Mail, Yandex, Google, Outlook - выкидывают стили из писем. Однако, есть выход.

Выполним несколько условий:
1) Надеюсь не нужно пояснять, что используем Content-type: text/html

2) Вспоминаем, что такое table вёрстска. Теперь все стили вписываем только в неё. Можно также вспомнить center , font .




От кого: Иванов Иван Иванович
Адрес: [email protected]
Сообщение: Смотрим и радуемся

С div то же самое

Нужный Вам текст

3) В примере выше с отправкой письма приводилась данная строка. Так вот её не забываем

$headers = "MIME-Version: 1.0" . "\r\n";

4) Используем HTML 3.2 . Вставляем в начало html письма.


5) В качестве background - можно цвет. Хотите фон-изображение - тогда делайте весь текст и фон изображением. Как вариант: можно указать background-image для body.

6) У единственной в ячейке картинки в Gmail появляется 3px отступ снизу, чтобы избежать этого указываем ей

Одной из самых востребованных функций на сайте является форма заявки или заказа, данные из которой отправляются на почту владельцу сайта. Как правило такие формы являются простыми и состоят из двух трех полей для ввода данных. Как же создать такую форму заказа? Здесь потребуется использование языка разметки HTML и языка программирования PHP.

Язык разметки HTML сам по себе несложен, нужно всего лишь разобраться в том как и где ставить те или иные теги. С языком программирования PHP все немного сложнее.

Для программиста создать такую форму не составит труда, а вот HTML верстальщику может показаться сложным некоторые действия.

Создаем форму отправки данных в html

Первая строка будет следующей

Это очень важный элемент формы. В нем мы указываем каким способом будут передаваться данные и какому файлу. В данном случае все передачется методом POST файлу send.php. Программа в этом файле соответственно должна принять данные, они будут содержаться в post массиве, и отправить их на указанный email адрес.

Вернемся к форме. Вторая строка будет содержать поле для ввода ФИО. Имеет следующий код:

Тип формы text, то есть пользователь сможет ввести или скопировать сюда текст с клавиатуры. Под параметром name содержится название формы. В данном случае это fio, именно под таким именем будет передаваться все, что пользователь введен в данноу поле. Параметр placeholder указывает на то, что будет записано в этом поле в виде пояснения.

Следующая строка:

Здесь практически все то же самое, но имя для поля указано email, а пояснении указано, чтобы пользователь в эту форму ввел свой адресс электронной почты.

Следующей строкой будет кнопка "отправить":

И последней строкой в форме будет тэг

Теперь соберем все вместе.





Теперь сделаем так, чтобы поля в форме стали обязательными для заполнения. Имеем следующий код:





Создаем файл, принимающий данные из HTML формы

Это будет файл с именем send.php

В файле на первом этапе нужно принять данные из пост массива. Для этого создаем две переменные:

$fio = $_POST["fio"];
$email = $_POST["email"];

Перед названиями переменных в php ставиться знак $, в конце каждой строки ставиться точка с запятой. $_POST это массив в который передаются данный из формы. В форме html при этом указан метод отправки method="post". Так, приняты две переменные из формы html. Для целей защиты своего сайта нужно провести эти переменные через несколько фильтров - функций php.

Первая функция преобразует все символы, которые пользователь попытается добавить в форму:

При этом новые переменные в php не создаются, а используются уже имеющиеся. Что сделает фильтр, он преобразует символ "<" в "<". Также он поступить с другими символами, встречающимися в html коде.

Вторая функция декодирует url, если пользователь попытается его добавить в форму.

$fio = urldecode($fio);
$email = urldecode($email);

Третей функцией мы удалим пробелы с начала и конца строки, если таковые имеются:

$fio = trim($fio);
$email = trim($email);

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

Проверка данных, передаваемых от HTML формы в файл PHP

Для того, чтобы проверить, работает ли этот код, передаются ли данные можно просто их вывести на экран при помощи функции echo:

echo $fio;
echo "
";
echo $fio;

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

Отправляем полученные данные из формы HTML на почту при помощи PHP

Для отправки данных на почту нужно воспользоваться функцией mail в PHP.

mail("на какой адрес отправить", "тема письма", "Сообщение (тело письма)","From: с какого email отправляется письмо \r\n");

Например, нужно отправить данные на email владельца сайта или менеджера [email protected].

Тема письма должна быть понятной, а сообщение письма должно содержать то, что указал пользователь в HTML форме.

mail("[email protected]", "Заявка с сайта", "ФИО:".$fio.". E-mail: ".$email ,"From: [email protected] \r\n");

Необходимо добавить условие, которе проверит отправилась ли форма при помощи PHP на указанные адрес электронной почты.

if (mail("[email protected]", "Заказ с сайта", "ФИО:".$fio.". E-mail: ".$email ,"From: [email protected] \r\n"))
{
echo "сообщение успешно отправлено";
} else {
}

Таким образом программный код файла send.php, который отправит данные HTML формы на почту будет выглядеть следующим образом:

$fio = $_POST["fio"];
$email = $_POST["email"];
$fio = htmlspecialchars($fio);
$email = htmlspecialchars($email);
$fio = urldecode($fio);
$email = urldecode($email);
$fio = trim($fio);
$email = trim($email);
//echo $fio;
//echo "
";
//echo $email;
if (mail("[email protected]", "Заявка с сайта", "ФИО:".$fio.". E-mail: ".$email ,"From: [email protected] \r\n"))
{ echo "сообщение успешно отправлено";
} else {
echo "при отправке сообщения возникли ошибки";
}?>

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

Помещаем HTML и PHP код отправки формы в один файл

В комментариях к этой статье многие задают вопрос о том, как сделать, чтобы и HTML форма и PHP код отправки данных на почту находились в одном файле, а не двух.

Для реализации такой работы нужно поместить HTML код формы в файл send.php и добавить условие, которое будет проверять наличие переменных в массиве POST (этот массив передается из формы). То есть, если переменные в массиве не существуют, то нужно показать пользователю форму. Иначе нужно принять данные из массива и отправить их адресату.

Давайте посмотрим как изменить PHP код в файле send.php:



Форма заявки с сайта


//проверяем, существуют ли переменные в массиве POST
if(!isset($_POST["fio"]) and !isset($_POST["email"])){
?>





} else {
//показываем форму
$fio = $_POST["fio"];
$email = $_POST["email"];
$fio = htmlspecialchars($fio);
$email = htmlspecialchars($email);
$fio = urldecode($fio);
$email = urldecode($email);
$fio = trim($fio);
$email = trim($email);
if (mail("[email protected]", "Заявка с сайта", "ФИО:".$fio.". E-mail: ".$email ,"From: [email protected] \r\n")){
echo "Сообщение успешно отправлено";
} else {
echo "При отправке сообщения возникли ошибки";
}
}
?>

Существование переменной в POST массиве мы проверяем PHP функцией isset(). Восклицательный знак перед этой функцией в условии означает отрицание. То есть, если переменной не существует, то нужно показать нашу форму. Если бы я не поставил восклицательный знак, то условие дословно означало бы - "если существует, то показать форму". А это неправильно в нашем случае. Естественно, что вы можете переименовать его в index.php. Если будуту переименовывать файл, то не забудьте переименовать название файла и в строке

. Форма должна ссылаться на эту же страницу, например index.php. В код я добавил заголовок страницы.

Частые ошибки, возникающие при отправке PHP формы с сайта

Первая, наверное самая популярная ошибка, это когда вы видите пустую белую страницу без сообщений. Это означает, что вы допустили ошибку в коде страницы. Вам нужно включить отображение всех ошибок в PHP и тогда вы увидите, где допущена ошибка. Добавьте в код:

ini_set("display_errors","On");
error_reporting("E_ALL");

Файл send.php должен запускаться только на сервере, иначе код просто не будет работать. Желательно, чтобы это был не локальный сервер, так как он не всегда настроен на отправку данных на внешний почтовый сервер. Если вы запустите код не на сервере, то вам отобразиться код PHP прямо на странице.

Таким образом, для корректной работы я рекомендую поместить файл send.php на хостинг сайта. Там, как правило, все уже настроено.

Еще одна частая ошибка, когда появляется оповещение "Сообщение успешно отправлено", а письмо не приходит на почту. В этом случае нужно внимательно проверить строку:

if (mail("[email protected]", "Заказ с сайта", "ФИО:".$fio.". E-mail: ".$email ,"From: [email protected] \r\n"))

Вместо [email protected] должен быть email адрес на который нужно отправить письмо, а вместо [email protected] должен быть существующий email данного сайта. Например для сайта сайт это будет . Только в этом случае письмо с данными из формы будет отправлено.


Очень часто на сайтах возникает необходимость отправить письмо администартору или клиенту. Сделать это можно двумя способами: на стороне клиента и на стороне сервера.


Для отправки почты со стороны клиента достаточно в HTML-код страницы добавить ссылку "mailto:" с указанием необходимого адреса:


Написать вебмастеру

Когда пользователь кликает по ссылке, браузер запускает почтовый клиент по-умолчанию и помещает указанный адрес в поле "Кому", так что пользователю достаточно написать текст и отправить письмо. Этот способ никак не связан с PHP, но пользоваться им иногда стоит. Кроме того, это единственный способ вызвать почтовый клиент с сайта, не поддеживающего исполнение скриптов.

Нас же интересует второй способ - отправка почтовых сообщений средствами PHP. В общем-то, для этого в PHP предусмотреда единственная функция - mail() , но вот способов использования её несколько. Прототип функции mail() выглядит следующим образом:

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

При отправке почты необходимо указать как-минимум три параметра: получателя, тему и текст сообщения.

В качестве адреся получателя "to" можно указывать как отдельный адрес, так и целый список, разделённый запятыми. Отдельный адрес может задаваться в следующих форматах "адрес" или "имя <адрес>" :

[email protected] или Site Webmaster

Тема сообщение "subject" - это обычная строка. Единственное ограничение - строка не должна содержать символов перевода строки или возврата каретки ("\n" и "\r").

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

Кроме обязательных элементов можно указывать два дополнительных - расширенные заголовки и расширенные параметры. Расширенные заголовки служат для добавления к письму дополнительных аттрибутов и блоков, таких как адрес отправителя, адрес отправки копии ("cc" ), адрес отправки скрытой копии ("bcc" ) и т.д. Расширенные заголовки так же позволяют отправлять сообщения в HTML-формате.

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

Итак, минимальный скрипт отправки сообщения выглядит так:

Этот скрипт отправит письмо по указанному адресу, но в поле "от кого" будет указан скорее всего служебный адрес почтового сервера провайдера. Поэтому если вы захотите ответить на это письмо - ответ уйдёт в никуда. Чтобы корректно указать отправителя, воспользуемся расширенными заголовками:

// формируем расширенные заголовки $headers = "From: [email protected]" . "\r\n" . "Reply-To: [email protected]" . "\r\n" . "X-Mailer: PHP/" . phpversion();
mail($to, $subject, $message, $headers); ?>

Этот скрипт отправит клиенту письмо от имени почтового робота вашего сайта (заголовок "From:" ). Дополнительно, применив заголовок "Reply-To:" , мы указали почтовой программе клиента, что ответы надо пересылать не почтовому роботу, а вебмастеру по указанному адресу. Третий фрагмент ("X-Mailer" ) не является обязательным и описывает программу, с помощью которой было отправлено сообщение. Согласно почтового протокола, разработчик может при необходимости добавлять собственные расширенные заголовки. Единственное ограничение - имена таких заголовков должны начинаться с "X- ".

По-умолчанию, функция mail() отправляет сообщения в текстовом виде. Это означает, что если вы в текст добавите HTML-теги, то они будут восприняты как обычный текст без гипертекстовой разметки. Для того, чтобы отправить HTML-сообщение, снова воспользуемся расширенными заголовками:

// список получателей $to = "[email protected], [email protected]";

// Тема сообщения
$subject = "Новости сайта";

// Сообщение в виде HTML-формате
$message = "


Новости сайта


Новости на сегодня:











НомерСодержание АвторОпубликовано
1первая новость Администраторвчера
2вторая новость Администраторсегодня



";

// Указываем правильный MIME-тип сообщения:
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type: text/html; charset=iso-8859-1" . "\r\n";

// Добавляем необходимые заголовки
$headers .= "To: Клиент №1 , ". "Клиент №2 " . "\r\n";
$headers .= "From: News Robot " . "\r\n";
$headers .= "Cc: News Archive $headers .= "Bcc: [email protected]" . "\r\n";

// Отправляем сообщение
mail($to, $subject, $message, $headers);
?>

Этот скрипт отправит письмо в HTML-формате двум получателям, а так же вышлет копии в архив и в контрольный ящик.

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

Второй способ чаще всего используется, когда скрипт необходимо выполнять периодически (например, ежедневная рассылка новостей). Организация планирования выполнения задачи средствами PHP - задача нетривиальная. Более простой путь - воспользоваться готовыми интсрументами, например crontab. Этот инструмент доступен на большинстве платных Unix-хостингов. Более подробно мы рассмотрим crontab в отдельном уроке.

Дополнительно можно отметить, что попробовать отправку почты с вашего локального сервера у вас не получится. В большинстве случаев в целях безопасности функции почты не настроены и их надо прописать вручную. Указать параметры можно либо в файле php.ini, либо непосредственно в коде перед вызовом функции mail() :

// в php.ini SMTP = localhost sptp_port = 25 // в коде ini_set("SMTP", "localhost"); ini_set("smtp_port", "25");

Кроме того, настоятельно рекомендую поставить локальный SMTP-сервер, например, PersonalSMTP. Эта утилита распространяется бесплатно, проста в установке и настройке, но при этом позволяет отлаживать отправку писем даже при отсутствии подключения к Интернет. При использовании PersonalSMTP в конфигурации по-умолчанию используется сервер "localhost" и порт 15025, следовательно перед вызовом функции mail() необходимо добавить строки:

// не забудьте закомментировать их // перед публикацией скрипта на сайте. ini_set("SMTP", "localhost"); ini_set("smtp_port", "15025");

Для работы с электронной почтой уже создано множество классов, поэтому вам нет острой нужды писать весь код самостоятельно. Достаточно посетить соответствующий сайт и скачать одну из бесплатных библиотек, например libmail2008.