Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.9.175] |
|
Сообщ.
#1
,
|
|
|
Всем привет. Недавно начал разбираться с сокетами, написал пару простых программ для обмена данными по локальной сети. Сейчас захотел попробовать подключиться к smtp-серверу для отправки email письма и возникли некоторые сложности, решения которых я не нашел в google.
DWORD SendMessage(const char * email, const char * msg, const char * from) { WSADATA _wsa; WSAStartup(MAKEWORD(2,2), &_wsa); hostent * h; int handle = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if(handle <= 0) printf("Error with creation socket %i", GetLastError()); char * em = getSMTPServer(email); h = gethostbyname(em); delete em; if(h == NULL) { printf("ERROR WITH GETTING HOSTBYNAME - %i\n", GetLastError()); closesocket(handle); return EXIT_FAILURE; } sockaddr_in destination; destination.sin_family = AF_INET; destination.sin_port = htons(25); destination.sin_addr.s_addr = *((unsigned long *) h->h_addr); if(connect(handle,(const sockaddr *)&destination, sizeof(sockaddr_in) == SOCKET_ERROR)) { printf("ERROR WITH CONNECT SMTP-SERVER - %i\n", GetLastError()); closesocket(handle); return EXIT_FAILURE; } ... WSACleanup(); } Функция getSMTPServer() самописная и возвращает smtp-сервер, основываясь на email-адресе. После вызова функции connect() возвращается SOCKET_ERROR и GetLastError() == 10014 |
Сообщ.
#2
,
|
|
|
Тебе интересно чисто разобраться?
Есть два момента, я не знаю с кем ты хочешь связать по 25 порту, но это обычный SMTP вроде и многие так уже не работают, а только с SSL ну и другим портом. И еще если ты пользуешься например gmail или еще кем не своим, полезь в настройки почты и сделай доступным для внешних программ. |
Сообщ.
#3
,
|
|
|
Цитата linuxoid @ После вызова функции connect() возвращается SOCKET_ERROR и GetLastError() == 10014 А что означает эта ошибка, ты посмотрел ? Попробуй так: .. if(connect(handle,(const sockaddr *)&destination, sizeof(destination) == SOCKET_ERROR)) .. connect, пример Исходники sources.ru |
Сообщ.
#4
,
|
|
|
Цитата ter_nk_ @ Тебе интересно чисто разобраться? Есть два момента, я не знаю с кем ты хочешь связать по 25 порту, но это обычный SMTP вроде и многие так уже не работают, а только с SSL ну и другим портом. И еще если ты пользуешься например gmail или еще кем не своим, полезь в настройки почты и сделай доступным для внешних программ. не просто разобраться, а сделать так, чтобы письмо все-таки отправилось куда нужно. Наткнулся на статью, в которой говорилось что smtp использует 25 порт, вот я и пробую, возможно, это и правда уже неактуально и следует пробовать другой порт. Но если я буду использовать порт с ssl тогда мне нужно использовать шифрование. Я хотел написать на чистом С, без подключения сторонних библиотек. |
Сообщ.
#5
,
|
|
|
Вполне возможно что самописная функция неверно формирует аргумент для gethostbyname()
Проверьте - поле h_addr структуры hostent Скажем распечатайте. |
Сообщ.
#6
,
|
|
|
Цитата linuxoid @ не просто разобраться, а сделать так, чтобы письмо все-таки отправилось куда нужно. Наткнулся на статью, в которой говорилось что smtp использует 25 порт, вот я и пробую, возможно, это и правда уже неактуально и следует пробовать другой порт. Но если я буду использовать порт с ssl тогда мне нужно использовать шифрование. Я хотел написать на чистом С, без подключения сторонних библиотек. А ты пробовал смотреть не статью, а конкретные настройки сервера, они могут убирать такие дыры безопасности, кто сейчас 25 порт использует? |
Сообщ.
#7
,
|
|
|
Цитата ter_nk_ @ А ты пробовал смотреть не статью, а конкретные настройки сервера, они могут убирать такие дыры безопасности, кто сейчас 25 порт использует? я попробовал. Можно законнектится на smtp.mail.ru:25. С операцией "connect" нет проблем. |
Сообщ.
#8
,
|
|
|
Цитата ЫукпШ @ я попробовал. Можно законнектится на smtp.mail.ru:25. С операцией "connect" нет проблем. С gmail это не пройдет. |
Сообщ.
#9
,
|
|
|
Согласен, что почтовик может и требовать аутентификации, и совсем на другой порт и прочая.
Но в любом случае коннект все равно проходил бы, если связка Ip:port была бы реальной. А тут сам коннект не проходит - т.е. первый SYN не находит адресат... |
Сообщ.
#10
,
|
|
|
Цитата ter_nk_ @ Цитата ЫукпШ @ я попробовал. Можно законнектится на smtp.mail.ru:25. С операцией "connect" нет проблем. С gmail это не пройдет. Предлагаешь все сервера проверять ? |
Сообщ.
#11
,
|
|
|
Извините не знал. У них в настройках для клиента указан только порт с SSL, да я думал на хрена типа оставлять обычный.
|
Сообщ.
#12
,
|
|
|
Именно поэтому я считаю что засада в формировании адреса почтовика...
|
Сообщ.
#13
,
|
|
|
Доброго всем дня. Не был дома несколько дней, не мог отвечать вам на форуме. По поводу ваших доводов о неправильной работе getSMTPServer(const char * email);
Возвращаемое значение функцией перед инициализацией gethostbyname(); Прикреплённая картинка
структура hostent после инициализации: Прикреплённая картинка
Кажется, что все в порядке с этим |
Сообщ.
#14
,
|
|
|
И тем не менее для коннекта эта ошибка обозначает неверно сформированный адрес назначения.
У меня вызывает подозрение приведение типа destination.sin_addr.s_addr = *((unsigned long *) h->h_addr); Такая запись характерна для связывания локального сокета для BIND на сервере. Попробуйте привести к типу struct in_addr таким образом destination.sin_addr = * ((struct in_addr *) h-> h_addr); И еще проверка - просто возьмите значение возвращенное значение h_addr и посмотрите - получается ли IP-адрес назначения. Адрес идет уже в сетевом порядке. |
Сообщ.
#15
,
|
|
|
Цитата Oleg2004 @ И тем не менее для коннекта эта ошибка обозначает неверно сформированный адрес назначения. У меня вызывает подозрение приведение типа destination.sin_addr.s_addr = *((unsigned long *) h->h_addr); Такая запись характерна для связывания локального сокета для BIND на сервере. Попробуйте привести к типу struct in_addr таким образом destination.sin_addr = * ((struct in_addr *) h-> h_addr); И еще проверка - просто возьмите значение возвращенное значение h_addr и посмотрите - получается ли IP-адрес назначения. Адрес идет уже в сетевом порядке. Попробовал изменить преобразование типов как указали Вы, но результата это особого не дало. Структура sin_addr заполнилась тем же самым IP-адресом, с которым я и пытался установить соединение. [attach=#0][/attach] Кстати, попробовал вывести на консоль значение h->h_addr; Результат следующий: [attach=#1][/attach] Возможно, в этом и таится проблема? или такое значение это норма? Прикреплённая картинка
Прикреплённая картинка
|
Сообщ.
#16
,
|
|
|
Цитата Oleg2004 @ Попробуйте привести к типу struct in_addr таким образом destination.sin_addr = * ((struct in_addr *) h-> h_addr); Тест я делал так: hostent *sh; //.. sh = ::gethostbyname(pName); //.. DWORD dwIP = ((in_addr* )sh->h_addr)->s_addr; //.. peer.sin_addr.s_addr = dwIP; //.. |
Сообщ.
#17
,
|
|
|
Скорее всего необходимые преобразования и приведения к типу можно выполнить несколькими способами.
Однако эта хрень что на втором аттаче это вообще ни в какие ворота... struct hostent { char *h_name; /* Официальное имя хоста.*/ char **h_aliases; /* Массив псевдонимов данного хоста, заканчивающийся нулем */ int h_addrtype; /* Тип возвращенного функцией адреса; для Интернет это AF_INET */ int h_length; /* Длина адреса в байтах. Для типа AF_INET длина всегда 4 байта */ char **h_addr_list; /* Указатель на массив указателей IPv4 (IPv6) адресов хоста. Он заканчивается нулем, порядок следования байтов сетевой. */ #define h_addr h_addr_list[0]/*Определяет h_addr как самый первый адрес хоста в списке*/ }; Ведь h_addr - это 4-х байтовый адрес хоста в сетевом порядке. Я пропинговал и получилось Pinging smtp.mail.ru [94.100.180.160] with 32 bytes of data: Адрес именно тот, который у вас на первой картинке - в s_b1 s_b2 s_b3 s_b4 А вот что и откуда взялось на второй? кракозябрыsmtp.mail.ru? Кстати, на той же первой картинке порт не 25-й, а 6400. Это так надо? Связка 94.100.180.160:6400 тоже даст bad address Кстати, было бы интересно посмотреть уходящий от коннекта первый TCP-SYN-сегмент программой типа TCPView, потому что в таблице TCP соединений соединение не зафиксировано, и адрес точки соединения там не виден. |
Сообщ.
#18
,
|
|
|
Цитата Oleg2004 @ Скорее всего необходимые преобразования и приведения к типу можно выполнить несколькими способами. Всё это будет работать: dwIP = ((in_addr* )sh->h_addr)->s_addr; dwIP = *(DWORD *) sh->h_addr_list[0]; dwIP = *(DWORD *) sh->h_addr; Выяснилось вот что: результат connect-а зависит от провайдера. Или системного администратора. С домашнего компа connect всегда удачный. С рабочего компа - всегда нет. Кто-то запретил.. |
Сообщ.
#19
,
|
|
|
Цитата ЫукпШ @ С домашнего компа connect всегда удачный. С рабочего компа - всегда нет. Кто-то запретил.. Ну, честно говоря я бы такие выводы не делал. Если бы такое происходило, реакция на коннект была бы другая. Все TCP- соединения начинаются с SYN-сегмента. И он должен уходить всегда. Если только на провайдере не отслеживаются все такие сегменты. Это практически невозможно. Т.е. бессмысленно. Разве что на каком то суперзасекреченном компе. Добавлено Однако судя по описанию ошибки Цитата Bad address (неверный адрес). Система обнаружила неверный указатель на адрес при попытке использовать его в вызове функции. Эта ошибка происходит при передачи приложением неверного указателя, или если размер буфера слишком мал - например, если длина аргумента, представляющего собой структуру типа sockaddr, меньше, чем sizeof(struct sockaddr). сегмент TCP вообще не инициируется. Т.е. из локального хоста он не уходит, так как функция встретила проблемы с указателем на ее параметр Блин, просто какой то бред - еще раз проверил код ТС - да нет, ошибки не вижу... Добавлено Единственная совершенно нетипичная команда для подобного кода, которая присутствует в коде, так это удаление аргумента функции gethost... h = gethostbyname(em); delete em; Зачем??? |
Сообщ.
#20
,
|
|
|
Цитата Oleg2004 @ Цитата ЫукпШ @ С домашнего компа connect всегда удачный. С рабочего компа - всегда нет. Кто-то запретил.. Ну, честно говоря я бы такие выводы не делал. Если бы такое происходило, реакция на коннект была бы другая. Да, я забыл упомянуть, что ошибка совсем другая. А именно - 10061. Очень часто это результат деятельности фиревола. В нашей организации так - что сделаешь.. До smtp - сервера конторы я дотягиваюсь, а во внешнии сети - нет. |
Сообщ.
#21
,
|
|
|
Цитата ЫукпШ @ А именно - 10061. |
Сообщ.
#22
,
|
|
|
Цитата Oleg2004 @ h = gethostbyname(em); delete em; Зачем??? В переменной em хранится строка с адресом (smtp.mail.ru). После того, как я вызываю функцию gethostbyname() я очищаю память этой переменной, т.к. она больше не нужна. Добавлено Сейчас ради интереса попробовал пропинговать любой внешний хост и результат был отрицательный. Пинг таких хостов как google.com, mail.ru, yandex.ru, smtp.mail.ru заканчиваются тем, что команде ping не удается обнаружить данные узлы. Не сильный эксперт в сетях, но, кажется, что существует какая-то блокировка или какой-то прокси. Кстати, пингую я и запускаю программу не с домашнего компьютера, а с рабочего. И как упомянул [ЫукпШ] возможно, с рабочего компьютера connect всегда завершается ошибкой. |
Сообщ.
#23
,
|
|
|
Цитата linuxoid @ Пинг таких хостов как google.com, mail.ru, yandex.ru, smtp.mail.ru заканчиваются тем, что команде ping не удается обнаружить данные узлы. Не сильный эксперт в сетях, но, кажется, что существует какая-то блокировка или какой-то прокси. Кстати, пингую я и запускаю программу не с домашнего компьютера, а с рабочего. С моего домашнего пингуются все. Цитата И как упомянул [ЫукпШ] возможно, с рабочего компьютера connect всегда завершается ошибкой. Ну так что мешает вашу прогу запустить с домашнего??? Но еще раз повторю - коннект с ошибкой 10014 вообще не покидает комп. Это не ошибка соединения или его блокировка файрволлом или провом. Это онибка в запуске коннекта - он вообще не запускается. Цитата linuxoid @ В переменной em хранится строка с адресом (smtp.mail.ru). После того, как я вызываю функцию gethostbyname() я очищаю память этой переменной, т.к. она больше не нужна. Это понятно... а смысл какой глубокий? Эта строка занимает пусть десяток байтов...Что за экономия? |
Сообщ.
#24
,
|
|
|
Цитата Oleg2004 @ Цитата linuxoid @ Пинг таких хостов как google.com, mail.ru, yandex.ru, smtp.mail.ru заканчиваются тем, что команде ping не удается обнаружить данные узлы. Не сильный эксперт в сетях, но, кажется, что существует какая-то блокировка или какой-то прокси. Кстати, пингую я и запускаю программу не с домашнего компьютера, а с рабочего. С моего домашнего пингуются все. Цитата И как упомянул [ЫукпШ] возможно, с рабочего компьютера connect всегда завершается ошибкой. Ну так что мешает вашу прогу запустить с домашнего??? Но еще раз повторю - коннект с ошибкой 10014 вообще не покидает комп. Это не ошибка соединения или его блокировка файрволлом или провом. Это онибка в запуске коннекта - он вообще не запускается. Цитата linuxoid @ В переменной em хранится строка с адресом (smtp.mail.ru). После того, как я вызываю функцию gethostbyname() я очищаю память этой переменной, т.к. она больше не нужна. Это понятно... а смысл какой глубокий? Эта строка занимает пусть десяток байтов...Что за экономия? Экономии может и нет, но это уже привычка. Так научили. Ладно, я с ошибкой разобрался. Тему можно закрыть! Всем спасибо |
Сообщ.
#25
,
|
|
|
Цитата linuxoid @ Ладно, я с ошибкой разобрался. Тему можно закрыть! Всем спасибо Разобрались - это плюс. А вот не поделились с коллегами о причине ее - это минус. Мы тут старались, время свое тратили на поиск ошибки, пытаясь вам помочь, и на тебе...секрет. Ведь форум учит не только ТС, но и всех других - чтобы они не делали подобных ошибок. А для закрытия темы нажмите справа вверху - Вопрос решен. |