c - C 上的 SMTP 服务器

标签 c sockets

我尝试在 c 上创建一个 SMTP 服务器并尝试使用 FakeSmtp,但我没有收到任何内容,而且我不知道为什么,因为代码没有警告和错误。有人可以帮助我吗? 我的整个代码执行成功,但我没有收到任何东西 输出在这里:

220 smtp.gmail.com ESMTP bh6sm124854736wjb.0 - gsmtp

DONE EHLO250-smtp.gmail.com at your service, [85.98.184.204]

250-SIZE 35882577

250-8BITMIME

250-STARTTLS

250-ENHANCEDSTATUSCODES

250-PIPELINING

250-CHUNKING

250 SMTPUTF8

DONE EHLO AUTH451 4.5.0 SMTP protocol violation, see RFC 2821 bh6sm124854736wjb.0 - gsmtp

DONE AUTH

AUTH UID

DONE UID

AUTH PWD

MAIL FROM

MAIL TO

DONE MAILTO

DATASON DONE

代码:

void error(char *msg)
{
  perror(msg);
  exit(0);
}

int main(int argc, char *argv[])
{
 int sockfd, portno, n;
 struct sockaddr_in serv_addr;
 struct hostent *server;

 char buffer[BUFFEr_SIZE];
 if (argc < 3) {
    fprintf(stderr,"usage %s hostname port\n", argv[0]);
    exit(0);
 }
 portno = atoi(argv[2]);
 sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) 
    error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
    fprintf(stderr,"ERROR, no such host\n");
    exit(0);
}

bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, 
     (char *)&serv_addr.sin_addr.s_addr,
     server->h_length);
serv_addr.sin_port = htons(portno);
if (connect(sockfd,&serv_addr,sizeof(serv_addr)) < 0) 
    error("ERROR connecting");

n = read(sockfd,buffer,BUFFEr_SIZE-1);
if (n < 0) 
     error("ERROR reading from socket");
printf("%s\n",buffer);

bzero(buffer,BUFFEr_SIZE);

/*------------------------------*/
printf("\nDONE\n");
printf("EHLO");

strcpy(buffer,"ehlo smtp.gmail.com\n");

n = write(sockfd,buffer,strlen(buffer));
if (n < 0) 
     error("ERROR writing to socket");
bzero(buffer,BUFFEr_SIZE);
n = read(sockfd,buffer,BUFFEr_SIZE-1);
if (n < 0) 
     error("ERROR reading from socket");
printf("%s\n",buffer);

/*------------------------------*/    

/*------------------------------*/
printf("\nDONE EHLO\n");
printf("AUTH");

strcpy(buffer,"AUTH LOGIN\n");

n = write(sockfd,buffer,strlen(buffer)+1);
if (n < 0) 
     error("ERROR writing to socket");
bzero(buffer,BUFFEr_SIZE);
n = read(sockfd,buffer,BUFFEr_SIZE-1);
if (n < 0) 
     error("ERROR reading from socket");
printf("%s\n",buffer);

/*------------------------------*/ 

/*------------------------------*/
printf("\nDONE AUTH\n");
printf("AUTH UID");

strcpy(buffer,"xxxx@gmail.com");

n = write(sockfd,buffer,strlen(buffer));
if (n < 0) 
     error("ERROR writing to socket");
bzero(buffer,BUFFEr_SIZE);
n = read(sockfd,buffer,BUFFEr_SIZE-1);
if (n < 0) 
     error("ERROR reading from socket");
printf("%s\n",buffer);

/*------------------------------*/ 

/*------------------------------*/
printf("\nDONE UID\n");
printf("AUTH PWD");

strcpy(buffer,"xxxxxx");

n = write(sockfd,buffer,strlen(buffer)+1);
if (n < 0) 
     error("ERROR writing to socket");
bzero(buffer,BUFFEr_SIZE);
n = read(sockfd,buffer,BUFFEr_SIZE-1);
if (n < 0) 
     error("ERROR reading from socket");
printf("%s\n",buffer);

/*------------------------------*/ 

