Программа работы с SMTP
Сохраню на память
Учебное задание из универа: Программа реализующая:Пример простейшей SMTP-сессии
Листинг
mail.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <errno.h> #define MSG_LEN 255 char srv_addr[20]; // адрес сервера char srv_port[10]; // порт сервера char recv_buf[MSG_LEN]; // буфер передачи char read_buf[MSG_LEN]; // буфер приема int read_bytes; // количество полученных байт char mail_from[100]; char mail_to[100]; char mail_subj[100]; char mail_msg[100]; char mail_data[MSG_LEN]; char mail_tmp[100]; //========================================================================== // Функция для чтения принятых данных с проверкой на их целостность //========================================================================== int my_readln( int fd, char *bp, size_t len, int flags) { int cnt; int rc; cnt = len; while ( cnt > 0 ) { rc = recv( fd, bp, cnt, flags ); if ( rc < 0 ) { /* read error? */ if ( errno == EINTR ) /* interrupted? */ continue; /* restart the read */ return -1; /* return error */ } if ( rc == 0 ) /* EOF? */ return len - cnt; /* return short count */ cnt -= rc; if ( bp[rc-1] == '\n') return len - cnt; bp += rc; } return len; } //========================================================================== // Функция для проверки кодов //========================================================================== int my_codecheck ( char *tmp_c, int c) { int i = 0; sscanf(tmp_c,"%d", &i); // вырезаем первой слово // проверяем на соответствие if ( i != c ) return 1; else return 0; } //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ int main() { int sock; struct sockaddr_in addr; // Структура sockaddr_in описывает сокет для работы с протоколами IP // открываем сокет (AF_INET=Интернет-домен; SOCK_STREAM=потоковые сокеты) sock = socket(AF_INET, SOCK_STREAM, 0); if(sock < 0) { perror("socket error"); exit(1); } // (!) Значение поля sin_family всегда равно AF_INET addr.sin_family = AF_INET; printf("server ip:"); scanf("%s", srv_addr); if ( inet_addr(srv_addr) < 0 ) { // Проверка введенного адреса printf("'%s' is not valid ip\n", srv_addr); exit(1); } // Запоминаем адрес addr.sin_addr.s_addr = inet_addr(srv_addr); printf("server port:"); scanf("%s", srv_port); if ( atol(srv_port) <= 0 ) { printf("'%s' in not valit port'\n", srv_port); exit(1); } // Запоминаем порт (hton - локальный к сетевому) addr.sin_port = htons(atol(srv_port)); // Подключение if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("connect error"); exit(1); } //========================================================================== // Работа с сервером //========================================================================== // Обнуление буфера перед приемом (как альтернатива) //memset(buf, 0, sizeof(buf)); // принимаем read_bytes=my_readln(sock, read_buf, sizeof(read_buf), 0); // (!) Запись NULL в последний элемент (эффективнее полного обнуления) read_buf[read_bytes]=(char)0; printf ("server response=>:'%s'\n", read_buf); if ((read_bytes <= 0) || (my_codecheck(read_buf, 220)) !=0) { printf("SMTP error\n"); exit(1); } printf("You mail(MAIL FROM):"); scanf("%s",mail_from); // Запись в буфер sprintf(recv_buf,"MAIL FROM: <%s>\n",mail_from); // Отправка серверу send(sock, recv_buf, strlen(recv_buf), 0); // Принимаем ответ read_bytes=my_readln(sock, read_buf, sizeof(read_buf), 0); read_buf[read_bytes]=(char)0; printf ("server response=>:'%s'\n", read_buf); if ((read_bytes <= 0) || (my_codecheck(read_buf, 250)) !=0) { printf("SMTP error\n"); exit(1); } printf("Recipient (RCPT TO):"); scanf("%s",mail_to); // Запись в буфер sprintf(recv_buf,"RCPT TO: <%s>\n",mail_to); // Отправка серверу send(sock, recv_buf, strlen(recv_buf), 0); // Принимаем ответ read_bytes=my_readln(sock, read_buf, sizeof(read_buf), 0); read_buf[read_bytes]=(char)0; printf ("server response=>:'%s'\n", read_buf); if ((read_bytes <= 0) || (my_codecheck(read_buf, 250)) !=0) { printf("SMTP error\n"); exit(1); } printf("Subject:"); scanf("%s",mail_subj); // Команда DATA sprintf(recv_buf,"DATA\n"); // Отправка серверу send(sock, recv_buf, strlen(recv_buf), 0); // Принимаем ответ read_bytes=my_readln(sock, read_buf, sizeof(read_buf), 0); read_buf[read_bytes]=(char)0; printf ("server response=>:'%s'\n", read_buf); if ((read_bytes <= 0) || (my_codecheck(read_buf, 354)) !=0) { printf("SMTP error\n"); exit(1); } printf("Message (DATA):"); scanf("%s",mail_msg); // Конкатинация тела сообщения sprintf(mail_tmp,"from: %s\n",mail_from); strcat(mail_data,mail_tmp); sprintf (mail_tmp,"to: %s\n",mail_to); strcat(mail_data,mail_tmp); sprintf(mail_tmp,"subject: %s\n",mail_subj); strcat(mail_data,mail_tmp); sprintf(mail_tmp,"%s\n.\n",mail_msg); strcat(mail_data,mail_tmp); strcpy(recv_buf,mail_data); /* printf("+++++++++++\n"); printf("%s", mail_data); printf("+++++++++++\n"); */ // Отправка серверу тела сообщения send(sock, recv_buf, strlen(recv_buf), 0); // Принимаем ответ read_bytes=my_readln(sock, read_buf, sizeof(read_buf), 0); read_buf[read_bytes]=(char)0; printf ("server response=>:'%s'\n", read_buf); if ((read_bytes <= 0) || (my_codecheck(read_buf, 250)) !=0) { printf("SMTP error\n"); exit(1); } // Завершение работы с сервером sprintf(recv_buf,"QUIT\n"); // Отправка серверу send(sock, recv_buf, strlen(recv_buf), 0); // Принимаем ответ read_bytes=my_readln(sock, read_buf, sizeof(read_buf), 0); read_buf[read_bytes]=(char)0; printf ("server response=>:'%s'\n", read_buf); if ((read_bytes <= 0) || (my_codecheck(read_buf, 221)) !=0) { printf("SMTP error\n"); exit(1); } close(sock); return 0; }
Проверка
lexa@u10:~$ ./a.out server ip:81.23.96.14 server port:25 server response=>:'220 new-mail.po4ta.net ESMTP Postfix ' You mail(MAIL FROM):mail@mail.ru server response=>:'250 2.1.0 Ok ' Recipient (RCPT TO):mymail@gmail.com server response=>:'250 2.1.5 Ok ' Subject:test server response=>:'354 End data with <CR><LF>.<CR><LF> ' Message (DATA):preved server response=>:'250 2.0.0 Ok: queued as 8F0DD4F7601 ' server response=>:'221 2.0.0 Bye '
Обсуждение