Jah00 Temat założony przez niniejszego użytkownika |
[C++] WinSock, brak odpowiedzi z serwera SMTP » 2018-12-16 22:17:59 Witam, podczas nauki winsock postanowiłem napisać prosty program który połączy się z serwerem SMTP (dowolnym), i ewentualnie wyślę maila. Obecnie utknąłem na etapie odpowiedzi z serwera. Program poprawnie łączy się z zadanym serwerem (testowałem smtp.gmail.com na porcie 587), oto pierwsza wiadomość jaką dostaje z serwera: 220 smtp.gmail.com ESMTP d4sm11349893wrp.89 - gsmtp Gdy wysyłam odpowiedź HELO lub EHLO z parametrem lub bez nie otrzymuje już nic więcej. Wklejam kod bo podejrzewam że w mojej pętli coś jest nie tak. #define _WIN32_WINNT 0x501 #include <iostream> #include <winsock2.h> #include <ws2tcpip.h> #include <cstdlib>
int main() { struct addrinfo * result = NULL; struct addrinfo hints; ZeroMemory( & hints, sizeof( hints ) ); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; WSADATA wsaData; char recvbuf[ 512 ]; char sendbuf[ 512 ]; int bytesSent = 0; int bytesRecv = 0; ZeroMemory( & recvbuf, sizeof( recvbuf ) ); if( WSAStartup( MAKEWORD( 2, 2 ), & wsaData ) ) { std::cout << "Failed to startup wsa!\n"; return 1; } if( getaddrinfo( "smtp.gmail.com", "587", & hints, & result ) ) { std::cout << "Getaddrinfo error!\n"; WSACleanup(); return 1; }; SOCKET mSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); if( mSocket == INVALID_SOCKET ) { std::cout << "Socket error: " << WSAGetLastError(); WSACleanup(); return 1; } if( connect( mSocket, result->ai_addr,( int ) result->ai_addrlen ) != 0 ) { std::cout << "Unable to connect to server!\n"; WSACleanup(); return 1; } do { bytesRecv = recv( mSocket, recvbuf, 512, 0 ); if( bytesRecv < 0 ) { std::cout << "Connection closed!\n"; return 1; } std::cout << recvbuf; std::cout << "> "; std::cin.getline( sendbuf, 512 ); bytesSent = send( mSocket, sendbuf, strlen( sendbuf ), 0 ); } while( bytesSent > 0 ); closesocket( mSocket ); WSACleanup(); return 0; }
|
|
pekfos |
» 2018-12-16 22:28:38 Nie wysyłasz znaku nowej linii po poleceniu. |
|
Jah00 Temat założony przez niniejszego użytkownika |
» 2018-12-16 23:14:54 Teraz działa, jednak jak już wkleiłem cały kod to mam jeszcze pytanie, jak serwer zwróci wiadomość dłuższą niż 512 bajtów to podejrzewam że ona zostanie obcięta natomiast zastanawiam się jak najlepiej zrobić aby wszystko co wyśle serwer było wyświetlane a potem moja odpowiedź
Edit
I zapomniałem, mój warunek wyjścia z pętli i zakończenia połączenia też raczej nie jest najlepszy |
|
pekfos |
» 2018-12-16 23:46:43 Nie ma uniwersalnego sposobu. Musisz sam to rozstrzygnąć na podstawie odebranych danych. |
|
Jah00 Temat założony przez niniejszego użytkownika |
» 2018-12-17 13:33:24 Ok, mam jeszcze ostatnie pytanie co do samego serwera pocztowego. Nie znam się na tym za bardzo a nie mogę się zalogować. Po wpisaniu AUTH LOGIN wyskakują dodatkowe znaczki, a czego nie wpiszę to zostaję odrzucone i serwer nie wysyła nic więcej. Wrzucam ss:
https://postimg.cc/n9hKLbQC
STARTTLS jest wymagane, jeśli tego nie ma to serwer po wpisaniu AUTH LOGIN wyrzuci że najpierw trzeba STARTTLS. Próbowałem szukać w google, na jednej stronie znalazłem ss jak powinno wyglądać logowanie, po wpisaniu AUTH LOGIN serwer powinien zwrócić wiadomość o wpisaniu e-maila, jednak tak nie jest. |
|
pekfos |
» 2018-12-17 13:54:14 Po poleceniu STARTTLS musisz przeprowadzić TLS handshake i dopiero potem możesz wysyłać dalsze polecenia SMTP, przy czym stan protokołu zostaje zresetowany, wiec zaczynasz od wysłania EHLO drugi raz. Wszystko co wysyłasz po ustanowieniu TLS jest już szyfrowane. wyskakują dodatkowe znaczki |
Bo twoje wyświetlanie jest błędne. recv() odbiera blok danych, nie tekst. Przekazanie bufora prosto do std::cout ma niezdefiniowane zachowanie. |
|
Jah00 Temat założony przez niniejszego użytkownika |
» 2018-12-17 14:20:50 Ok rozumiem, a wiesz może jak wygląda przeprowadzenie tls handshake w praktyce? |
|
pekfos |
» 2018-12-17 14:28:59 Najprościej z użyciem takich bibliotek jak OpenSSL. |
|
« 1 » |