/*------------------------------*/

printf("MAIL FROM");

strcpy(buffer,"MAIL FROM: xxxxx@gmail.com");

n = write(sockfd,buffer,strlen(buffer));
if (n < 0) 
     error("ERROR writing to socket");
bzero(buffer,BUFFEr_SIZE);
n = read(sockfd,buffer,BUFFEr_SIZE-1);
if (n < 0) 
     error("ERROR reading from socket");
printf("%s\n",buffer);

/*------------------------------*/ 

/*------------------------------*/

 printf("MAIL TO");


strcpy(buffer,"RCPT TO: aaaaa@gmail.com");

n = write(sockfd,buffer,strlen(buffer));
if (n < 0) 
     error("ERROR writing to socket");
bzero(buffer,BUFFEr_SIZE);
n = read(sockfd,buffer,BUFFEr_SIZE-1);
if (n < 0) 
     error("ERROR reading from socket");
printf("%s\n",buffer);

/*------------------------------*/       

/*------------------------------*/
printf("DONE MAILTO\n");

printf("DATA");

strcpy(buffer,"DATA\r\n");

n = write(sockfd,buffer,strlen(buffer));

strcpy(buffer,"Subject: test\r\n");

n = write(sockfd,buffer,strlen(buffer));

strcpy(buffer,"SMTP MAIL TOOL TEST WORKS!!!\r\n");

n = write(sockfd,buffer,strlen(buffer));

strcpy(buffer,"\n\n");

n = write(sockfd,buffer,strlen(buffer));

strcpy(buffer,".\n");

n = write(sockfd,buffer,strlen(buffer));


/*------------------------------*/ 

/*------------------------------*/ 
printf("SON DONE");
strcpy(buffer,"quit\n");

n = write(sockfd,buffer,strlen(buffer));
if (n < 0) 
     error("ERROR writing to socket");
bzero(buffer,BUFFEr_SIZE);
n = read(sockfd,buffer,BUFFEr_SIZE-1);
if (n < 0) 
     error("ERROR reading from socket");
puts(buffer);

/*------------------------------*/

return 0;
}

最佳答案

如果您实现像 SMTP 这样的协议(protocol),建议您查看实际的协议(protocol)标准,而不是仅仅猜测协议(protocol)如何工作。在这种情况下,即使服务器没有在对 EHLO 的响应中指定对 AUTH 的任何支持,您也会向服务器发送 AUTH LOGIN命令:

250-SIZE 35882577  
250-8BITMIME   
250-STARTTLS   
250-ENHANCEDSTATUSCODES   
250-PIPELINING   
250-CHUNKING
250 SMTPUTF8

这违反了 SMTP 协议(protocol),因为服务器正确地认为:

451 4.5.0 SMTP protocol violation, see RFC 2821

不过,在这种情况下,服务器略有错误,因为 AUTH 是在 RFC 4954 中定义的。不是 RFC 2821。

一般来说,gmail.com 的 SMTP 服务器不提供没有 TLS 的身份验证。这意味着您首先需要发出 STARTTLS 命令并检查是否有成功回复,然后将套接字升级到 TLS,然后您可以再次发出 EHLO,这将显示支持对于AUTH:

$ openssl s_client -connect smtp.gmail.com:25 -starttls smtp
...
ehlo foo
250-smtp.gmail.com at your service, [92.117.36.90]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH   <<<< HERE
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8

关于c - C 上的 SMTP 服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50895460/

相关文章:

c - 循环正在跳过 while 语句

c - 使用#define 创建与 C89 std 兼容的虚拟记录

c# - 为什么异步回调套接字方法通常是静态的?

python-3.x - 我用 python 3 编码的服务器不会向所有用户发送消息

java - 客户端-服务器程序

qt - QTcpSocket不会读取所有内容

Python C-API 段错误

c - 如何测试我的 gstreamer 插件?是否有用于 gstreamer 插件测试的标准测试套件?

c - 写入 dat 文件清除旧数据

java - 与两个 wifip2p 设备建立套接字连接