Файл: магазин/e-proger/engine/libmail.php
Строк: 431
<?php
date_default_timezone_set('Europe/Moscow');
class Mail {
var $sendto = array();
var $acc = array();
var $abcc = array();
var $aattach = array();
var $xheaders = array();
var $priorities = array('1 (Highest)', '2 (High)', '3 (Normal)', '4 (Low)', '5 (Lowest)');
var $charset = "UTF-8";
var $ctencoding = "8bit";
var $receipt = 0;
var $text_html = "text/html"; // формат письма. по умолчанию текстовый
var $smtp_on = false; // отправка через smtp. по умолчанию выключена
var $names_email = array(); // имена для email адресов, чтобы делать вид ("Антон" <te@gg.ru>)
/*
конструктор тоже по старому объявлен для совместимости со старыми версиями php
пошел конструктор.
входящий параметр кодировка письма
внесено изменение
*/
function Mail($charset="") {
$this->autoCheck(true);
$this->boundary = "--" . md5(uniqid("myboundary"));
if ($charset != "") {
$this->charset = strtolower($charset);
if ($this->charset == "us-ascii")
$this->ctencoding = "7bit";
}
}
/*
включение выключение проверки валидности email
пример: autoCheck( true ) проверка влючена
по умолчанию проверка включена
*/
function autoCheck($bool) {
if ($bool)
$this->checkAddress = true;
else
$this->checkAddress = false;
}
/*
Тема письма
внесено изменения кодирования не латинских символов
*/
function Subject($subject) {
$this->xheaders['Subject'] = "=?" . $this->charset . "?Q?" . str_replace("+", "_", str_replace("%", "=", urlencode(strtr($subject, "rn", " ")))) . "?=";
}
/*
от кого
*/
function From($from) {
if (!is_string($from)) {
echo "ошибка, From должен быть строкой";
exit;
}
$temp_mass = explode(';', $from); // разбиваем по разделителю для выделения имени
if (count($temp_mass) == 2) { // если удалось разбить на два элемента
$this->names_email['from'] = $temp_mass[0]; // имя первая часть
$this->xheaders['From'] = $temp_mass[1]; // адрес вторая часть
} else { // и если имя не определено
$this->names_email['from'] = '';
$this->xheaders['From'] = $from;
}
}
/*
на какой адрес отвечать
*/
function ReplyTo($address) {
if (!is_string($address))
return false;
$temp_mass = explode(';', $address); // разбиваем по разделителю для выделения имени
if (count($temp_mass) == 2) { // если удалось разбить на два элемента
$this->names_email['Reply-To'] = $temp_mass[0]; // имя первая часть
$this->xheaders['Reply-To'] = $temp_mass[1]; // адрес вторая часть
} else { // и если имя не определено
$this->names_email['Reply-To'] = '';
$this->xheaders['Reply-To'] = $address;
}
}
/*
Добавление заголовка для получения уведомления о прочтении. обратный адрес берется из "From" (или из "ReplyTo" если указан)
*/
function Receipt() {
$this->receipt = 1;
}
/*
set the mail recipient
@param string $to email address, accept both a single address or an array of addresses
*/
function To($to) {
// если это массив
if (is_array($to)) {
foreach ($to as $key => $value) { // перебираем массив и добавляем в массив для отправки через smtp
$temp_mass = explode(';', $value); // разбиваем по разделителю для выделения имени
if (count($temp_mass) == 2) { // если удалось разбить на два элемента
$this->smtpsendto[$temp_mass[1]] = $temp_mass[1]; // ключи и значения одинаковые, чтобы исключить дубли адресов
$this->names_email['To'][$temp_mass[1]] = $temp_mass[0]; // имя первая часть
$this->sendto[] = $temp_mass[1];
} else { // и если имя не определено
$this->smtpsendto[$value] = $value; // ключи и значения одинаковые, чтобы исключить дубли адресов
$this->names_email['To'][$value] = ''; // имя первая часть
$this->sendto[] = $value;
}
}
} else {
$temp_mass = explode(';', $to); // разбиваем по разделителю для выделения имени
if (count($temp_mass) == 2) { // если удалось разбить на два элемента
$this->sendto[] = $temp_mass[1];
$this->smtpsendto[$temp_mass[1]] = $temp_mass[1]; // ключи и значения одинаковые, чтобы исключить дубли адресов
$this->names_email['To'][$temp_mass[1]] = $temp_mass[0]; // имя первая часть
} else { // и если имя не определено
$this->sendto[] = $to;
$this->smtpsendto[$to] = $to; // ключи и значения одинаковые, чтобы исключить дубли адресов
$this->names_email['To'][$to] = ''; // имя первая часть
}
}
if ($this->checkAddress == true)
$this->CheckAdresses($this->sendto);
}
/* Cc()
* установка заголдовка CC ( открытая копия, все получатели будут видеть куда ушла копия )
* $cc : email address(es), accept both array and string
*/
function Cc($cc) {
if (is_array($cc)) {
$this->acc = $cc;
foreach ($cc as $key => $value) { // перебираем массив и добавляем в массив для отправки через smtp
$this->smtpsendto[$value] = $value; // ключи и значения одинаковые, чтобы исключить дубли адресов
}
} else {
$this->acc[] = $cc;
$this->smtpsendto[$cc] = $cc; // ключи и значения одинаковые, чтобы исключить дубли адресов
}
if ($this->checkAddress == true)
$this->CheckAdresses($this->acc);
}
/* Bcc()
* скрытая копия. не будет помещать заголовок кому ушло письмо
* $bcc : email address(es), accept both array and string
*/
function Bcc($bcc) {
if (is_array($bcc)) {
$this->abcc = $bcc;
foreach ($bcc as $key => $value) { // перебираем массив и добавляем в массив для отправки через smtp
$this->smtpsendto[$value] = $value; // ключи и значения одинаковые, чтобы исключить дубли адресов
}
} else {
$this->abcc[] = $bcc;
$this->smtpsendto[$bcc] = $bcc; // ключи и значения одинаковые, чтобы исключить дубли адресов
}
if ($this->checkAddress == true)
$this->CheckAdresses($this->abcc);
}
/* Body( text [ text_html ] )
* $text_html в каком формате будет письмо, в тексте или html. по умолчанию стоит текст
*/
function Body($body, $text_html="") {
$this->body = $body;
if ($text_html == "html")
$this->text_html = "text/html";
}
/* Organization( $org )
* set the Organization header
*/
function Organization($org) {
if (trim($org != ""))
$this->xheaders['Organization'] = $org;
}
/* Priority( $priority )
* set the mail priority
* $priority : integer taken between 1 (highest) and 5 ( lowest )
* ex: $mail->Priority(1) ; => Highest
*/
function Priority($priority) {
if (!intval($priority))
return false;
if (!isset($this->priorities[$priority - 1]))
return false;
$this->xheaders["X-Priority"] = $this->priorities[$priority - 1];
return true;
}
/*
прикрепленные файлы
@param string $filename : путь к файлу, который надо отправить
@param string $webi_filename : реальное имя файла. если вдруг вставляется файл временный, то его имя будет хрен пойми каким..
@param string $filetype : MIME-тип файла. по умолчанию 'application/x-unknown-content-type'
@param string $disposition : инструкция почтовому клиенту как отображать прикрепленный файл ("inline") как часть письма или ("attachment") как прикрепленный файл
*/
function Attach($filename, $webi_filename="", $filetype = "", $disposition = "inline") {
// TODO : если типа файла не указан, ставим неизвестный тип
if ($filetype == "")
$filetype = "application/x-unknown-content-type";
$this->aattach[] = $filename;
$this->webi_filename[] = $webi_filename;
$this->actype[] = $filetype;
$this->adispo[] = $disposition;
}
/*
Собираем письмо
*/
function BuildMail() {
$this->headers = "";
// создание заголовка TO.
// добавление имен к адресам
foreach ($this->sendto as $key => $value) {
if (strlen($this->names_email['To'][$value]))
$temp_mass[] = "=?" . $this->charset . "?Q?" . str_replace("+", "_", str_replace("%", "=", urlencode(strtr($this->names_email['To'][$value], "rn", " ")))) . "?= <" . $value . ">";
else
$temp_mass[] = $value;
}
$this->xheaders['To'] = implode(", ", $temp_mass); // этот заголовок будет не нужен при отправке через mail()
if (count($this->acc) > 0)
$this->xheaders['CC'] = implode(", ", $this->acc);
if (count($this->abcc) > 0)
$this->xheaders['BCC'] = implode(", ", $this->abcc); // этот заголовок будет не нужен при отправке через smtp
if ($this->receipt) {
if (isset($this->xheaders["Reply-To"]))
$this->xheaders["Disposition-Notification-To"] = $this->xheaders["Reply-To"];
else
$this->xheaders["Disposition-Notification-To"] = $this->xheaders['From'];
}
if ($this->charset != "") {
$this->xheaders["Mime-Version"] = "1.0";
$this->xheaders["Content-Type"] = $this->text_html . "; charset=$this->charset";
$this->xheaders["Content-Transfer-Encoding"] = $this->ctencoding;
}
// вставаляем файлы
if (count($this->aattach) > 0) {
$this->_build_attachement();
} else {
$this->fullBody = $this->body;
}
// создание заголовков если отправка идет через smtp
if ($this->smtp_on) {
// разбиваем (FROM - от кого) на юзера и домен. домен понадобится в заголовке
$user_domen = explode('@', $this->xheaders['From']);
$this->headers = "Date: " . date("D, j M Y G:i:s") . " +0700rn";
$this->headers .= "Message-ID: <" . rand() . "." . date("YmjHis") . "@" . $user_domen[1] . ">rn";
reset($this->xheaders);
while (list( $hdr, $value ) = each($this->xheaders)) {
if ($hdr == "From" and strlen($this->names_email['from']))
$this->headers .= $hdr . ": =?" . $this->charset . "?Q?" . str_replace("+", "_", str_replace("%", "=", urlencode(strtr($this->names_email['from'], "rn", " ")))) . "?= <" . $value . ">rn";
elseif ($hdr == "Reply-To" and strlen($this->names_email['Reply-To']))
$this->headers .= $hdr . ": =?" . $this->charset . "?Q?" . str_replace("+", "_", str_replace("%", "=", urlencode(strtr($this->names_email['Reply-To'], "rn", " ")))) . "?= <" . $value . ">rn";
elseif ($hdr != "BCC")
$this->headers .= $hdr . ": " . $value . "rn"; // пропускаем заголовок для отправки скрытой копии
}
}
// создание заголовоков, если отправка идет через mail()
else {
reset($this->xheaders);
while (list( $hdr, $value ) = each($this->xheaders)) {
if ($hdr == "From" and strlen($this->names_email['from']))
$this->headers .= $hdr . ": =?" . $this->charset . "?Q?" . str_replace("+", "_", str_replace("%", "=", urlencode(strtr($this->names_email['from'], "rn", " ")))) . "?= <" . $value . ">rn";
elseif ($hdr == "Reply-To" and strlen($this->names_email['Reply-To']))
$this->headers .= $hdr . ": =?" . $this->charset . "?Q?" . str_replace("+", "_", str_replace("%", "=", urlencode(strtr($this->names_email['Reply-To'], "rn", " ")))) . "?= <" . $value . ">rn";
elseif ($hdr != "Subject" and $hdr != "To")
$this->headers .= "$hdr: $valuen"; // пропускаем заголовки кому и тему... они вставятся сами
}
}
}
// включение отправки через smtp используя сокеты
// после запуска этой функции отправка через smtp включена
// для отправки через защищенное соединение сервер нужно указывать с добавлением "ssl://" например так "ssl://smtp.gmail.com"
function smtp_on($smtp_serv, $login, $pass, $port=25, $timeout=5) {
$this->smtp_on = true; // включаем отправку через smtp
$this->smtp_serv = $smtp_serv;
$this->smtp_login = $login;
$this->smtp_pass = $pass;
$this->smtp_port = $port;
$this->smtp_timeout = $timeout;
}
function get_data($smtp_conn) {
$data = "";
while ($str = fgets($smtp_conn, 515)) {
$data .= $str;
if (substr($str, 3, 1) == " ") {
break;
}
}
return $data;
}
/*
отправка письма
*/
function Send() {
$this->BuildMail();
$this->strTo = implode(", ", $this->sendto);
// если отправка без использования smtp
if (!$this->smtp_on) {
$res = @mail($this->strTo, $this->xheaders['Subject'], $this->fullBody, $this->headers);
} else { // если через smtp
if (!$this->smtp_serv OR !$this->smtp_login OR !$this->smtp_pass OR !$this->smtp_port)
return false; // если нет хотя бы одного из основных данных для коннекта, выходим с ошибкой
// разбиваем (FROM - от кого) на юзера и домен. юзер понадобится в приветсвии с сервом
$user_domen = explode('@', $this->xheaders['From']);
$this->smtp_log = '';
$smtp_conn = fsockopen($this->smtp_serv, $this->smtp_port, $errno, $errstr, $this->smtp_timeout);
if (!$smtp_conn) {
$this->smtp_log .= "соединение с сервером не прошлоnn";
fclose($smtp_conn);
return;
}
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
fputs($smtp_conn, "EHLO " . $user_domen[0] . "rn");
$this->smtp_log .= "Я: EHLO " . $user_domen[0] . "n";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
$code = substr($data, 0, 3); // получаем код ответа
if ($code != 250) {
$this->smtp_log .= "ошибка приветсвия EHLO n";
fclose($smtp_conn);
return;
}
fputs($smtp_conn, "AUTH LOGINrn");
$this->smtp_log .= "Я: AUTH LOGINn";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
$code = substr($data, 0, 3);
if ($code != 334) {
$this->smtp_log .= "сервер не разрешил начать авторизацию n";
fclose($smtp_conn);
return;
}
fputs($smtp_conn, base64_encode($this->smtp_login) . "rn");
$this->smtp_log .= "Я: " . base64_encode($this->smtp_login) . "n";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
$code = substr($data, 0, 3);
if ($code != 334) {
$this->smtp_log .= "ошибка доступа к такому юзеруn";
fclose($smtp_conn);
return;
}
fputs($smtp_conn, base64_encode($this->smtp_pass) . "rn");
$this->smtp_log .="Я: " . base64_encode($this->smtp_pass) . "n";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
$code = substr($data, 0, 3);
if ($code != 235) {
$this->smtp_log .= "неправильный парольn";
fclose($smtp_conn);
return;
}
fputs($smtp_conn, "MAIL FROM:<" . $this->xheaders['From'] . "> SIZE=" . strlen($this->headers . "rn" . $this->fullBody) . "rn");
$this->smtp_log .= "Я: MAIL FROM:<" . $this->xheaders['From'] . "> SIZE=" . strlen($this->headers . "rn" . $this->fullBody) . "n";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
$code = substr($data, 0, 3);
if ($code != 250) {
$this->smtp_log .= "сервер отказал в команде MAIL FROMn";
fclose($smtp_conn);
return;
}
foreach ($this->smtpsendto as $keywebi => $valuewebi) {
fputs($smtp_conn, "RCPT TO:<" . $valuewebi . ">rn");
$this->smtp_log .= "Я: RCPT TO:<" . $valuewebi . ">n";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
$code = substr($data, 0, 3);
if ($code != 250 AND $code != 251) {
$this->smtp_log .= "Сервер не принял команду RCPT TOn";
fclose($smtp_conn);
return;
}
}
fputs($smtp_conn, "DATArn");
$this->smtp_log .="Я: DATAn";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
$code = substr($data, 0, 3);
if ($code != 354) {
$this->smtp_log .= "сервер не принял DATAn";
fclose($smtp_conn);
return;
}
fputs($smtp_conn, $this->headers . "rn" . $this->fullBody . "rn.rn");
$this->smtp_log .= "Я: " . $this->headers . "rn" . $this->fullBody . "rn.rn";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
$code = substr($data, 0, 3);
if ($code != 250) {
$this->smtp_log .= "ошибка отправки письмаn";
fclose($smtp_conn);
return;
}
fputs($smtp_conn, "QUITrn");
$this->smtp_log .="QUITrn";
$this->smtp_log .= $data = $this->get_data($smtp_conn) . "n";
fclose($smtp_conn);
}
}
/*
* показывает что было отправлено
*
*/
function Get() {
if (isset($this->smtp_log)) {
if ($this->smtp_log) {
return $this->smtp_log; // если есть лог отправки smtp выведем его
}
}
$this->BuildMail();
$mail = $this->headers . "nn";
$mail .= $this->fullBody;
return $mail;
}
/*
проверка мыла
возвращает true или false
*/
function ValidEmail($address) {
// если существует современная функция фильтрации данных, то проверять будем этой функцией. появилась в php 5.2
if (function_exists('filter_list')) {
$valid_email = filter_var($address, FILTER_VALIDATE_EMAIL);
if ($valid_email !== false)
return true;
else
return false;
}
else { // а если php еще старой версии, то проверка валидности пойдет старым способом
if (ereg(".*<(.+)>", $address, $regs)) {
$address = $regs[1];
}
if (ereg("^[^@ ]+@([a-zA-Z0-9-]+.)+([a-zA-Z0-9-]{2}|net|com|gov|mil|org|edu|int)$", $address))
return true;
else
return false;
}
}
/*
проверка массива адресов
*/
function CheckAdresses($aad) {
for ($i = 0; $i < count($aad); $i++) {
if (!$this->ValidEmail($aad[$i])) {
echo "ошибка : не верный email " . $aad[$i];
exit;
}
}
}
/*
сборка файлов для отправки
*/
function _build_attachement() {
$this->xheaders["Content-Type"] = "multipart/mixed;n boundary="$this->boundary"";
$this->fullBody = "This is a multi-part message in MIME format.n--$this->boundaryn";
$this->fullBody .= "Content-Type: " . $this->text_html . "; charset=$this->charsetnContent-Transfer-Encoding: $this->ctencodingnn" . $this->body . "n";
$sep = chr(13) . chr(10);
$ata = array();
$k = 0;
// перебираем файлы
for ($i = 0; $i < count($this->aattach); $i++) {
$filename = $this->aattach[$i];
$webi_filename = $this->webi_filename[$i]; // имя файла, которое может приходить в класс, и имеет другое имя файла
if (strlen($webi_filename))
$basename = basename($webi_filename); // если есть другое имя файла, то оно будет таким
else
$basename = basename($filename); // а если нет другого имени файла, то имя будет выдернуто из самого загружаемого файла
$ctype = $this->actype[$i]; // content-type
$disposition = $this->adispo[$i];
if (!file_exists($filename)) {
echo "ошибка прикрепления файла : файл $filename не существует";
exit;
}
$subhdr = "--$this->boundarynContent-type: $ctype;n name="$basename"nContent-Transfer-Encoding: base64nContent-Disposition: $disposition;n filename="$basename"n";
$ata[$k++] = $subhdr;
// non encoded line length
$linesz = filesize($filename) + 1;
$fp = fopen($filename, 'r');
$ata[$k++] = chunk_split(base64_encode(fread($fp, $linesz)));
fclose($fp);
}
$this->fullBody .= implode($sep, $ata);
}
}
// class Mail
?>