Отправить письмо на c, сервер никогда не отвечает после отправки тела - PullRequest
0 голосов
/ 14 января 2019

Я создал небольшую программу для отправки электронного письма на c. Я сделал 3 функции: Connect: подключиться к серверу с помощью сокета, SendAndRecieve: отправлять и получать сообщения на почтовый сервер, SendAnEmail: написать текст, который будет отправлен SendAndRecieve.

Connect и SendAndRecieve работают отлично. Моя проблема в SendAnEmail. Я не знаю, как сделать закончить шаг данных.

Для каждой команды я получаю ответ сервера: 250 ****** Но что касается данных, он отвечает в первых 354, но не 250 после последней полной остановки. Я, хотя это тот же протокол, что и Telnet. Конечная полная остановка = конец тела. Но это не работает. Почтовый сервер никогда не отвечает.

Кто-нибудь знает решение сообщить серверу, что я закончу писать тело?

код

SOCKET connexion(char* server_name,unsigned short port)
{
    char buf[1024]={0};
    int res_l= 0;
    int nbrecv;
    struct sockaddr_in   serverSockAddr;
    struct hostent     * serverHostEnt;
    SOCKET to_server_socket = 0;
    serverHostEnt = gethostbyname( server_name );
    if ( serverHostEnt == NULL )  {
        res_l = h_errno;
        return (SOCKET)-1;         }
    memcpy(&serverSockAddr.sin_addr,serverHostEnt->h_addr, serverHostEnt->h_length );
    serverSockAddr.sin_port = htons( port );/
    serverSockAddr.sin_family = AF_INET;            


/* Create socket */                                        
    to_server_socket = socket( AF_INET, SOCK_STREAM, 0 );

/* connexion request*/
    if( connect( to_server_socket, ( struct sockaddr * ) &serverSockAddr,sizeof( serverSockAddr ) ) < 0 ) 
        return (SOCKET)-3;
    while( !buf[0] ) nbrecv = recv( to_server_socket, buf, 1024, 0 );
    printf("Welcome message : %s\n",buf);
    return to_server_socket;
}

void SendAndReceive(SOCKET to_server_socket, char * messagesend)
{
    char bufreceive[1024];                                                             
    int size,retVal,nbrecv;                                         
    size  = (int)strlen( messagesend );                                                

    // SEND THE MESSAGE
    retVal = send( to_server_socket, messagesend, size, 0 );
    printf("Envoye : %s\n",messagesend)   ;

    // WAIT THE ANSWER    
    memset(bufreceive,0,1024);                                                                                       
    while(!bufreceive[0])  
        nbrecv = recv( to_server_socket, bufreceive, 1024, 0 );
    printf("Recu : %s\n",bufreceive);                                                  
}             

void SendAnEmail(SOCKET sock)
{
    //ehlo
    SendAndReceive(sock, "EHLO localhost\r\n");
    //mail from
    SendAndReceive(sock, "MAIL FROM:<user@adresse.com\r\n");
    //rcpt to
    SendAndReceive(sock, "RCPT TO:<user@adress.com>\r\n");
    /data
    SendAndReceive(sock, "DATA\r\n");
    //Subject : Subject
    //
    //Body
    //.
    SendAndReceive(sock, "Subject : Subject\r\n\r\nBody\r\n.\r\n");
    //quit
    SendAndReceive(sock, "QUIT\r\n");
}

В вашем main вы должны установить port = 25, использовать настоящий smtp-сервер для server_name и добавить библиотеку, содержащую Winsock2.h


CMD:

Welcome message : 220 mwinf5d05 ME ESMTP server ready

S: EHLO localhost

R: 250-mwinf5d05 hello [10.162.66.36], pleased to meet you
250-HELP
250-AUTH LOGIN PLAIN
250-SIZE 44000000
250-ENHANCEDSTATUSCODES
250-8BITMIME
250 OK

S: MAIL FROM: <blablabla@orange.fr>

R: 250 2.1.0 <blablabla@orange.fr> sender ok

S: RCPT TO: <xapx35@gmail.com>

R: 250 2.1.5 <xapx35@gmail.com> recipient ok

S: DATA

R: 354 enter mail, end with "." on a line by itself

S: Subject: FlashRad

Ceci est un test.
.

Я ожидал, что смогу делать то же самое, когда использую telnet сам:

Как это объяснить на этом сайте .

Так кто-нибудь знает, что, как сказать, что я закончу писать тело? Как и последняя полная остановка с telnet.

1 Ответ

0 голосов
/ 14 января 2019

RFC 821 говорит

Третьим этапом процедуры является команда DATA.

        DATA <CRLF>

     If accepted, the receiver-SMTP returns a 354 Intermediate reply
     and considers all succeeding lines to be the message text.
     When the end of text is received and stored the SMTP-receiver
     sends a 250 OK reply.

     Since the mail data is sent on the transmission channel the end
     of the mail data must be indicated so that the command and
     reply dialog can be resumed.  SMTP indicates the end of the
     mail data by sending a line containing only a period.  A
     transparency procedure is used to prevent this from interfering
     with the user's text (see Section 4.5.2).

Так что вам нужно отправить строку только с одним периодом после вашего тела.

Если вы ждете 250 после DATA, это тоже будет ошибкой. Сначала вы получаете 354, а затем 250 после строки периода

RFC 821

...