Простой скрипт email рассылки.

27.01.2010 Рубрика: Обучение \ PHP

рассылка писем

Не так давно понадобилось написать небольшой скрипт для собcтвенных нужд. О нём сегодня мы и поговорим. Язык программирования — PHP. Приступим.

Постановка задачи и выбор методов её решения

Задача: написать максимально быстро и просто скрипт для отправки e-mail сообщения на n-ное количество адресов. Дело в том, что иногда нужно послать письмо нескольким адресатам, но так, чтобы они друг о друге не знали. То есть, исключаем тупое копирование всех адресов через запятую в поле «Кому».

автор

Автор: Алексей Опанасенко

Алексей Опанасенко живёт на севере Украины в древнем городе Чернигове. Типичный вебмастер самоучка – занялся самообучением, бросил работу в офисе и стал работать в Сети. Сейчас занимается веб разработками на заказ и своими личными проектами. В очередной раз доказывает, что научиться делать сайты с нуля и без учителей МОЖНО.

Сайт: http://neverlex.com – «Заметки вебмастера самоучки»

Скачать исходный код себе на компьютер!

Язык программирования — PHP.

Приступим.

Почему PHP? Да потому что на PHP это сделать очень просто и он стоит на любом хостинге (платном конечно). Тем более, скрипт не нужно хранить на компьютере, а лучше залить на сервер и пользоваться откуда угодно. Даже с мобильника.

Если говорить более простым языком, мы пишем небольшой скрипт e-mail рассылки. Сразу же в голове рождается представление работы скрипта.

У нас есть форма с полями:

Кому (список получателей)

Тема сообщения

Текст сообщения

Адрес отправителя (выбор из перечня)

Схема работы: Вводим данные и нажимаем «Отправить» → происходит отправка писем → получаем отчёт.

Есть также пару особенностей. Для отправки писем желательно использовать небольшой тайм-аут, чтобы наш сервер не посчитали спаммером. Отчёт желательно записать в небольшой текстовый файл. Нужно защитить скрипт от несанкционированного использования.

Пишем скрипт

Здесь я не буду описывать процесс написания, а просто приведу максимально откомментированный код.

