Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> SMTP отправка почты через сокет. Цикл, SMTP отправка почты через сокет. Цикл 
V
    Опции темы
BlackRu
Дата 4.7.2014, 16:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 431
Регистрация: 14.9.2009

Репутация: нет
Всего: 4



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

Могу ли я сделать так? Т.е. без цикла. 
Код


function ch_code(&$a, $smtp_conn) {

$a=fgets($smtp_conn,625);  
$a=substr($a,0,3);

}
$smtp_conn = fsockopen("smtp.rambler.ru", 25,$errno, $errstr, 10);
ch_code($a, $smtp_conn);
 
if(!$smtp_conn) {print "Connection Lost"; fclose($smtp_conn); exit;}
 
fputs($smtp_conn,"HELO rambler.ru\r\n"); 
ch_code($a, $smtp_conn);
 
 
fputs($smtp_conn,"AUTH LOGIN\r\n");
ch_code($a, $smtp_conn);

и т.д., и т.д.




Изначальный код из статьи: 
Код

<?php
function get_data($smtp_conn)
{
$data="";
while($str = fgets($smtp_conn,515)) 
{

$data .= $str;
if(substr($str,3,1) == " ") { break; }
}
return $data;
}

$header="Date: ".date("D, j M Y G:i:s")." +0700\r\n"; 
$header.="From: =?windows-1251?Q?".str_replace("+","_",str_replace("%","=",urlencode('Максим')))."?= <[email protected]>\r\n"; 
$header.="X-Mailer: The Bat! (v3.99.3) Professional\r\n"; 
$header.="Reply-To: =?windows-1251?Q?".str_replace("+","_",str_replace("%","=",urlencode('Максим')))."?= <[email protected]>\r\n";
$header.="X-Priority: 3 (Normal)\r\n";
$header.="Message-ID: <172562218.".date("YmjHis")."@mail.ru>\r\n";
$header.="To: =?windows-1251?Q?".str_replace("+","_",str_replace("%","=",urlencode('Сергей')))."?= <[email protected]>\r\n";
$header.="Subject: =?windows-1251?Q?".str_replace("+","_",str_replace("%","=",urlencode('проверка')))."?=\r\n";
$header.="MIME-Version: 1.0\r\n";
$header.="Content-Type: text/plain; charset=windows-1251\r\n";
$header.="Content-Transfer-Encoding: 8bit\r\n";

$text="привет, проверка связи.";

$smtp_conn = fsockopen("smtp.mail.ru", 25,$errno, $errstr, 10);
if(!$smtp_conn) {print "соединение с серверов не прошло"; fclose($smtp_conn); exit;}
$data = get_data($smtp_conn);
fputs($smtp_conn,"EHLO mail.ru\r\n");
$code = substr(get_data($smtp_conn),0,3);
if($code != 250) {print "ошибка приветсвия EHLO"; fclose($smtp_conn); exit;}
fputs($smtp_conn,"AUTH LOGIN\r\n");
$code = substr(get_data($smtp_conn),0,3);
if($code != 334) {print "сервер не разрешил начать авторизацию"; fclose($smtp_conn); exit;}

fputs($smtp_conn,base64_encode("login")."\r\n");
$code = substr(get_data($smtp_conn),0,3);
if($code != 334) {print "ошибка доступа к такому юзеру"; fclose($smtp_conn); exit;}


fputs($smtp_conn,base64_encode("password")."\r\n");
$code = substr(get_data($smtp_conn),0,3);
if($code != 235) {print "не правильный пароль"; fclose($smtp_conn); exit;}

fputs($smtp_conn,"MAIL FROM:[email protected]\r\n");
$code = substr(get_data($smtp_conn),0,3);
if($code != 250) {print "сервер отказал в команде MAIL FROM"; fclose($smtp_conn); exit;}

fputs($smtp_conn,"RCPT TO:[email protected]\r\n");
$code = substr(get_data($smtp_conn),0,3);
if($code != 250 AND $code != 251) {print "Сервер не принял команду RCPT TO"; fclose($smtp_conn); exit;}

fputs($smtp_conn,"DATA\r\n");
$code = substr(get_data($smtp_conn),0,3);
if($code != 354) {print "сервер не принял DATA"; fclose($smtp_conn); exit;}

fputs($smtp_conn,$header."\r\n".$text."\r\n.\r\n");
$code = substr(get_data($smtp_conn),0,3);
if($code != 250) {print "ошибка отправки письма"; fclose($smtp_conn); exit;}

