Квартиры, дома, земельные участки Краснодарского края без посредников. Объявления собственников недвижимости.
Реклама здесь
Главная
Примеры PHP Примеры JavaScript Примеры Ajax Примеры CSS,HTML

Отправка почты по шаблону минуя SMTP-сервер провайдера на PHP

Пример по созданию и отправке письма на основании активного шаблона письма минуя SMTP-сервер провайдера.


<?php
// Посылка почты вручную, минуя SMTP-сервер провайдера.
include_once "lib/getmxrr.php";
include_once 
"lib/template.php";
include_once 
"lib/mailenc.php";
include_once 
"lib/mailx.php";
include_once 
"lib/socketmail.php";

$mail template("mail.php.eml", array(
  
"to"   => "Кто-то очень страшный <somebody@thematrix.com>",
  
"text" => "Проверка слуха!"
));
$mail mailenc($mail);
mailx_manual($mail$reason)
  or die(
"Errors:<br>".join("<br>"$reason));
echo 
"Почта отослана.";
?>
Скопировать в буфер

lib/getmxrr.php - эмуляция функции getmxrr(), которая не работает на Windows хостинге

<?php
if (!function_exists("getmxrr")) {
  function 
getmxrr($hostname, &$hosts, &$weights=false) {
    
$hosts $weights = array();
    
// Не идеальный способ, но работающий: используется внешняя
    // программа nslookup, доступная в WIndows NT/2000/XP/2003.
    
exec("nslookup -type=mx $hostname"$result);
    
// Построчно перебираем ответ утилиты.
    
foreach ($result as $line) {
      
// Выделяем имя почтового сервера.
      
if (preg_match('/mail\s+exchanger\s*=\s*(\S+)/'$line$pock)) {
        
$hosts[] = $pock[1];
        
// Также выделяем вес.
        
if (preg_match("/MX\s+preference\s*=\s*(\d+)/"$line$pock))
          
$weights[] = $pock[1];
        else
          
$weights[] = 0;
      }
    }
    return 
count($hosts) > 0;
  }
}
// В PHP5 появился синоним для getmxrr() - его мы тоже эмулируем.
if (!function_exists("dns_get_mx")) {
  function 
dns_get_mx($hostname, &$hosts, &$weights) {
    return 
getmxrr($hostname$hosts$weights);
  }
}
?>
Скопировать в буфер

lib/template.php - Обработка шаблона.

<?php
// Функция делает то же самое, что инструкция include, однако
// блокирует вывод текста в браузер. Вместо этого текст возвращается
// в качестве результата. Функцию можно использовать, например,
// для обработки почтовых шаблонов.
function template($__fname$vars) {
  
// Перехватываем выходной поток.
  
ob_start();
    
// Запускаем файл как программу на PHP.
    
extract($varsEXTR_OVERWRITE);
    include(
$__fname);
  
// Получаем перехваченный текст.
  
$text ob_get_contents();
  
ob_end_clean();
  return 
$text;
}
?>
Скопировать в буфер

lib/mailx.php

<?php
// Функция отправляет письмо, полностью заданное в параметре $mail.
// Корректно обрабатываются заголовки To и Subject.
function mailx($mail) {
  
// Разделяем тело сообщения и заголовки.
  
list ($head$body) = preg_split("/\r?\n\r?\n/s"$mail2);
  
// Выделяем заголовок To.
  
$to "";
  if (
preg_match('/^To:\s*([^\r\n]*)[\r\n]*/m'$head$p)) {
    
$to = @$p[1]; // сохраняем
    
$head str_replace($p[0], ""$head); // удаляем из исходной строки
  
}
  
// Выделяем Subject.
  
$subject "";
  if (
preg_match('/^Subject:\s*([^\r\n]*)[\r\n]*/m'$head$p)) {
    
$subject = @$p[1];
    
$head str_replace($p[0], ""$head);
  }
  
// Отправляем почту. Внимание! Опасный прием!
  
mail($to$subject$bodytrim($head));
}
?>
Скопировать в буфер

lib/mailenc.php