<?php
  // Устанавливает лимит времени исполнения для этого файла (связано с тайм-аутом)
	set_time_limit (1200);
  // Адреса отправителя
	$mail1="Ваше имя 1 <your1@email.com>";
	$mail1="Ваше имя 2 <your2@email.com>";
	$mail1="Ваше имя 3 <your3@email.com>";

  // Обрабатываем адреса для отображения в форме
	$tmail1=htmlspecialchars($mail1);
	$tmail2=htmlspecialchars($mail2);
	$tmail3=htmlspecialchars($mail3);

  // Далее идёт сам скрипт
  // Если массив POST не пустой, отправка состоялась
	if (!empty($_POST) && !isset($sent)) {

// Определяем переменные
	$emailer_subj = $_POST['emailer_subj'];
	$emailer_mails = $_POST['emailer_mails'];
	$emailer_text = $_POST['emailer_text'];
	$emailer_yourmail = $_POST['emailer_yourmail'];

    // Теперь проверяем заполнение всех полей
	if (empty($emailer_subj) || $emailer_subj=="Тема письма") {
    // Если тема пустая...
    $mail_msg='<b>Вы не ввели тему письма</b>';
  } elseif (empty($emailer_mails) || $emailer_mails=="Почтовые адрсе") {
    // Если адресов нет...
    $mail_msg='<b>Не указано адреса получателей</b>';
  } elseif (empty($emailer_text) || $emailer_text=="Текст письма") {
    // Если сообщение пустое...
    $mail_msg='<b>Вы не ввели текст письма</b>';
  } else { // Если все поля заполнены верно...
    // Готовим сообщение об успешной отправке... Вдруг у вас какой-то необычный браузер
    $mail_msg='Ваше сообщение отправлено.<br>Нажмите <a href="'.$_SERVER['REQUEST_URI'].'">здесь</a>, если ваш браузер не поддерживает перенаправление.';
    // Готовим заголовки письма... Будем отправлять письма в формате HTML и кодировке UTF-8
    $headers="MIME-Version: 1.0\r\n";
    $headers.="Content-type: text/html; charset=utf-8\r\n";
    $headers.="From: $emailer_yourmail";

	// Обработка письма. Нужно удалить лишние пробелы и проставить переносы.
	$emailer_text=preg_replace("/ +/"," ",$emailer_text); // множественные пробелы заменяются на одинарные
	$emailer_text=preg_replace("/(\r\n){3,}/","\r\n\r\n",$emailer_text); // убираем лишние переносы (больше 1 строки)
	$emailer_text=str_replace("\r\n","<br>",$emailer_text); // ставим переносы

	// Получаем массив адресов. В качестве разделителя у нас используется запятая.
	$emails=explode(",", $emailer_mails);
	$count_emails = count($emails); // Подсчёт количества адресов
	// Запускаем цикл отправки сообщений
    for ($i=0; $i<=$count_emails-1; $i++) // Отчёт начинается в массиве с нуля, поэтому уменьшаем сумму на единицу
    {
    // Подставляем адреса получаетелей и обрезаем пробелы с обоих сторон, если таковые имеются
    $email=trim($emails[$i]);
    // Отправляем письмо и готовим отчёт по отправке
	if($emails[$i]!="") { // Проверка на случай попадения в массив пустого значения
    if(mail($email,$emailer_subj,$emailer_text,$headers)) $report.="<li><span style=\"color:green;\">Отправлено: ".$emails[$i]."</span></li>"; else $report.="<li><span style=\"color:red;\">Не отправлено: ".$emails[$i]."<span></li>";
	sleep(5); // Делаем тайм-аут в 5 секунд
	}
    }

	// Запись отчёта в файл. Файл будет сгенерирован в той же папке, под названием log.txt. Проверьте настройку прав папки.
	$log=fopen("log.txt","w");
	fwrite($log,$report);
	fclose($log);
    // Переменная $sent – признак успешной отправки
    $sent=1;
  }
} else { // Если в массиве POST пусто, форма еще не передавалась
  // Готовим приглашение
  $mail_msg='Все поля обязательны для заполнения.';
  // Поля темы, адресов получаетелей и получателей, и текста в этом случае должны быть пустыми
  $emailer_text=$emailer_subj=$emailer_mails=$emailer_yourmail='';
}

  // Если $sent не существует, выводим форму или отчёт
	if (!isset($sent)) {
  // Если сообщение уже отправлено - выводим отчёт
    if(isset($_GET['messent']))
	{echo $text.="<b style=\"text-align:center;margin-top:200px;display:block;\">Всё окей. Сообщение отправлено. <a href=\"emailer.php\">Ещё?</a><br><br><u>Отчёт:</u></b> <ol style=\"display:block;width:300px;margin:10px auto;\">";
	readfile("log.txt");
	echo"</ol>";}
	else {
  // Или выводим форму, если сообщение ещё не отправлено
    echo $text.=<<<post
    <script type="text/javascript">
    function form_validator(form) {
    if (form.emailer_subj.value=='' || form.emailer_subj.value=='Тема письма') { alert('Укажите тему письма.'); form.emailer_subj.focus(); return false; }
    if (form.emailer_mails.value=='' || form.emailer_mails.value=='Почтовые адреса') { alert('Укажите адреса получаталей.'); form.emailer_mails.focus(); return false; }
    if (form.emailer_text.value=='' || form.emailer_text.value=='Текст письма') { alert('Вы не заполнили поле сообщения.'); form.emailer_text.focus(); return false; }
    return true;
    }
    </script>
	<style type="text/css">
	form {display:block;margin:20px auto;width:500px;}
	textarea, input, select {width:100%; margin:5px 0;}
	textarea {height:200px;}
	.red {color:#a00;}
	</style>
    <form method="post" onsubmit="return form_validator(this);">
	<p class="red">$mail_msg</p>
	<input type="text" name="emailer_subj" id="emailer_subj" value="Тема письма" title="По какому поводу пишем?" onfocus="if (this.value=='Тема письма') this.value='';" onblur="if (this.value=='') this.value='Тема письма';">
	<textarea name="emailer_mails" id="emailer_mails" title="Кто получатели?" onfocus="if (this.value=='Почтовые адреса') this.value='';" onblur="if (this.value=='') this.value='Почтовые адреса';">Почтовые адреса</textarea>
	<textarea name="emailer_text" id="emailer_text" title="Что пишем?" onfocus="if (this.value=='Текст письма') this.value='';" onblur="if (this.value=='') this.value='Текст письма';">Текст письма</textarea>
	<select name="emailer_yourmail">
	<option value="$mail1">$tmail1</option>
	<option value="$mail2">$tmail2</option>
	<option value="$mail3">$tmail3</option>
	</select>
	<input type="submit" value="Отправить" title="Отправить мыл">
	</form>
post;
}
}
else { // А если существует...
  // Посылаем в заголовке редирект (303 Refresh) на этот же адрес с дополнительным параметром messent
  $ret_uri=$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  header("Refresh: 0; URL=http://".$ret_uri."?messent");
  exit;
}

?>

Защита скрипта

Создайте папку, где будет находиться скрипт, и положите туда файл .htaccess, с таким содержанием. Эти пару строк ограничат доступ по IP адресу.

Order Deny,Allow
Deny from all
Allow from ваш IP

Или, если у вас не постоянный IP адрес, можно добавить пароль.

if (!isset($_SERVER['PHP_AUTH_USER'])) {
// посылаем браузеру запрос логина/пароля
header("WWW-Authenticate: Basic realm=\"Enter login and password\"");
header("HTTP/1.0 401 Unauthorized");
exit;
} else {
if($_SERVER['PHP_AUTH_USER']!=='Ваш логин' && $_SERVER['PHP_AUTH_PW']!=='Ваш пароль')
{
header("WWW-Authenticate: Basic realm=\"Enter login and password\"");
header("HTTP/1.0 401 Unauthorized");
exit('Введён неверный логин или пароль');
}
else {
//Сюда нужно вставить тело скрипта
}

Доработка скрипта

Конечно, можно бесконечно дорабатывать этот скрипт, ведь решение написано «на коленке», однако свою функцию он выполняет. Неоднократно пользовался им и сбоев не было.

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

Можно вставить себя последним в списке, чтобы проконтролировать отправку. Вдруг что с файлом случится :)

Надеюсь, эта статья поможет вам в освоении языка программирования PHP.

Автор: Алексей Опанасенко

Редакция: Рог Виктор и Андрей Бернацкий. Команда webformyself.

E-mail: contact@webformyself.com

Проект webformyself.com – Как создать свой сайт. Основы самостоятельного сайтостроения

P.S. Хотите опубликовать интересный тематический материал и заработать? Если ответ «Да», то жмите сюда.

Подписаться Поделиться

Метки: , ,

Комментарии (22)

  1. Елена

    Здравствуйте, Андрей и Виктор! Материал замечательный и очень актуальный. Обязательно попробую, но только не сегодня. Мои дипломники вышли на финишную прямую – идет работа над ошибками, удовлетворение капизов руководителей дипломов, подготовка докладов, рецензий, аннотаций и т.д. и т.п.Передайте, пожалуйста, мой восторг автору – Алексею Опанасенко.С уважением, Елена Владиславовна, kiselevaev2009@mail.ru

    Нравится или не нравится: Thumb up 0 Thumb down 0

  2. Василий

    Очень нужный скрипт-однако!Ещё бы прояснили «чайнику»-подробнее-как пользоваться им( можно -ли загружать этот код хостеру или это только пример;в какую папку на хостинге заливать и как отправлять им письма?)Спасибо!

    Нравится или не нравится: Thumb up 0 Thumb down 0

  3. Dan

    И правда,напишите куда вставлять

    Нравится или не нравится: Thumb up 0 Thumb down 0

    • RohViktor

      Все очень просто.

      1. Делаем файл к примеру emailer.php, где кодом будет весь код из данной статьи.

      2. Закачиваем на свой хостинг в папку www/

      3. потом пшем в строке браузера http://www.доменное_имя.ru/emailer.php и пользуемся.

      Вот и все. Главное залить на сервер!

      Нравится или не нравится: Thumb up 1 Thumb down 0

      • Never Lex

        Спасибо, Виктор, за ответ.

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

        Нравится или не нравится: Thumb up 2 Thumb down 0

  4. Алексей

    Интересно – даже не предполагал о такой возможности

    Нравится или не нравится: Thumb up 0 Thumb down 0

  5. Slava

    А у меня сервер не разрешает выполнение скрипта. Что делать?

    Нравится или не нравится: Thumb up 0 Thumb down 0

  6. Менеджер

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

    Нравится или не нравится: Thumb up 0 Thumb down 0

  7. Константин

    Скрипт, приведенный в статье, в основном годится качестве учебного примера. Его можно безбоязненно использовать для отправки максимум одного-двух десятков сообщений. Если хотите отправлять больше, то обязательно нужно заранее спросить у хостера, на чьем сервере будет размещен скрипт, какие ограничения накладываются на отправку писем. Обычно на shared хостингах пользователю разрешается посылать не больше нескольких сотен или даже десятков писем в день, бывают и более строгие ограничения (напр., на отправку в течение часа).

    Еще один базовый недостаток скрипта: значение, возвращаемое функцией mail(), позволяет узнать, было ли письмо поставлено в очередь на отправку или нет. Невозможно узнать не только было ли оно доставлено (а если нет, то почему), но даже предпринимались ли вообще попытки доставки. Чтобы получить эту информацию, нужно непосредственно взаимодействовать с SMTP-сервером. Это обычно делается с помощью готовых библиотек, например PEAR::Net_SMTP. В этом случае можно получить идентификатор сообщения, а затем, анализируя логи сервера и письма, приходящие на адрес, указанный в хедере Return-path, определить результат его доставки.

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

    Нравится или не нравится: Thumb up 0 Thumb down 0

    • Vlad

      Дело в том, что на UniSender нужно подтверждать почтовые адреса – что это не спам!!! Кто знает сервисы рассылки – где можно загружать любые почтовые адреса без ограничений???

      Нравится или не нравится: Thumb up 0 Thumb down 0

  8. Never Lex

    Константин, конечно. По учебность примера писалось и в само статье :) Но отправлять несколько писем тоже можно.

    Нравится или не нравится: Thumb up 1 Thumb down 0

  9. astrov

    Отличный скрипт, мне нравится, а качества рассылки добиваюсь как здесь http://www.eco-money.ru/forum/topic?id=45, взял там шаблон и просто его немного переделал, очень крутой шаблон.

    Нравится или не нравится: Thumb up 0 Thumb down 0

  10. Сергей

    Добрый день!
    Спасибо скрипт отличный!
    Но подскажите что изменить что-бы в приходящем письме не отображался весь список е-mail адресов ( в поле кому в полученном письме)

    Нравится или не нравится: Thumb up 0 Thumb down 0

    • Never Lex

      Вы уверены, что пользовались скриптом, указанным в статье?
      Этот скрипт как раз решает данную проблему. В поле «кому» должен быть только 1 адрес. Или может вы не разделяете адреса запятой? Тогда вообще не понятно как письмо приходит.

      Нравится или не нравится: Thumb up 1 Thumb down 0

  11. Сергей

    Да спасибо! заработало!

    Нравится или не нравится: Thumb up 0 Thumb down 0

  12. Игорь

    Отличный скрипт! Еслибы еще кто нибудь подсказал хостинг на котором можно его разместить, а то хостеры сразу блокируют аккаунт ((, Подскажите кто нибудь такой безотказный хостинг, буду примного благодарен!!! Заранее всем спасибо!

    Нравится или не нравится: Thumb up 0 Thumb down 0

  13. Олег

    Обрабатываем адреса для отображения в форме
    010. $tmail1=htmlspecialchars($mail1);
    011. $tmail2=htmlspecialchars($mail2);
    012. $tmail3=htmlspecialchars($mail3); Не пойму, что сюда нужно поставить(Е-мейл, адрес сайтаЮ страницы) все время выдает ошибку:
    Parse error: syntax error, unexpected ‘:’ in /home/krim124/data/www/evpatoria-kurort.com.ua/cod/emailer.php on line 9

    Нравится или не нравится: Thumb up 0 Thumb down 0

    • Andrey Bernacki

      Так у вас ругается на 9-ую строку. А не на 10, 11, или 12 как вы показали. Причем ругается на символ «:» . Проверьте 9-ую строку еще разок. Если что, такие вопросы на e-mail.

      Нравится или не нравится: Thumb up 0 Thumb down 0

  14. max

    Всё Ок работает, но:

    1. Та часть кода, где устанавливается таймаут, либо там ошибка, либо у меня на хостинге ограничения. Просто убрал эту часть кода.

    2. Когда пишешь текст сообщения на русском языке, на мыло отправителя приходят кракозябры, писать нужно на ангельском или транслите, тогда всё ОК. Как писать на русском?

    Нравится или не нравится: Thumb up 0 Thumb down 0

  15. max

    По второму вопросу всё решил, поменял кодировку.
    Также переписал код, что бы не выбирать адреса отправителей со списка, а вписываем какой желаем)
    Отличный код для знакомства и экспериментов с PHP)

    Нравится или не нравится: Thumb up 0 Thumb down 0

    • Шахин

      «Также переписал код, что бы не выбирать адреса отправителей со списка, а вписываем какой желаем» интересный вариант. не подскажите как это сделали? в смысле какой код написали

      Нравится или не нравится: Thumb up 0 Thumb down 0

  16. Виталий

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

    Нравится или не нравится: Thumb up 0 Thumb down 0

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

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

*

Я не робот.

Spam Protection by WP-SpamFree