我用 Winsock 编程,做个 ESMTP 协议客户端,没想到在发送 DATA 命令后继续发送 BASE64 编码好的数据时收到 "354 End with <CRLF>.<CRLF> " ,不知道如何解决?

解决方案 »

  1.   

    发送 DATA 命令,收到354回应后,再发送邮件正文数据
      

  2.   

    baojian说的完全对!
    需要在等待得到354以后才开始发邮件主体并以\r\n.\r\n结束。
    有时只要出现\r\n.就自动结束了!
      

  3.   

    嗯,奇怪,我发送 DATA 命令之后收到的是 250 Mail OK , 怎么回事啊?难道还要继续再接收服务器端的回应信息?
      

  4.   

    // 高人请看,问题代码如下:
        wsprintf( szSend , "DATA\r\n" ) ;
        PrintInfo( "发送 DATA 命令 ..." ) ;
        if( send( socketClient , szSend , strlen( szSend ) , 0 ) == SOCKET_ERROR )
        {
            PrintInfo( "发送 DATA 命令失败!");
            goto ErrExit ;     
        }    szBuffer[0]='\0' ;
        ret = recv(socketClient, szBuffer, DEFAULT_BUFFER, 0);
        if (ret == 0)        
        {
            PrintInfo("接收发送 DATA 之后的信息失败!");
            goto ErrExit ;
        }
        else if (ret == SOCKET_ERROR)
        {
            
            wsprintf( szInfo ,"接收发送 DATA 命令之后的信息失败,错误号:%d\n", WSAGetLastError());
            PrintInfo(szInfo);
            goto ErrExit ;
        }
        else
        {
           szBuffer[ret] = '\0';
           wsprintf( szInfo ,"接收发送 DATA 命令之后的信息成功:[%d bytes]: %s", ret, szBuffer);
           PrintInfo(szInfo);
        }    dwFileLength = strlen( szBody ) + strlen( szMailData )  ;
        szMail = new char[ dwFileLength + 1 ] ;
        strcpy( szMail , szBody ) ;
        strcat( szMail , szMailData ) ;
        szMail[ dwFileLength ] = '\0' ;
     
        ret = send( socketClient , szMail , dwFileLength , 0 ) ;
        if( ret == SOCKET_ERROR )
        {
            wsprintf( szInfo , "发送数据发生错误: %d " , WSAGetLastError() ) ;
            PrintInfo( szInfo);
            goto ErrExit ;     
        }    ret = recv(socketClient, szBuffer, DEFAULT_BUFFER, 0);
        if (ret == 0)        
        {
             PrintInfo("接收发送全部数据后的信息失败");
             goto ErrExit ;
        }
        else if (ret == SOCKET_ERROR)
        {
            wsprintf( szInfo ,"接收发送数据后返回的信息失败,错误号: %d\n",  WSAGetLastError());
            PrintInfo(szInfo);  
            goto ErrExit ;
        }
        else  
        {
            szBuffer[ret] = '\0';
            wsprintf( szInfo ,"接收发送数据后返回的信息成功![%d bytes]: %s", ret, szBuffer);
            // ********** 就是这个地方非常奇怪,老是返回 354 End with <CRLF>.<CRLF> ******
     
            // 还应该判断返回码以决定退出循环
            PrintInfo(szInfo);
        }
      

  5.   

    我在拼合 szMail 时已经将 "\r\n.\r\n" 加入进去作为字符串结尾,服务端应该能接收到这个结束标志,难道不应该这么做?应该发送字符串数据后接收到“354 End with <CRLF>.<CRLF>”后再发送 "\r\n.\r\n" 串?望高人指点,一个邮件程序到这个地方被卡了很长时间了。
      

  6.   

    354 是对 DATA 命令的回应,应该在发送完DATA并收到354后,再开始发送邮件正文如下以smtp.163.com为例:--> 220 163.com Anti-spam GT for Coremail System (163com[20050206])
    HELO 163.com
    --> 250 OK
    AUTH LOGIN
    --> 334 ...
    base64的用户名
    --> 334 ...
    base64的密码
    --> 235 Authentication successful
    MAIL FROM: <[email protected]>
    --> 250 Mail OK
    RCPT TO: <[email protected]>
    --> 250 Mail OK
    DATA
    --> 354 End data with <CR><LF>.<CR><LF>
    邮件内容,以\r\n.\r\n结束
    --> 250 Mail OK
    QUIT
    --> 221 Bye
      

  7.   

    另外你的接收recv函数,都应该换成循环接收
    即收到后查找\r\n结束标志,如果没有找到\r\n则继续接收
      

  8.   

    哦,非常感谢 baojian88888(机器人) 不吝赐教!
      

  9.   

    不过还有 2 个问题想请教一下: 1、C 中 "\r\n"  的 ASC 码显示 0D 0D 0A 怎么回事?
    2、发送数据后返回 421 Read Data form client error !这下懵了!
      

  10.   

    1. "\r\n" 是 0D0A
    2. 如果每次都这样,可能是邮件内容编码不合规范
      

  11.   

    baojian88888(机器人) 老兄:    你好,在仁兄的指点下,我终于发信成功,不过有意思的是,对于几 KB 的附件是没问题,对于 1 MB 的附件,还是返回“421 Read Data form client error !”,真是吊诡!难道对于大于某个尺寸的邮件需要分段发送?希望仁兄能继续指定一下我!    另外,本来打算把分给你,结果密码输入总是错误!十分抱歉!希望仁兄大人大量,不要介意!
      

  12.   

    如果网络收发没有问题的话,还是考虑编码的问题吧
    可以看foxmail或outlook的邮件编码格式,有一个察看原文功能
    1MB的附件不算大,现在的邮箱都至少支持4M甚至10M的附件