<?php
// Корректно кодирует все заголовки в письме $mail с использованием
// метода base64. Кодировка письма определяется автоматически на основе
// заголовка Content-type. Возвращает полученное письмо.
function mailenc($mail) {
  
// Разделяем тело сообщения и заголовки.
  
list ($head$body) = preg_split("/\r?\n\r?\n/s"$mail2);
  
// Определяем кодировку письма по заголовку Content-type.
  
$encoding '';
  
$re '/^Content-type:\s*\S+\s*;\s*charset\s*=\s*(\S+)/mi';
  if (
preg_match($re$head$p)) $encoding $p[1];
  
// Проходимся по всем строкам-заголовкам.
  
$newhead "";
  foreach (
preg_split('/\r?\n/s'$head) as $line) {
    
// Кодируем очередной заголовок.
    
$line mailenc_header($line$encoding);
    
$newhead .= "$line\r\n";
  }
  
// Формируем окончательный результат.
  
return "$newhead\r\n$body";
}

// Кодирует в строке максимально возможную последовательность
// символов, начинающуюся с недопустимого символа и НЕ
// включающую E-mail (адреса E-mail обрамляют символами < и >).
// Если в строке нет ни одного недопустимого символа, преобразование
// не производится.
function mailenc_header($header$encoding) {
  
// Кодировка не задана - делать нечего.
  
if (!$encoding) return $header;
  
// Сохраняем кодировку в глобальной переменной. Без использования
  // ООП это - единственный способ передать дополнительный параметр
  // callback-функции.
  
$GLOBALS['mail_enc_header_encoding'] = $encoding;
  return 
preg_replace_callback(
    
'/([\x7F-\xFF][^<>\r\n]*)/s',
    
'mailenc_header_callback',
    
$header
  
);
}

// Служебная функция для использования в preg_replace_callback().
function mailenc_header_callback($p) {
  
$encoding $GLOBALS['mail_enc_header_encoding'];
  
// Пробелы в конце оставляем незакодированными.
  
preg_match('/^(.*?)(\s*)$/s'$p[1], $sp);
  return 
"=?$encoding?B?".base64_encode($sp[1])."?=".$sp[2];
}
?>
Скопировать в буфер

lib/socketmail.php

<?php
// Функция для посылки почты вручную, минуя SMTP-сервер провайдера.
// Использует getmxrr(), которая в Windows не поддерживается.
function mailx_manual($mail, &$reason=false) {
  
$reason = array();
  
// Выделяем заголовок To.
  
$to "";
  if (
preg_match('/^To:\s*([^\r\n]*)[\r\n]*/m'$mail$p)) {
    
$to = @$p[1]; // сохраняем
  
}
  
// Вначале выделяем имя хоста.
  
if (!preg_match('/@([\w.-]*)/'$to$pockets)) {
    
$reason[] = "invalid e-mail address - $to: no host";
    return 
false;
  }
  
$host $pockets[1];
  
// По стандарту SMTP, если нет ни одной MX-записи, то в качестве
  // почтового сервера выступает сам хост.
  
if (!getmxrr($host$mxes, &$weights)) {
    
$mxes = array($host);
  }
  
// Проходимся по всем MX-записям. Для простоты веса не
  // учитываем - большой беды от этого не будет.
  
foreach ($mxes as $mx) {
    
$result socketmail($mx$mail$r);
    
$reason array_merge($reason$r);
    
// Если письмо отослано, все сделано.
    
if ($result) return true;
  }
  
$reason[] = "could not connect to any of (".join(", "$mxes).")";
  return 
false;
}

