Отправка уведомлений через SMTP

Board index Кухня Розробка

Description: Пропозиції, питання, обговорення

#1by Назар Токарь » 06.09.2013, 14:46

[обновлено 2013-12-24]

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

Для начала регистрируете почтовый ящик на своем домене. В настройках своего почтового ящика в панели управления получаете такие данные:

  • адрес smtp-сервера
  • порт smtp, обычно это 25
  • имя почтового пользователя, чаще всего здесь просто адрес почты
  • пароль

Обратите внимание, что чаще всего имя пользователя это полный адрес электронной почты. Далее создаете новый файл smtp.php с таким содержимым (взято отсюда):

Code: Select all
<?php
$mhSmtpMail_Server = "smtp.domain.tld"; // smtp-сервер
$mhSmtpMail_Port = "25"; // порт smtp
$mhSmtpMail_Username = "postmaster@domain.tld"; // имя пользователя
$mhSmtpMail_Password = "password"; // пароль

function MailSmtp($to, $subject, $message, $headers) {
global $mhSmtpMail_Server, $mhSmtpMail_Port, $mhSmtpMail_Username, $mhSmtpMail_Password;
$mhSmtpMail_localhost  = "localhost";
$mhSmtpMail_newline    = "\r\n";
$mhSmtpMail_timeout    = "30";

$smtpConnect = fsockopen($mhSmtpMail_Server, $mhSmtpMail_Port, $errno, $errstr, $mhSmtpMail_timeout);
$smtpResponse = fgets($smtpConnect, 515);

if(empty($smtpConnect)) {
$output = "Failed to connect: $smtpResponse";
return $output;
} else {
$logArray['connection'] = "Connected: $smtpResponse";
}

fputs($smtpConnect, "HELO $mhSmtpMail_localhost" . $mhSmtpMail_newline);
$smtpResponse = fgets($smtpConnect, 515);
$logArray['heloresponse'] = "$smtpResponse";

fputs($smtpConnect,"AUTH LOGIN" . $mhSmtpMail_newline);
$smtpResponse = fgets($smtpConnect, 515);
$logArray['authrequest'] = "$smtpResponse";

fputs($smtpConnect, base64_encode($mhSmtpMail_Username) . $mhSmtpMail_newline);
$smtpResponse = fgets($smtpConnect, 515);
$logArray['authmhSmtpMail_username'] = "$smtpResponse";

fputs($smtpConnect, base64_encode($mhSmtpMail_Password) . $mhSmtpMail_newline);
$smtpResponse = fgets($smtpConnect, 515);
$logArray['authmhSmtpMail_password'] = "$smtpResponse";

fputs($smtpConnect, "MAIL FROM: $mhSmtpMail_Username" . $mhSmtpMail_newline);
$smtpResponse = fgets($smtpConnect, 515);
$logArray['mailmhSmtpMail_fromresponse'] = "$smtpResponse";

fputs($smtpConnect, "RCPT TO: $to" . $mhSmtpMail_newline);
$smtpResponse = fgets($smtpConnect, 515);
$logArray['mailtoresponse'] = "$smtpResponse";

fputs($smtpConnect, "DATA" . $mhSmtpMail_newline);
$smtpResponse = fgets($smtpConnect, 515);
$logArray['data1response'] = "$smtpResponse";

fputs($smtpConnect, "Subject: $subject\r\n$headers\r\n\r\n$message\r\n.\r\n");
$smtpResponse = fgets($smtpConnect, 515);
$logArray['data2response'] = "$smtpResponse";

fputs($smtpConnect,"QUIT" . $mhSmtpMail_newline);
$smtpResponse = fgets($smtpConnect, 515);
$logArray['quitresponse'] = "$smtpResponse";
}
?>

Файл загружаете в папку со скриптом по адресу /callme/. Далее открываете файл /callme/lib/send.php и после строки

Code: Select all
header("Content-Type: text/html; charset=utf-8"); //кодировка

Вставляете код

Code: Select all
require "smtp.php";

Ищете строку:

Code: Select all
@mail ($to, $title, $mess, $headers);

И заменяете ее на:

Code: Select all
MailSmtp ($to, $title, $mess, $headers);

После этого замените переменную $from на почтовый адрес, от которого отправляется сообщение.

Готово.
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

Настройка Buyme на отправку сообщений через SMTP

#2by paulo737 » 07.11.2013, 22:29

Опробовал рецепт который указан выше для отправки на почту но не работает. Возможно потому, что на сервере требуется подключаться через зашифрованный канал (SSL/TLS). Подскажите как быть в этом случае. Дело в том что почта для домена прикручена к gmail.
Вы всегда можете купить слепки и наборы для их изготовления на нашем сайте
paulo737 M
Avatar
Age: 35
Location: Украина, Луганск
Reputation: 0
Posts: 3
With us: 2 yaers 6 months

#3by Назар Токарь » 07.11.2013, 22:57

paulo737, не хотите копаться, создайте ящик на мэйлру или яндекс и настройте отправку через него.
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

#4by paulo737 » 07.11.2013, 23:53

Пример работающего скрипта отправки для SSL/TSL:

Code: Select all
<?php
include "libmail.php"; // вставляем файл с классом
$m= new Mail; // начинаем
$m->From( "Василий Пупкин;мой_аккаунт@gmail.com" ); // от кого отправляется почта
$m->To( "_мой_аккаунт_@gmail.com" ); // кому адресованно
$m->Subject( "Тест скрипта" );
$m->Body( "Ваш заказ принят" );   
$m->Priority(3) ;    // приоритет письма
$m->smtp_on("ssl://smtp.gmail.com","Логин","Пароль", 465);
$m->Send();    // а теперь пошла отправка
?>
Ссылка на файл библиотеки libmail.php

Пример скрипта взят вот здесь. Там есть более подробное описание для других случаев

Added after 1 hour 30 minutes:
Возник другой вопрос, как вместо сообщения "Ваш заказ принят" вставить данные из формы которую пользователь заполнил.
Вы всегда можете купить слепки и наборы для их изготовления на нашем сайте
paulo737 M
Avatar
Age: 35
Location: Украина, Луганск
Reputation: 0
Posts: 3
With us: 2 yaers 6 months

#5by Назар Токарь » 08.11.2013, 01:36

paulo737, интересно, но библиотека рассчитана на отправку в кодировке Win-1251, а обычно все работают с UTF-8.

paulo737 wrote:вместо сообщения "Ваш заказ принят" вставить данные из формы

В send.php где

Code: Select all
for each ... as $value

Сохранять нужные переменные. Например, это добавить перед циклом:

Code: Select all
$toSendArray = array();

А это внутри цикла:

Code: Select all
if ( ($value == "Номер телефона") || ($value == "Адрес доставки") ) {
$toSendArray[] = $value;
}

Ну и в конце аттачить массив к письму или к уведомлению.
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

#6by paulo737 » 08.11.2013, 12:49

Спасибо за развернутый ответ.

интересно, но библиотека рассчитана на отправку в кодировке Win-1251, а обычно все работают с UTF-8.
Code: Select all
$m= new Mail; // начинаем

Можно заменить для использования UTF-8
Code: Select all
$m= new Mail("utf-8");
Вы всегда можете купить слепки и наборы для их изготовления на нашем сайте
paulo737 M
Avatar
Age: 35
Location: Украина, Луганск
Reputation: 0
Posts: 3
With us: 2 yaers 6 months

#7by Souz2000 » 18.11.2013, 12:12

Здравствуйте!
В первом сообещние вы описали как делать для скрипта callme, а в случае скрипта buyme где что заменять нужно?
И еще у нас почта привязана к домену, но сделана на gmail'е, в этом случае использовать скрипт отправки для SSL/TSL?
Заранее спасибо!
Souz2000
Reputation: 0
Posts: 2
With us: 2 yaers 6 months

#8by Назар Токарь » 18.11.2013, 13:46

Souz2000, в скриптах этих отправка работает практически одинаково.
Странно задавать такие вопросы, просто посмотрите на код.

Если не работает через gmail, настройте на Яндекс.
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

#9by Souz2000 » 18.11.2013, 15:56

То что отправка работает одинаково это ясно, интересует вот этот момент:
Файл загружаете в папку со скриптом по адресу /callme/. Далее открываете файл /callme/index.php и после строки
В случае с buyme как быть? Например index.php - такого файла нет, есть index.html - но ведь это не оно
Souz2000
Reputation: 0
Posts: 2
With us: 2 yaers 6 months

#10by Назар Токарь » 19.11.2013, 00:55

Souz2000, /lib/send.php
Их там всего несколько папок и несколько файлов, как можно запутаться?
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

#11by Ramapriya » 14.01.2014, 09:58

Всем привет...

простите за глупый вопрос... а настройках smtp указывать, например, gmail?
Ramapriya
Reputation: -1
Posts: 1
With us: 2 yaers 4 months

#12by Назар Токарь » 14.01.2014, 11:24

Ramapriya, попробуйте в гугле ввести "smtp gmail".
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

#13by urok » 09.02.2014, 14:09

установлен Buyme в файле buyme\lib\send.php не было строки
header("Content-Type: text/html; charset=utf-8"); //кодировка
добавил её после <?php
получилось вот так
Code: Select all
<?php
header("Content-Type: text/html; charset=utf-8"); //кодировка
require "smtp.php";

закомментировал
//@mail ($to, $title, $mess, $headers);
ниже вставил это
MailSmtp ($to, $title, $mess, $headers);

тут сделал так $from = "адрес@почты.отправителя".$HTTP_HOST; // отправитель

в итогах пишет, что отправлено нормально. СМС приходит, а письма нет.
Сам ящик отправителя проверял, в аутлуке письмо приходит.
urok
Reputation: 1
Posts: 5
With us: 2 yaers 3 months

#14by Назар Токарь » 10.02.2014, 01:39

urok, нужно так

Code: Select all
$from = "адрес@почты.отправителя";

PS: я мог бы понимать вас лучше, если бы вы использовали знаки препинания. Например, запятые и точки.

urok wrote:Сам ящик отправителя проверял, в аутлуке письмо приходит.

Эту фразу я не понял. Если письмо приходит, в чем тогда вопрос.
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

#15by urok » 10.02.2014, 04:50

исправил на
Code: Select all
$from = "адрес@почты.отправителя";
не помогло

Назар Токарь wrote:Эту фразу я не понял. Если письмо приходит, в чем тогда вопрос.
ящик отправителя настроил в оутлоке и отправил на адрес получателя , письмо пришло
а со скрипта не приходит :wink:
urok
Reputation: 1
Posts: 5
With us: 2 yaers 3 months

#16by Назар Токарь » 10.02.2014, 10:33

urok, ну тогда проблема в настройках, ищите ошибку.
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

#17by urok » 10.02.2014, 15:03

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

еще раз все настройки, smtp.php исправляю верхние 4 строчки, ниже ничего не трогаю
Code: Select all
$mhSmtpMail_Server = "smtp.yandex.ru"; // smtp-сервер
$mhSmtpMail_Port = "25"; // порт smtp
$mhSmtpMail_Username = "ящик-отправителя@yandex.ru"; // имя пользователя
$mhSmtpMail_Password = "пароль от почты"; // пароль

в файле send.php исправляю только эти строчки
Code: Select all
require "smtp.php";
$to = "ящик-получателя@mail.ru";
$from = "ящик-отправителя@yandex.ru";
MailSmtp($to, $title, $mess, $headers);

file send.php
Spoiler
<?php
// Buyme 1.3.5 2013 by Nazar Tokar
// dedushka.org * nazartokar.com * a@dedushka.org
require "smtp.php";
//адрес почты для отправки уведомления
$to = "ящик-получателя@mail.ru"; //несколько ящиков могут перечисляться через запятую

$HTTP_HOST = parse_url('http://'.$_SERVER["HTTP_HOST"]);
$HTTP_HOST = str_replace(array("http://","www."),"", $HTTP_HOST['host']);
$from = "ящик-отправителя@yandex.ru"; // отправитель

// данные для отправки смс

$sms["id"] = "";
$sms["key"] = "";
$sms["log"] = "";
$sms["pss"] = "";
$sms["frm"] = "callme"; // добавьте новую подпись в смс-шлюзе и дождитесь апрува
$sms["num"] = ""; // ваш номер в формате без + (79218886622)
$sms["prv"] = "sms.ru"; // на выбор: sms.ru, infosmska.ru, bytehand.com, sms-sending.ru, smsaero.ru

function uc ($s)
{
$s = urlencode($s);
return $s;
}

function gF ($s) // no shit
{
$s = substr( (htmlspecialchars($_GET[$s])), 0, 500);
if (strlen($s) > 1) return $s;
}

function echoResult ($result, $class, $time, $message) // выводим данные json
{
echo '{
"result": "'.$result.'",
"cls": "'.$class.'",
"time": "'.$time.'",
"message": "'.$message.'" }';
exit();
}

function sendSMS ($to, $msg){
global $sms;

$u['sms.ru'] = "sms.ru/sms/send?api_id=".uc($sms["key"])."&to=".uc($sms["num"])."&text=".uc($msg);
$u['bytehand.com'] = "bytehand.com:3800/send?id=".uc($sms["id"])."&key=".uc($key)."&to=".uc($sms["num"])."&partner=callme&from=".uc($sms["frm"])."&text=".uc($msg);
$u['sms-sending.ru'] = "lcab.sms-sending.ru/lcabApi/sendSms.php?login=".uc($sms["log"])."&password=".uc($sms["pss"])."&txt=".uc($msg)."&to=".uc($sms["num"]);
$u['infosmska.ru'] = "api.infosmska.ru/interfaces/SendMessages.ashx?login=".uc($sms['log'])."&pwd=".uc($sms["pss"])."&sender=SMS&phones=".uc($sms["num"])."&message=".uc($msg);
$u['smsaero.ru'] = "gate.smsaero.ru/send/?user=".uc($sms["log"])."&password=".md5 (uc($sms["pss"]))."&to=".uc($sms["num"])."&text=".uc($msg)."&from=".uc($sms["frm"]);

@$r = file_get_contents("http://".$u[$sms["prv"]]);
}

$l["sent"] = "Заказ уже был отправлен";
$l["err"] = "Пожалуйста, заполните все поля";
$l["ok"] = "Спасибо, заказ принят. Ждите звонка";
$l["title"] = "BuyMe: новый заказ";
$l["footer"] = "<p><a href='http://dedushka.org/tag/buyme/'>Следите</a> за обновлениями скрипта.<br>Спасибо за использование BuyMe.</p>";

function addToMess ($c, $o)
{
$s = "<p><b>".$c."</b>:<br>".$o."</p>";
return $s;
}

function getOptions ($o) // get fields
{
$captions = $_GET["cs"];
$options = $_GET["os"];
$opts = "";
$i = 0;

if ($o == 1) {
foreach ($options as $value)
{
if ( strlen($value) > 1 ) {
if ($captions[$i] == "url")
{
if (strlen($value) < 60)
{
$opts .= addToMess($captions[$i], $value);
}
else
{
$link = "<a href='".$value."'>".substr($value, 0, 60)."...</a>";
$opts .= addToMess($captions[$i], $link);
}
}
else
{
$opts .= addToMess($captions[$i], $value);
}
}
$i++;
}
} else {
foreach ($options as $value)
{
if ( strlen($value) > 1 ) {
$opts .= $captions[$i]."(".$value.") ";
}
$i++;
}
}
return $opts;
}

function translit ($str) // translit by programmerz.ru
{
$tr = array("А"=>"A","Б"=>"B","В"=>"V","Г"=>"G","Д"=>"D","Е"=>"E","Ё"=>"E","Ж"=>"J","З"=>"Z","И"=>"I","Й"=>"Y","К"=>"K","Л"=>"L","М"=>"M","Н"=>"N","О"=>"O","П"=>"P","Р"=>"R","С"=>"S","Т"=>"T","У"=>"U","Ф"=>"F","Х"=>"H","Ц"=>"C","Ч"=>"4","Ш"=>"SH","Щ"=>"SC","Ъ"=>"","Ы"=>"Y","Ь"=>"","Э"=>"E","Ю"=>"U","Я"=>"YA","а"=>"a","б"=>"b","в"=>"v","г"=>"g","д"=>"d","е"=>"e","ё"=>"e","ж"=>"j","з"=>"z","и"=>"i","й"=>"y","к"=>"k","л"=>"l","м"=>"m","н"=>"n","о"=>"o","п"=>"p","р"=>"r","с"=>"s","т"=>"t","у"=>"u","ф"=>"f","х"=>"h","ц"=>"c","ч"=>"4","ш"=>"sh","щ"=>"sch","ъ"=>"y","ы"=>"y","ь"=>"","э"=>"e","ю"=>"u","я"=>"ya");
return strtr($str,$tr);
}

// далее можно не трогать

$time = time(); // время отправки
$interval = $time - gF("time");
if ($interval < 1) // если прошло менее (сек)
{
echoResult('err', 'b1c-err', '', $l["sent"]);
} else {

$get_data = $_GET["cs"];

if (count($get_data) > 1) // data to send
{
$ip = $_SERVER['REMOTE_ADDR'];
$prd = gF("prd");

@$geo = file_get_contents('http://freegeoip.net/json/'.$ip);
@$geo = json_decode($geo, true);

$title = $l["title"];
$title = "=?UTF-8?B?".base64_encode($title)."?=";
$mess = "<h3>Заказ на ".$prd."</h3><div style='background:#fffce8;border:1px solid #cecece;padding:10px 10px 0'>";

$mess .= getOptions(1);

$mess .= addToMess("IP",$ip);
$mess .= addToMess("Откуда запрос",(($geo['city'])." (".($geo['country_name']).")" ));

$mess .= "</div>".$l["footer"];

$headers = "Content-type: text/html; charset=utf-8 \r\n";
$headers .= "From: BuyMe 1.3.5 <".$from.">\r\n";

$sms["msg"] = substr( translit($prd.",".(getOptions(0))), 0 ,160 );

MailSmtp($to, $title, $mess, $headers);
if ( ($sms["id"] != "") || ($sms["key"] != "") || ($sms["log"] != "") )
{
@sendSMS($num, $sms["msg"]);
}
echoResult("ok", "b1c-ok", $time, $l["ok"]);
} else {
echoResult("err", "b1c-err", "", $l["err"]);
}
}
?>
urok
Reputation: 1
Posts: 5
With us: 2 yaers 3 months

#18by foxsnort » 10.02.2014, 15:08

Друзья, подскажите, пожалуйста! Я новичок в этом, проблему гуглил, но так и не нашел решение((
Ситуация следующая: сервер на debian 7, настроил exim4, тестовое письмо получаю, все ок. Поставил скрипт callme, все настройки сделал по инструкции в начале этой темы. НО письма не приходят. Стал разбираться и вот что записывается в логах:

Spoiler
[Sat Feb 08 16:21:31 2014] [error] [client х.х.х.х] PHP Warning: fsockopen(): php_network_getaddresses: getaddrinfo failed: Name or service not known in /www/callme/lib/smtp.php on line 14, referer: http://mydomain.com/
[Sat Feb 08 16:21:31 2014] [error] [client х.х.х.х] PHP Warning: fsockopen(): unable to connect to smtp.domain.tld:25 (php_network_getaddresses: getaddrinfo failed: Name or service not known) in /www/callme/lib/smtp.php on line 14, referer: http://mydomain.com/
[Sat Feb 08 16:21:31 2014] [error] [client х.х.х.х] PHP Warning: fgets() expects parameter 1 to be resource, boolean given in /www/callme/lib/smtp.php on line 15, referer: http://mydomain.com/

Предполагаю, что косяк в настройках файла smtp.php?
foxsnort
Reputation: 0
Posts: 2
With us: 2 yaers 3 months

#19by Назар Токарь » 10.02.2014, 15:39

urok, ну на первый взгляд все правильно. А попробуйте закомментировать все строки с get_file_contents. У вас на хостинге может быть выключена эта функция, такое иногда бывает. Ну или банально на яндекса запрещена отправка через smtp для вашего ящика.

foxsnort, на хостинге запрещены эти функции, по которым варнинги. Нужно их попросить включить хостера. Ну или самому настроить.
Читайте твітер.
Назар Токарь M
Topic author, Администратор
Avatar
Location: Україна
Reputation: 140
Posts: 2352
Topics: 99
With us: 3 yaers 2 months

#20by foxsnort » 10.02.2014, 17:18

Назар Токарь, я так понимаю, что запрещена функция fsockopen? А включается она в php.ini строкой allow_url_fopen = On?
foxsnort
Reputation: 0
Posts: 2
With us: 2 yaers 3 months

Next

Return to Розробка

Who is online (over the past 30 minutes)

Users browsing this forum: 2 guests

cron