Jump to content
  • 0

Письма, то приходили на почту, то нет. А оказалась проблема в... Но почему?


Zverushka
 Share

Question

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

<?php$mail3 = 'svcxxxt@inbox.ru'; //поддельный адрес$name = '';	$phone = '';    function getIp(){if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){	$ip_address=$_SERVER['HTTP_X_FORWARDED_FOR'];}if (!isset($ip_address)){		if (isset($_SERVER['REMOTE_ADDR']))			$ip_address=$_SERVER['REMOTE_ADDR'];}return $ip_address;}//taking info about date, IP and user agent$timestamp = date("Y-m-d H:i:s");$ip   = getIp();$host = gethostbyaddr($ip); $user_agent = $_SERVER["HTTP_USER_AGENT"];	//taking the data from form	$name = addslashes(trim($_POST['name']));	$phone = addslashes(trim($_POST['phone']));//preparing mail		$headers = "MIME-Version: 1.0\n";$headers .= "Content-type: text/html; charset=utf-8\n";$headers .= "Content-Transfer-Encoding: quoted-printable\n";$headers .= "From: $mail\n";$content = 'name: '.$name.'<br>'.'phone: '.$phone.'<br>';'IP: '.$host.'<br>'.'User agent: '.$user_agent;//sending mailif (!mail($mail3,"Охранные видеосистемы: заявка от ".$name." тел.: ".$phone, $content, $headers)){	echo "error";}?>

На хостинге моего клиента - письма приходили раз через раз. То есть первые 6 не приходят, 7 приходит. Дописала для рассылки еще 1 один емейл. Ситуация вообще такая - на первый е-мейл пришло, на втором пусто и наоборот.

При этом от меня письма доходили влегкую.

На крайний случай я решила закомментировать эти строки кода

<?php$mail3 = 'svcxxxt@inbox.ru'; //поддельный адрес$name = '';	$phone = '';    // function getIp()// {if(isset($_SERVER['HTTP_X_FORWARDED_FOR'])){// 	$ip_address=$_SERVER['HTTP_X_FORWARDED_FOR'];// }// if (!isset($ip_address)){// 		if (isset($_SERVER['REMOTE_ADDR']))	// 		$ip_address=$_SERVER['REMOTE_ADDR'];// }// return $ip_address;// }//taking info about date, IP and user agent// $timestamp = date("Y-m-d H:i:s");// $ip   = getIp();// $host = gethostbyaddr($ip); // $user_agent = $_SERVER["HTTP_USER_AGENT"];	//taking the data from form	$name = addslashes(trim($_POST['name']));	$phone = addslashes(trim($_POST['phone']));//preparing mail		$headers = "MIME-Version: 1.0\n";$headers .= "Content-type: text/html; charset=utf-8\n";$headers .= "Content-Transfer-Encoding: quoted-printable\n";$headers .= "From: $mail\n";$content = 'name: '.$name.'<br>'.'phone: '.$phone.'<br>';// 'IP: '.$host.'<br>'.// 'User agent: '.$user_agent;//sending mailif (!mail($mail3,"Охранные видеосистемы: заявка от ".$name." тел.: ".$phone, $content, $headers)){	echo "error";}?>

И у него все стало приходить.

Кто-нибудь может объяснить в чем была причина такого странного поведения? Есть ли в этом коде внутрення ошибка, что письма доходили через раз?

Edited by Zverushka
Link to comment
Share on other sites

22 answers to this question

Recommended Posts

  • 0

 

$ip_address=$_SERVER['HTTP_X_FORWARDED_FOR'];

 

...

// $host = gethostbyaddr($ip);

 

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

Link to comment
Share on other sites

  • 0

Ну допустим он не резолвится, но ведь должно хоть с каким-нибудь содержанием отправиться письмо?

При этом на первый ящик оно не отправляется, а на второй отправляется или даже НАОБОРОТ!

Link to comment
Share on other sites

  • 0

Зашла на фтп-сервер, ерор лога на нем нету. Зашла через спанель - нажала просмотреть лог - лог пуст.
Кстати хостинг http://www.hostinger.ru/

При этом на моем аккаунте бесплатно все письма приходили. (вроде, сейчас точно уточню!)

 
Уточнила по моему сайту - с него также не приходят сообщения, то есть, то нету.
 
 

А на его (тоже бесплатно), но посаженным на посторонний домен - нет.

При этом у них на сайте есть предупреждение: 

 

Your domain is not pointing to our nameservers at the moment, so services such as FTP, File Manager, E-mail (and others) will not work correctly.


А что сказал error.log сервера? Теоретически, скрипт мог нормально дорабатывать до ошибки, а на ней валиться намертво...

У меня на скрипте отправки стоит ajax, если сообщение сервера пустое - то отправка успешна. Если хоть какой-то символ или сообщение есть в файле - то отправка не успешна. Но все сообщения выдавались, что отправка успешна.

var data = $(this).serialize();				var answer = $.post("contact.php", data).done(function(msg){					if (msg==""){						$("#offer").hide();						$(".thankyou").modal({							autoStyle: false,							center : false						});											}					else {												alert("Не удалось отправить заявку");					}				}).fail(function(){					alert("Произошла ошибка при отправке данных на сервер");				});	
Edited by Zverushka
Link to comment
Share on other sites

  • 0

Тогда не вижу другого пути узнать правду, кроме как перенастроить error_reporting и display_errors для отладки.

 

Но в любом случае не вижу смысла анализировать тут HTTP_X_FORWARDED_FOR и подобное. Я бы прикладывал к письму один лишь «честный» айпишник отправителя (т.е. обычный REMOTE_ADDR), если понадобится узнать, чей он и прочее — это может сделать и тот, кто разбирает заявки, слишком автоматизировать это (к тому же усложняя и замедляя скрипт рассылки лишним для дела обращением к DNS).

 

Кстати, в мане PHP 3-й коммент — возможно, как раз про эту ошибку.

 

 

 

если сообщение сервера пустое - то отправка успешна

 

Если в настройках PHP стоит display_errors = off, то при падении скрипта с ошибкой сообщение сервера останется пустым, с обычным статусом 200. Для отладки, имхо, лучше врубить display_errors и вызывать скрипт напрямую.

Link to comment
Share on other sites

  • 0

Такая проблема будет возникать на любом сервере с этим скриптом или это особенность сервера?

А по поводу ошибок. На обычных ошибках, вроде синтаксических - сервер выдает ошибки. Значит директива включена?

Edited by Zverushka
Link to comment
Share on other sites

  • 0
Такая проблема будет возникать на любом сервере с этим скриптом?

Сложно сказать, но этот кусок скрипта 1) судя по всему, ошибочен логически, 2) содержит потенциально слабое звено в лице gethostbyaddr. Лучше таких вещей по возможности избегать.

 

На обычных ошибках, вроде синтаксических - сервер выдает ошибки. Значит директива включена?

Видимо, да (хотя неплохо бы еще значение error_reporting проверить).

Link to comment
Share on other sites

  • 0

Я сейчас оставила только время и ип адрес через  remote_addr, теперь не знаю, что делать с предыдущими сайтами с этим кодом. Никто не жаловался, хостинги везде разные - есть ли там такая проблема или она возникает только на этом хостинге =(.... Я всегда по 10 раз формы тестировала и у меня никогда не возникало проблем - все данные приходили на почту, а тут такая засада...

Edited by Zverushka
Link to comment
Share on other sites

  • 0

Я сейчас оставила только время и ип адрес через  remote_addr, теперь не знаю, что делать с предыдущими сайтами с этим кодом. Никто не жаловался, хостинги везде разные - есть ли там такая проблема или она возникает только на этом хостинге =(.... Я всегда по 10 раз формы тестировала и у меня никогда не возникало проблем - все данные приходили на почту, а тут такая засада...

На хостингере функционал подрезан в целях  безопасности. много чего не работает

Link to comment
Share on other sites

  • 0

HTTP_X_FORWARDED_FOR штука интерессная и в данном случае боюсь непригодна.

вот почитайте - первые в яндексе

http://www.phpfaq.ru/ip

http://habrahabr.ru/post/177113/

 

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

а потом вы подсовывали это сюда - gethostbyaddr()... короче не заморачивайтесь, мне кажется php был в замешательстве, когда для определения имени сервера вместо ip ему подсовывали фигпоймичто =)

 

upd: на хостингере $_server(HTTP_X_FORWARDED_FOR ) - вообще ошибку выдаёт

Edited by Николя223
  • Like 1
Link to comment
Share on other sites

  • 0

@Николя223, когда я с хостингера отправляю этим скриптом, у меня никаких ошибок. Но может на это влияет файрволл и подобные штуки, стоящие у пользователя, когда сервер не может получить айпи...?... Как думаешь, на других хостерах может не быть такой проблемы у этих пользователей, которые отправляли письма с хостингера и письма не приходили. ?...

Link to comment
Share on other sites

  • 0

Как думаете - этот вариант корректный? (в чужом коде нашла)

function get_real_ip() {	$result = NULL;	if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {		if(substr_count($_SERVER['HTTP_X_FORWARDED_FOR'], ',')) {			$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);			if(trim($ips[count($ips)-1]) == $_SERVER['HTTP_X_REAL_IP']) {				unset($ips[count($ips)-1]);			}			$result = trim($ips[count($ips)-1]);		} else {			$result = $_SERVER['HTTP_X_FORWARDED_FOR'];		}	} elseif (isset($_SERVER['HTTP_X_REAL_IP'])) {		$result = $_SERVER['HTTP_X_REAL_IP'];	} elseif(isset($_SERVER['REMOTE_ADDR'])) {		$result = $_SERVER['REMOTE_ADDR'];	}	return trim($result);}
Link to comment
Share on other sites

  • 0

ну потестируй... По коду вроде работать должен

если существует  HTTP_X_FORWARDED_FOR, то если в нем один IP он и возвращается , либо строка разбивается в массив и возвращается последний IP с учетом удаления $_SERVER['HTTP_X_REAL_IP'])

 

Иначе возвращается как раз  $_SERVER['HTTP_X_REAL_IP'])

 

И если нет ни того не другого возвращается  $_SERVER['REMOTE_ADDR'])

 

Зачем только весь этот гемор

Link to comment
Share on other sites

  • 0

ХЗ. Кстати этот скрипт, но там еще строки кода, геолокейшин - с еще одним внутренним багом, причину, я так и не нашла. например. если в нем есть строка с номером телефона - сообщение якобы отправляется, но не приходит на почту (на 2х разных серверах). При этом я мониторю содержимое тело письма - с ним все нормально, но стоит помимо обычного  ряда строк добавить телефон или время отправки - письмо где-то теряется. 2 часа потратила на поиск бага - нашла строчку (1 строка с номером - если ее закомментить, все работает), где это происходит. Но так и не поняла почему и откуда. Все стерла, вписала свой код обычный - работает.

Edited by Zverushka
Link to comment
Share on other sites

  • 0

На хостингере нет логов. Да и допустим, когда был баг, описанный в первом сообщении этой темы - все логи были кристально чистыми...

Edited by Zverushka
Link to comment
Share on other sites

  • 0

Логи апача и пхп тут мало помогут(если, конечно, скрипт работает без ошибок). Дело в том, что php-функция отправки почтового сообщения mail - есть посредник к sendmail, который установлен на сервере и на который пхп должен быть настроен.

 

Вызов функции mail - это обращение к sendmail, и возвращаемый результат true - говорит только о том, что письмо принято на отправку почтовиком, а не как не гарантия того, что это письмо дойдет до адресата. Тут если и смотреть на логи то, на логи самого почтовика, которые никто не показывает на хостинге.

 

С версии 5.3 в конфиге пхп есть параметр mail.log. Можно его попробовать выставить, но опять таки там будет фиксироваться факт передачи сообщения почтовику.

 

Если письма то доходят, то нет - попробуйте попытаться периодически отправлять одно и тоже письмо на один и тот-же ящик. Дело в том, что на хостингах частенько бывает, что ip, с которого уходят письма попадает в "черные спам-списки" и поэтому некоторые почтовые сервера могут игнорить письма с этого ip, если он присутствует в черных списках.  Если окажется, что письма все таки доходят, но с пропусками - причина не в спам фильтрах.

 

И еще можно проверить наличие ip в черных списках: https://www.google.com.ua/search?q=ip+email+black+list.

 

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

Edited by CoDy
Link to comment
Share on other sites

  • 0

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

$dt        = date("d.m.Y H:i:s");$to        = "anonym@yandex.ru";$title     = $post["type"] == 'order' ? "Заявка на занятие" : "Заявка на обратный звонок";$mess      = "Имя: <b>{$post["name"]}</b><br>";$mess     .= "Телефон: <b>{$post["phone"]}</b><br>";//$mess     .= "Email: <b>{$post["email"]}</b><br>";$mess     .= "Адрес: <b>{$address}</b> (IP: {$ip})<br>";$mess     .= "Отправлено с формы: <b>" . ($post["type"] == 'order' ? "Заявка на занятие" : "Заказ звонка'") . "</b><br>";$mess     .= "Сообщение с сайта:  <b>m-zebra.ru</b><br>";$mess     .= "Дата и Время: <b>{$dt}</b>";$headers   = "MIME-Version: 1.0\r\n";$headers  .= "Content-type: text/html; charset=UTF-8\r\n";$headers  .= "From: юныйпобедитель.рф<no-reply@юныйпобедитель.рф>\r\n";mail($to, $title, $mess, $headers);

Тело письма

Если оставить только $mess = "Имя: <b>{$post["name"]}</b><br>"; - сообщение приходит, при этом если к нему добавить некоторые строки - тоже приходит, но вот  телефоном или датой - отказывается приходить.

 

Что имеется из пхп набора

 

Файл order.php