// Функция открывает соединение с SMTP-сервером $host
// и пытается отправить через него письма, заданные в $mails.
// Все ошибки накапливаются в необязательной переменной $reason
// в виде списка строк. В случае, если отправка всех писем
// прошла успешно, функция возвращает true, иначе - false.
// Каждое письмо в $mails должно быть представлено в формате:
// "Заголовки\r\n\r\nТело". Функция не заботится о правильном
// кодировании заголовков, предполагая, что это уже было
// сделано ранее.
function socketmail($host$mails, &$reason=false) {
  
// Открываем соединение с почтовым сервером.
  
$reason = array();
  
$f = @fsockopen($host25$errno$errstr30);
  if (!
$f) {
    
$reason[] = "could not open $host:25";
    return 
false;
  }
  
$answer fgets($f1024);

  
// Сигнализируем о начале обмена данными.
  
fputs($f"HELO {$_SERVER['SERVER_NAME']}\r\n");
  
$answer fgets($f1024);

  
// Отправляем все письма для этого сервера в цикле.
  // Все это происходит за одно соединение с сервером.
  
if (!is_array($mails)) $mails = array($mails);
  foreach (
$mails as $i=>$data) {
    
// Получаем заголовки и тело сообщения.
    
list ($headers$body) = preg_split('/\r?\n\r?\n/'$data2);
    
// Получаем заголовок From.
    
if (!preg_match('/^From:\s*(.*)/mi'$headers$pockets)) {
      
$reason[] = "could not find required From: header in mail #$i";
      continue;
    }
    
$from getEmail($pockets[1]);
    if (!
$from) {
      
$reason[] = "no email in From: header in mail #$i";
      continue;
    }
    
// Получаем заголовок To.
    
if (!preg_match('/^To:\s*(.*)/mi'$headers$pockets)) {
      
$reason[] = "could not find required To: header in mail #$i";
      continue;
    }
    
$to getEmail($pockets[1]);
    if (!
$to) {
      
$reason[] = "no email in To: header in mail #$i";
      continue;
    }
    
// Т.к. точка в протоколе SMTP свидетельствует о конце данных,
    // (см. ниже), мы ее удваиваем.
    
$data preg_replace("/\n\./""\n.."$data);
    
// Отправляем управляющие команды SMTP.
    
do {
      if (!
smtp_say($f"MAIL FROM: <$from>"$reason)) break;
      if (!
smtp_say($f"RCPT TO: <$to>"$reason)) break;
      if (!
smtp_say($f"DATA"$reason)) break;
      
// Печатаем данные.
      
fputs($ftrim($data)."\r\n");
      if (!
smtp_say($f"."$reason)) break;
    } while (
false);
    
// Конец письма.
    
!smtp_say($f"RSET"$reason);
  }

  
// Говорим серверу об окончании работы.
  
@smtp_say($f"QUIT"$reason);
  
fclose($f);
  return !
count($reason);
}

function 
smtp_say($f$cmd, &$reason) {
  
fputs($f"$cmd\r\n");
  
$answer fgets($f1024);
#  echo "&gt; $cmd<br>&lt; $answer<br>";
  
if (!preg_match('/^(250|354|221)/'$answer)) { $reason[] = "$answer"; return; }
  return 
true;
}

// Извлекает первый адрес E-mail из заголовка To или From.
// Внимание: упрощенная версия!
function getEmail($header) {
  if (!
preg_match('/([\w.-]+@[\w.-]+)/s'$header$p)) return;
  return 
$p[1];
}
?>
Скопировать в буфер

mail.php.eml - активный шаблон письма
From: Почтовый робот <somebody@mail.ru>
To: &lt;?=$to?>
Subject: Добрый день!
Content-type: text/plain;
	charset=windows-1251

Привет, &lt;?=$to?>!
&lt;?=$text?>
Содержимое переменных окружения на момент отправки письма:
&lt;?print_r($_SERVER)?>
Это сообщение сгенерировано роботом - не отвечайте на него.
Здесь представлен полностью работающий скрипт, Вы можете собрать его сами в одну папку, поправить адреса и запустить.

Всего за 100 рублей (~3$) Вы можете приобрести готовый rar-архив, содержащий скрипт, который также поддерживает весь функционал, и имеет дополнительные отладочные опции. Код скрипта реализован на PHP, полностью открытый и не использует никаких дополнительных библиотек.


Имя:
Пароль:   Забыли?


При нажатии кнопки Оплатить и загрузить, Вы подтверждаете согласие с условиями использования скрипта, описанными на этой странице.
Вы будете перенаправлены на страницу выбора способа оплаты, после оплаты 100 рублей (~3$) начнется загрузка файла.
Чтобы мы не потеряли Вашу оплату при потере соединения, укажите Ваш действующий
адрес электронной почты

трансформеры игры

© Copyright 2008-2012 by KDG