fputs($smtp_conn,"QUIT\r\n");
fclose($smtp_conn);
?>



Извиняюсь за количество кода, могу сократить после ответа.
(Для практических целей использую Sendmail,  понять хочу для себя(в учебных целях).
 

Это сообщение отредактировал(а) BlackRu - 8.7.2014, 13:05


--------------------
Удалена администрацией форума
PM MAIL WWW Skype   Вверх
polls
Дата 8.7.2014, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 8.7.2014

Репутация: -1
Всего: -1



прошлое десятилетие,
отправляй почту через gmail из php
http://stackoverflow.com/questions/712392/...9-send-mail-php

в сутки с одного gmail акка можно отправить 500 писем, если ограничение не изменилось.

Это сообщение отредактировал(а) polls - 8.7.2014, 11:02
PM MAIL   Вверх
krundetz
Дата 8.7.2014, 16:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 20
Всего: 69



BlackRu, цикл так как:
1. ответ может иметь разную длину, а в коде есть ограничение в 515 символов (очень странное кстати)
2. ответ может состоять из нескольких строк, а fgets работает пока не достигнут конец строки

как работает fgets можно почитать на php.net

Цитата(polls @  8.7.2014,  11:01 Найти цитируемый пост)
прошлое десятилетие,
отправляй почту через gmail из php

человек же ясно сказал
Цитата(BlackRu @  4.7.2014,  16:01 Найти цитируемый пост)
 понять хочу для себя(в учебных целях).


Цитата(polls @  8.7.2014,  11:01 Найти цитируемый пост)
в сутки с одного gmail акка можно отправить 500 писем, если ограничение не изменилось.

это смешная цифра. Вы не представляете себе объемы коммерческой корреспонденции. Только писем по одному вопросу с одним клиентом может быть десятки, а иногда и сотни в день. Вопросов может быть несколько да и в нормальной организации клиентов не один два, а еще не стоит забывать про сотрудников. Про отправку заказов с магазинов говорить?

polls, вам минус:
1. за некомпетентность, к вашему сведению для отправки почты GMAIL использует туже самую технологию, которую пытается понять BlackRu и которую вы называете прошлым десятилетием
2. за ответ не по теме,  BlackRu четко и ясно выразился для чего он задает этот вопрос
3. безапеляционность, BlackRu что у него отправка работает и через что.
4. за неправильную вставку ссылок, если уж настаиваете на своем решение, а слово "отправляй" я по другому расценить не могу, и приводите ссылки на материалы, то потрудитесь их вставить так чтобы человек смог ими воспользоваться.
5. общая невнимательность.

Все в совокупности дало минус. Если бы вы сформулировали свой ответ по другому. Например:
Цитата

Я использую gmail почему бы тебе его тоже не попробовать, узнать о нем можно здесь и здесь, там правда есть ограничение в 500 писем с аккаунта.

в таком случае я бы списал ваш ответ просто на невнимательное изучение сообщения ТС и минуса бы не поставил.

Это сообщение отредактировал(а) krundetz - 8.7.2014, 16:58


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
_zorn_
Дата 9.7.2014, 05:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1077
Регистрация: 21.8.2007

Репутация: 6
Всего: 12



Цитата(krundetz @  9.7.2014,  00:29 Найти цитируемый пост)
BlackRu, цикл так как:
1. ответ может иметь разную длину, а в коде есть ограничение в 515 символов (очень странное кстати)
2. ответ может состоять из нескольких строк, а fgets работает пока не достигнут конец строки

Так то оно так, но там нужно 3 первых символа - поэтому особого смысла в цикле нет.
И да, можно заюзать fread вместо fgets, но здесь все равно без разницы.

И цикл там все равно не правильный. Что будет если встретится стока состоящая из одного символа "0" ?

Это сообщение отредактировал(а) _zorn_ - 9.7.2014, 05:18
PM MAIL   Вверх
krundetz
Дата 9.7.2014, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 20
Всего: 69



Цитата(_zorn_ @  9.7.2014,  05:03 Найти цитируемый пост)
Так то оно так, но там нужно 3 первых символа - поэтому особого смысла в цикле нет.

вот пример обмена сообщениями
Код

220 smtp25.mail.ru ESMTP ready
EHLO bob.examle.org
250-smtp25.mail.ru
250-SIZE 73400320
250-8BITMIME
250-PIPELINING
250-AUTH PLAIN LOGIN XOAUTH2
250 STARTTLS

а теперь вопрос, как быть если нужно узнать SIZE?

Цитата(_zorn_ @  9.7.2014,  05:03 Найти цитируемый пост)
И цикл там все равно не правильный. 

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

Я сделал хотя бы так:
Код

function getResponse($socet) {
    $response = '';
    while($str = fgets($socet)) {
        $response .= $str;
    }
    return $response;
}
function getCode($response) {
    return substr($response, 0, 3);
}

так как могут понадобиться и другие данные из ответа.

Цитата(_zorn_ @  9.7.2014,  05:03 Найти цитируемый пост)
Что будет если встретится стока состоящая из одного символа "0" ?

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

ИМХО, программист который создавал код, взятый за основу BlackRu, либо не до конца понимает что он делает и на чем, либо делал времянку для чего то. Вот поэтому и код такой же.

Это сообщение отредактировал(а) krundetz - 9.7.2014, 10:55


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
_zorn_
Дата 10.7.2014, 05:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1077
Регистрация: 21.8.2007

Репутация: 6
Всего: 12



Цитата(krundetz @  9.7.2014,  18:29 Найти цитируемый пост)
Не совсем понял имеется в виду нуль символ или строка из нуля?

Я имел ввиду что то типа такого
Код
afafwwf
gggw
0
this is the end
but we not get it

Понимаю что в данном случае такое вряд ли встретится, однако...
Код
while(($str = fgets($socet))!==false)


PM MAIL   Вверх
krundetz
Дата 10.7.2014, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 20
Всего: 69



_zorn_, нет, ваш вариант:
1. не обработает ситуацию когда в ответ возвращаются неправильные данные
2. не имеет смысла, так как fgets() всегда возвращает строку

Если надо обработать правильность входящих данных, то как то так:
Код

function isVaild($response) {
    rerurn preg_match_all('/(\d){3}(\s|-).*/', $response);
}

Не совсем уверен, что правильно будут обработаны несколько строк. Надо еще подумать.

Или можно пойти дальше извлекая только данные соответствующие шаблону:
Код

function getData($response) {
    $data = array();
    $matches = array();
    $count = preg_match_all('/(\d){3}(\s|-).*/', $response, $macthes);
    for($i = 0; $i < $count; $i++) {
        $data[$i]['code'] = $matches[$i][1];
        $data[$i]['message'] = $matches[$i][3];
    }
    return $data;
}

P.S. Данный код совсем не оптимален приведен как отправная точка для дальнейших размышлений.

Это сообщение отредактировал(а) krundetz - 11.7.2014, 11:14


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
BlackRu
Дата 10.7.2014, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 431
Регистрация: 14.9.2009

Репутация: нет
Всего: 4



Спасибо, 
krundetz
_zorn_

Уже не ожидал ответа, поэтому пропал.   
Ага, этот 4  (получается по счету) символ - пробел, по которому происходит выход из цикла, может оказаться в ответе сервера и не пробелом. Если я не ошибаюсь.

Это сообщение отредактировал(а) BlackRu - 10.7.2014, 23:16


--------------------
Удалена администрацией форума
PM MAIL WWW Skype   Вверх
_zorn_
Дата 11.7.2014, 02:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1077
Регистрация: 21.8.2007

Репутация: 6
Всего: 12



Цитата(krundetz @  10.7.2014,  18:35 Найти цитируемый пост)
2. не имеет смысла, так как fgets() всегда возвращает строку

Вы забываете одну "приятную" особенность ПХП - динамические типы данных.

Код
<?php
if('0'==0) echo "OLOLO1\n";
if('0'===0) echo "OLOLO2\n";
if(0==false) echo "OLOLO3\n";
if('0'==false) echo "OLOLO4\n";
if('0'===false) echo "OLOLO5\n";

Код
OLOLO1
OLOLO3
OLOLO4


http://ideone.com/8svgZ2
PM MAIL   Вверх
BlackRu
Дата 11.7.2014, 08:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 431
Регистрация: 14.9.2009

Репутация: нет
Всего: 4



Т.е. суммируя вышесказанное, если я правильно понимаю: 
  • Желательно получить всю строку, которая будут в ответе сервера?! 
  • Найти в этой строке числовой трехзначный код?! 
  • Проверить расположение кода относительно предыдущей и следующей подстроки?! Убедиться, что код не прикленн к другим данным.


Интересно, какова вероятность, что код ответа будет не вначале, а где-нибудь в середине или конце строки?

Т.е., получается, получив строку ответа, желательно проверить наличие в ней трехзначного кода? Если данные неправильные (по каким-то причинам), то следует повторить последний запрос?

 

Это сообщение отредактировал(а) BlackRu - 11.7.2014, 09:00


--------------------
Удалена администрацией форума
PM MAIL WWW Skype   Вверх
krundetz
Дата 11.7.2014, 09:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 20
Всего: 69



Цитата(BlackRu @  11.7.2014,  08:54 Найти цитируемый пост)
Желательно получить всю строку, которая будут в ответе сервера?! 

Да, желательно получать весь ответ сервера, который может состоять из нескольких строк. И только после этого с ним работать.
Цитата(BlackRu @  11.7.2014,  08:54 Найти цитируемый пост)
Найти в этой строке числовой трехзначный код?! 

Да, необходимо найти код ответа сервера который должен стоять в начале каждой строки.  От него и переданных на сервер данных будет зависеть дальнейшее поведение программы.
Цитата(BlackRu @  11.7.2014,  08:54 Найти цитируемый пост)
Проверить расположение кода относительно предыдущей и следующей подстроки?! Убедиться, что код не прикленн к другим данным.

Да.
Цитата(BlackRu @  11.7.2014,  08:54 Найти цитируемый пост)
Интересно, какова вероятность, что код ответа будет не вначале, а где-нибудь в середине или конце строки?

Вероятность должна стремиться к 0, но это не значит, что входящие данные не нужно проверять на корректность. Так как по идее имея собственный "почтовый сервер" с которым ваша программа будет общаться можно вести исследование на проникновение, на ваш сервер.
Цитата(BlackRu @  11.7.2014,  08:54 Найти цитируемый пост)
Если данные неправильные (по каким-то причинам), то следует повторить последний запрос?

Нет. Если ответ сервера не предусмотрен сценарием работы программы, то повтор запроса бессмыслен, следует просто прекратить обработку отправки этого письма на этот сервер и записать информацию об этом в лог.


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
krundetz
Дата 11.7.2014, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 20
Всего: 69



Цитата(_zorn_ @  11.7.2014,  02:50 Найти цитируемый пост)
Вы забываете одну "приятную" особенность ПХП - динамические типы данных.

да вы правы, не учел. smile  Следовательно меняем код на такой:
Код

function getResponse($socet) {
    $response = '';
    while(($str = fgets($socet)) !== false) {
        $response .= $str;
    }
    return $response;
}


Цитата(krundetz @  10.7.2014,  10:35 Найти цитируемый пост)
P.S. Данный код совсем не оптимален приведен как отправная точка для дальнейших размышлений.

Понял несколько моментов который меня смущали.

1. В моём коде нет проверки на начало строки поэтому такая строка:
Код

dfg250 bad string

тоже подпадет под него. Хотя на нее надо выводить ошибку.

2. Также нет проверки на то что между строками ответа может затесаться неправильная строка, вот так например:
Код

250-smtp25.mail.ru
bad string
250 STARTTLS


Это сообщение отредактировал(а) krundetz - 11.7.2014, 11:11


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
krundetz
Дата 11.7.2014, 12:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вечный странник
***


Профиль
Группа: Завсегдатай
Сообщений: 1400
Регистрация: 14.6.2007
Где: НН(Сормово)

Репутация: 20
Всего: 69



немного допилил getData()
Код

function getData($response) {
    $data = array();
    $matches = array();
    $count = preg_match_all('/(\d{3,})(\s|-)(.*)/', $response, $matches, PREG_PATTERN_ORDER);
    for($i = 0; $i < $count; $i++) {
        $data[$i]['code'] = $matches[1][$i];
        $data[$i]['message'] = $matches[3][$i];
    }
    return $data;
}


http://ideone.com/Phqy1b

Это сообщение отредактировал(а) krundetz - 11.7.2014, 12:43


--------------------
!цензоры - Хранитель стратегической жидкости
Группа ТГВ
Группа Нижний Новгород
user posted image
PM MAIL   Вверх
BlackRu
Дата 11.7.2014, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 431
Регистрация: 14.9.2009

Репутация: нет
Всего: 4



krundetz, спасибо огромное за подробные ответы и пример кода. Начинаю вникать. 

Это сообщение отредактировал(а) BlackRu - 11.7.2014, 14:41


--------------------
Удалена администрацией форума
PM MAIL WWW Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1031 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.