<?phperror_reporting(E_ERROR);include './tools.php';if(empty($_POST["type"])) return;foreach($_POST as $k => $v) {	$post[$k] = clear_input($v);}/** * GEO */include './ipgeobase/ipgeobase.php';$lgeo = new ipgeobase();$ip   = get_real_ip();$GEO  = $lgeo->getRecord($ip);$address = !empty($GEO["region"]) ? "{$GEO["region"]}, {$GEO["city"]}" : '<не определен>';/** * Отправка письма */$dt        = date("d.m.Y H:i:s");$to        = "anonym@yandex.ru";$title     = $post["type"] == 'order' ? "Заявка на занятие" : "Заявка на обратный звонок";$mess      = "Имя: <b>{$post["name"]}</b><br>";$mess     .= "Телефон: <b>{$post["phone"]}</b><br>";//$mess     .= "Email: <b>{$post["email"]}</b><br>";$mess     .= "Адрес: <b>{$address}</b> (IP: {$ip})<br>";$mess     .= "Отправлено с формы: <b>" . ($post["type"] == 'order' ? "Заявка на занятие" : "Заказ звонка'") . "</b><br>";$mess     .= "Сообщение с сайта:  <b>m-zebra.ru</b><br>";$mess     .= "Дата и Время: <b>{$dt}</b>";$headers   = "MIME-Version: 1.0\r\n";$headers  .= "Content-type: text/html; charset=UTF-8\r\n";$headers  .= "From: юныйпобедитель.рф<no-reply@юныйпобедитель.рф>\r\n";mail($to, $title, $mess, $headers);/** * Ответ */if (in_array(date('w'), array(1,2,3,4,5)) && date('G') < 9) {	$mess = "Сегодня наш рабочий день еще не начался.<br>Сегодня с утра мы вам перезвоним";} elseif (in_array(date('w'), array(1,2,3,4)) && date('G') > 17) {	$mess = "Сегодня наш рабочий день уже закончился.<br>Завтра с утра мы вам перезвоним";} elseif (in_array(date('w'), array(5)) && date('G') > 17) {	$mess = "Сегодня наш рабочий день уже закончился.<br>В понедельник мы вам перезвоним";} elseif (in_array(date('w'), array(0,6))) {	$mess = "Сегодня у нас выходной.<br>В понедельник мы вам перезвоним";} else {	$mess = "В течении нескольких минут вам перезвонит наш менеджер";}if($post["type"] == 'order') {	echo "	<div class='thanx'>		<h3>Ваша заявка отправлена</h3>		<p>{$mess}</p>		<p><a href='#' class='return' onclick='return false;'>вернуться к форме</a></p>	</div>";} else {	echo "	<div class='thanx'>		<h3>Спасибо, ваша заявка принята.</h3>		<p>{$mess}</p>		<p><a href='#' class='return' onclick='return false;'>вернуться на сайт</a></p>	</div>";}/** * Статистика */$content = file_get_contents('./stats.txt');if(!empty($content)) {	$data = explode('|', $content);} else {	$data = array('orders', 0, 'calls', 0);}if($post["type"] == 'order') {	$data[1]++;} else {	$data[3]++;}file_put_contents('./stats.txt', implode('|', $data));?>

Файл tools.php

<?function clear_input($str){	$search = array('"', "'", "«", "»", "<", ">");	$replace = array('"', "'", "«", "»", "<", ">");	$str = str_replace($search, $replace, $str);	return $str;}function get_real_ip() {	$result = NULL;	if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {		if(substr_count($_SERVER['HTTP_X_FORWARDED_FOR'], ',')) {			$ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);			if(trim($ips[count($ips)-1]) == $_SERVER['HTTP_X_REAL_IP']) {				unset($ips[count($ips)-1]);			}			$result = trim($ips[count($ips)-1]);		} else {			$result = $_SERVER['HTTP_X_FORWARDED_FOR'];		}	} elseif (isset($_SERVER['HTTP_X_REAL_IP'])) {		$result = $_SERVER['HTTP_X_REAL_IP'];	} elseif(isset($_SERVER['REMOTE_ADDR'])) {		$result = $_SERVER['REMOTE_ADDR'];	}	return trim($result);}function get_city_prepositional_сase() {	include './ipgeobase/ipgeobase.php';	$lgeo = new ipgeobase();	$GEO  = $lgeo->getRecord(get_real_ip());	if(empty($GEO["city"])) {		return FALSE;	}	include './ipgeobase/cities.php';	return !empty($cities[$GEO["city"]]) ? $cities[$GEO["city"]] : FALSE;}?>

И папка с \ipgeobase\ - какая-то вспомогательная тулза

 

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

Edited by Zverushka
Link to comment
Share on other sites

  • 0

Да, там реально оказалось порезано. Эти скрипты работают на родном хостинге заказчика.

Интересно только - в платной версии хостингера все заработает?....

Link to comment
Share on other sites

  • 0
Интересно только - в платной версии хостингера все заработает?....

А теперь всё ясно ))) Если хостинг бесплатный, то я понимаю почему там много не пашет и порезано ))) Это нормально. В платной с вероятностью 99% заработает.

На халяве часто режут всё что только можно чтобы стимулировать клиентов переходить на платные тарифы.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy