Как отправить письмо php
Перейти к содержимому

Как отправить письмо php

  • автор:

Отправка писем на PHP через SMTP

Отправлять письма через PHP намного проще, чем кажется. Всего-то надо сформировать правильный EML, подключиться к SMTP и отправить письмо. Ну ещё может быть, хотя и не факт, надо где-то как-то залогировать отправку, а то потом потеряют письмо, скажут, что и не было никаких писем. И виноватый опять ты, хотя ты бел и пушист. А ещё бы хорошо сделать хоть какую-то обработку ошибок, а то вдруг эксепшин, или серевер устал, или коннект не пошёл, а тут суперважный клиент. И уж совсем замечательно хранить где-то письма на случай «я потеряль», «мне не дошло», «а вышлите мне ещё раз». А ещё мы хотим отправлять письма на сайте, который видел расцвет динозавров. А ещё. мне кажется, что список ещё может расширяться не хуже нашей вселенной.

Для решения всех этих проблем я решил написать небольшой инструмент — ApMailer.

ApMailer

ApMailer — это небольшая библиотека, единственной целью которой является отправка почты. Я постарался сделать её максимально простой и удобной. Вы можете скачать всего один файл и отправлять письма и из консоли, и из web-скриптов!

Подключение ApMailer

Скачайте из репозитория файл mailer.phar или src/lib.php (если не нужна консольная версия). После этого подключите lib.php:

// Если скачали phar include 'phar:///path/to/mailer.phar/lib.php'; // Если скачали исходный код include '/path/to/lib.php';

После этого будет доступна функция Mailer() :

Mailer()->init(include 'config.php'); $message = Mailer()->newHtmlMessage(); $message->setSubject($messageSubject); $message->setSenderEmail($messageFrom); $message->addRecipient($messageTo); $message->addContent(file_get_contents('mail-header.html')); $message->addContent($messageText); $message->addContent(file_get_contents('mail-footer.html')); $message->addRelatedFile('signature.png'); if (isset($_FILES['attachment']['size']) && $_FILES['attachment']['size'] > 0) < $message->addAttachmentFile( $_FILES['attachment']['tmp_name'], $_FILES['attachment']['name'], $_FILES['attachment']['type'] ); > Mailer()->sendMessage($message);

Инициализация

Перед отправкой писем Mailer надо проинициализировать. Делается это так:

Mailer()->init($config);

Конфиг представляет из себя многомерный массив, в котором указываются адрес отправителя по умолчанию, хуки для обработки ошибок и ведения логов и транспортёры:

$config = [ 'defaultFrom' => 'mymail@example.org', 'onError' => function($error, $message, $transport) < echo $error; >, 'afterSend' => function($text, $message, $layer) < echo $text; >, 'transports' => [ // Сохранение всех писем в папке ['file', 'dir' => __DIR__ .'/mails'], // Отправка писем через Yandex, используя SSL и авторизацию ['smtp', 'host' => 'smtp.yandex.ru', 'ssl' => true, 'port' => '465', 'login' => '****@yandex.ru', 'password' => '******'], ], ];

В качестве транспортов можно использовать file и smtp . Тип транспорёта всегда должен передаваться первым элементом массива, дальше идут его настройки.

Транспортёр file сохраняет письмо в виде EML в папку. Доступны следующие настройки:

  • dir — папка, а которую будут сохраняться письма. Если предполагается много писем, лучше хранить их с разбивкой по дате ‘dir’ => strftime( ‘/path/to/mails/%Y/%m/%d’ )

Транспортёр smtp отправляет письмо через SMTP. Доступны следующие настройки:

  • host — адрес SMTP-сервера
  • ssl — использовать SSL при подключении (обязательно для google, yandex и других популярных сервисов)
  • port — порт подключения (обычно 25 для подключения без SSL и 465 для подклюения с SSL)
  • login — логин для авторизации (если логин не указан, то используется подключение без авторизации)
  • password — пароль для авторизации (не используется, если логин не указан)
  • onError — срабатывает на ошибку транспортёра (удобно делать лог ошибок отправки писем)
  • afterSend — срабатывает после отправки письма (удобно делать общий лог отправки писем)

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

Рабочий пример

В качестве примера я сделал форму отправки письма:

Форма отправки письма

Пример письма

Отправка почты на старых версиях PHP

Поскольку библиотека умеет работать через консоль, то можно формировать команду, которая сможет отправлять письма. Единственное, что нужно, наличие скомпилированного бинарника PHP 5.6.

function sendMail($message) < $keys = array( 'subject' => '-s', 'from' => '-f', 'text' => '-t', 'reciient' => array('-r'), 'to' => array('-r'), 'related' => array('-i'), 'attachment' => array('-a'), 'config' => array('-c'), ); $args = array(); // Если отправляют HTML if (isset($message['html'])) < $args[] = '--html'; // Подключаем шаблон $textArray = array(); // Header $textArray[] = ''; if (isset($message['html'])) < $textArray[] = join((array) $message['html']); > // Footer $textArray[] = ''; $message['text'] = join($textArray); > foreach ($keys as $key => $argument) < if (!isset($message[$key])) < continue; > if (is_array($argument)) < $argument = array_shift($argument); foreach ((array) $message[$key] as $value) < $args[] = $argument .' '. escapeshellarg($value); > > else < $args[] = $argument .' '. escapeshellarg($message[$key]); > > $command = 'php5.6 /path/to/mailer.phar '. join(' ', $args); exec($command); >;

А дальше уже можно отправлять письма:

sendMail(array( 'to' => array('someone@exmaple.org', 'someoneelse@exmaple.org'), 'subject' => 'Привет, мир!', 'html' => '

Hello

'
, ));

Отправка письма средствами PHP

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

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

Адрес электронной почты получателя — это ваш электронный адрес, уж его вы знаете.

Тема письма — можем придумать сами. Проявите фантазию.

Само письмо — в принципе мы можем использовать тот же текст, который выводился в сценарии report.php. Только его нужно отформатировать немного, чтобы получить нужную строку. Ведь, как вы помните, в сценарии мы выводили текст в отдельных строках при помощи команды echo с использованием тега для красивого вывода на html-странице.

 echo 'Спасибо за заполнение формы.
'; echo 'Кота похитили ' . $when . '
'; echo 'Похитители: ' . $description . '
'; echo 'Ваш email: ' . $email;

Создадим новую переменную $msg, которая будет содержать текст письма:

 $msg = 'Спасибо за заполнение формы.'. 'Кота похитили ' . $when . 'Похитители: ' . $description . 'Ваш email: ' . $email; 

Мы создали достаточно длинную строку, соединив отдельные части с помощью оператора конкатенации (точки). Если вывести текст, содержащий в новой переменной через команду echo $msg; на той странице с сценарием, то получим приблизительно следующее:

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

Так как письмо — это обычный текст, то здесь нельзя использовать HTML-тег . Для перевода текста на новую строку используется символ новой строки в форме Escape-последовательности ‘\n’.

Попробуем переделать пример:

 $msg = 'Спасибо за заполнение формы.\n'. 'Кота похитили ' . $when . '\n'. 'Похитители: ' . $description . '\n'. 'Ваш email: ' . $email; 

Снова выводим результат с помощью echo $msg; и смотрим:

Вместо переноса строк мы видим \n как обычный текст, который затесался между нашими словами для письма. Фигня какая-то.

Проблема заключается в том, что PHP по разному обрабатывает строки, заключённые в одинарные или двойные кавычки. В нашем случае, что перенос строк заработал, необходимо использовать двойные кавычки. Попробуем:

 $msg = "Спасибо за заполнение формы.\n". "Кота похитили $when\n". "Похитители: $description\n". "Ваш email: $email"; echo $msg; 

Мы видим, что символы \n исчезли, но текст всё равно выводится в одну строку. Однако, если вы откроете исходный код страницы, то увидите, что на самом деле текст разбит на отдельные строки. Но браузер игнорирует подобные переносы, поэтому мы не замечаем эффекта переноса строк. Если бы мы выводили строку в текстовый документ, то всё бы работало, как мы хотели. В письме переносы также будут работать.

Обратите внимание на следующую особенность. В примере с двойными кавычками мы вставляли имена переменных прямо в текст без обрамляющий кавычек. PHP самостоятельно подставляет значения переменных в текст. Это очень удобно. Здесь важно понимать разницу между одинарными и двойными кавычками в PHP-коде. Данное объяснение выходит за рамки изучаемого урока.

У нас есть все необходимые компоненты для отправки письма. Осталось скомпоновать в одно целое. Создадим отдельные переменные для каждого элемента письма:

 $email = $_POST['email']; // от кого $to /cdn-cgi/l/email-protection" data-cfemail="5c3f34293f371c32332e2e352f723f3331">[email protected]"; // кому $subject = "Вам письмо"; // тема письма $msg = "Спасибо за заполнение формы.\n". "Кота похитили $when\n". "Похитители: $description\n". "Ваш email: $email"; 

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

 mail($to, $subject, $msg); 

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

 mail($to, $subject, $msg, 'From: ' . $email); 

Мы соединили слово From: с адресом почты через точку (оператор конкатенации) и получили четвёртый параметр для функции.

Если вы хотите также отправить копию и скрытую копию, то следует добавить нужные элементы («Cc: » или «Bcc: «) в четвёртом параметре, отделяя элементы комбинацией символов возврата каретки и новой строки, например так:

 "From: " . $from . "\r\nCc: " . $cc 

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

Вторая проблема связана с русским языком. Исторически сложилось, что некоторые служебные заголовки при отправке писем используют устаревшие кодировки. И если вы будете проверять поступившую почту у себя на компьютере, то можете увидеть кракозябры в теме письма, в сообщении, в обратном адресе. Некоторые почтовые сервера умеют частично определять и конвертировать на лету неправильную кодировку. А если вы привыкли читать почту через почтовые клиенты, то эта проблема может проявиться особенно отчётливо.

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

 $subject = "=?utf-8?B?" . base64_encode("здесь тема вашего письма") . "? From: $email\r\nReply-To: $email\r\nReturn-Path: $email\r\nContent-Type: text/plain; charset=utf-8\r\nContent-Transfer-Encoding: 8bit"); 

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

PHP отправка письма

PHP отправка письма

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

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

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

Мы не будем здесь рассматривать отправку письма с вложением, нас интересует только отчет о поступившем сообщении с сайта. Для того чтобы отправить письмо нам нужно три параметра, а именно: отправитель, получатель и сам текст письма. Тело письма мы будем отправлять в HTML разметки. Чтобы почтовый сервер понимал, что мы хотим в теле письма отправить HTML нужно указать Content-type в заголовках почтового сервера.

Пишем скрипт php отправки письма.
 '); //Адрес почты от кого отправляем define('KAS_MAIL_AUTOR','Робот доставки '); /**Отпровляем сообщение на почту * @param string $to - Кому * @param string $from - От кого * @param string $title - Заголовок письма * @param string $message - Тело письма */ function sendMail($to, $from, $title, $message) < //Формируем заголовок письма $subject = $title; $subject = '=?utf-8?b?'. base64_encode($subject) .'?='; /*Формируем заголовки для почтового сервера, Говорим серверу что используем HTML*/ $headers = "Content-type: text/html; charset=\"utf-8\"\r\n"; $headers .= "From: ". $from ."\r\n"; $headers .= "MIME-Version: 1.0\r\n"; $headers .= "Date: ". date('D, d M Y h:i:s O') ."\r\n"; //Отправляем данные на ящик if(!mail($to, $subject, $message, $headers)) return 'Ошибка отправки письма!'; else return true; >//Формируем заголовок письма $title = 'Ура нам письмо пришло!'; //Формируем HTML верстку письма для отправки $msg = '

Ура нам письмо пришло!


Это письмо создано автоматически, отвечать на него не нужно!

'; //Вызываем функцию отправки письма if(sendMail(KAS_MAIL_TO, KAS_MAIL_AUTOR, $title, $msg)) echo 'Письмо отправленно. ' ?>

Вот такой простой скрипт php отправки письма. Вам нужно вызывать данную функцию в обработчике вашей формы в случае если форма прошла валидацию.

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

Работая над проектом, мне пришлось создать специфичную «анкету соискателя» в котором надо была отправлять всю анкету на указные за ране e-mail адрес, и я сразу же вспомнил про PHP функцию mail().

bool mail ( string to, string subject, string message [, string additional_headers [, string additional_parameters]]) 
  • E-mail получателя
  • Заголовок письма
  • Текст письма
  • Дополнительные заголовки письма
  • Дополнительные параметры командной строки
  • true, если письмо было принято к доставке
  • false, в противном случае.
Простейший пример
Перейдем к более сложному примеру
Текст письма


1-ая строчка
2-ая строчка
'; $headers = "Content-type: text/html; charset=windows-1251 \r\n"; $headers . ; $headers .= "Reply-To: reply-to@example.com\r\n"; mail($to, $subject, $message, $headers); ?>

В начале мы определяем кому адресовано письмо, за это отвечает переменная &to, если же получателей несколько человек, то записываем через запятую адреса эл. почты.

Переменные $subject и $message, не буду описывать, это и так понятно.

  • В первой строчке ми определяем ты отправляемого письма-HTML и кодировку windows-1251.
  • В 2-ом мы указываем от кого пришло письмо.
  • В 3-ем указываем e-mail адрес, для ответа на письмо.
А теперь самое интересное отправка письма c вложением (attachment)
$subject = "тема письма"; $message ="Текст сообщения"; // текст сообщения, здесь вы можете вставлять таблицы, рисунки, заголовки, оформление цветом и т.п. $filename = "file.doc"; // название файла $filepath = "files/file.doc"; // месторасположение файла //исьмо с вложением состоит из нескольких частей, которые разделяются разделителем $boundary = "--".md5(uniqid(time())); // генерируем разделитель $mailheaders = "MIME-Version: 1.0;\r\n"; $mailheaders .="Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n"; // разделитель указывается в заголовке в параметре boundary $mailheaders . ; $mailheaders .= "Reply-To: $user_email\r\n"; $multipart = "--$boundary\r\n"; $multipart .= "Content-Type: text/html; charset=windows-1251\r\n"; $multipart .= "Content-Transfer-Encoding: base64\r\n"; $multipart .= \r\n; $multipart .= chunk_split(base64_encode(iconv("utf8", "windows-1251", $message))); // первая часть само сообщение // Закачиваем файл $fp = fopen($filepath,"r"); if (!$fp) < print "Не удается открыть файл22"; exit(); >$file = fread($fp, filesize($filepath)); fclose($fp); // чтение файла $message_part = "\r\n--$boundary\r\n"; $message_part .= "Content-Type: application/octet-stream; name=\"$filename\"\r\n"; $message_part .= "Content-Transfer-Encoding: base64\r\n"; $message_part .= "Content-Disposition: attachment; filename=\"$filename\"\r\n"; $message_part .= \r\n; $message_part .= chunk_split(base64_encode($file)); $message_part .= "\r\n--$boundary--\r\n"; // второй частью прикрепляем файл, можно прикрепить два и более файла $multipart .= $message_part; mail($to,$subject,$multipart,$mailheaders); // отправляем письмо //удаляем файлы через 60 сек. if (time_nanosleep(5, 0)) < unlink($filepath); >// удаление файла 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *