用CSocket如何发邮件? 包括SMTP身份验证

解决方案 »

  1.   

    看看smtp的协议
    http://www.ietf.org/rfc/rfc0821.txt
      

  2.   

    codeguru.com上有,
    以后先去搜一下在问,不要浪费分
      

  3.   

    由Socket套接字为SMTP提供网络通讯基础  许多网络程序都是采用Socket套接字实现的,对于一些标准的网络协议如HTTP、FTP和SMTP等协议的编程也是基于套接字程序的,只是端口号不再是随意设定而要由协议来指定,比如HTTP端口在80、FTP是21,而SMTP则是25。Socket只是提供在指定的端口上同指定的服务器从事网络上的通讯能力,至于客户和服务器之间是如何通讯的则由网络协议来规定,这对于套接字是完全透明的。因此可以使用Socket套接字为程序提供网络通讯的能力,而对于网络通讯连路建立好之后采取什么样的通讯应答则要按SMTP协议的规定去执行了。Socket套接字网络编程方面的文章资料非常丰富,限于本文篇幅,在此不再赘述,有关详情请参阅相关文档。为简便起见,没有采用编写较复杂的Windows Sockets API进行编程,而是使用经过较好封装的MFC 的CSocket类。在正式使用套接字之前,也要先用AfxSocketInit()函数对套接字进行初始化,然后用Create()创建套接字对象,并由该套接字通过Connect()建立同邮件服务器的连接。如果一切正常,再后续的工作中就是遵循SMTP协议的约定来使用Send()、Receive()函数来发送SMTP命令和接收邮件服务器发来的应答码以完成对邮件的传送。  SMTP会话应答的实现  在同邮件服务器建立好链路连接后就可以按前面介绍过的会话流程进行程序设计了,对于SMTP命令的发送,可按命令格式将其组帧完毕后用CSocket类的Send()函数将其发送到服务器,并通过CSocket类的Receive()函数接收从邮件服务器发来的应答码,并根据SMTP协议的应答码表对其做出响应的处理。下面是用于接收应答码的函数get_response()的部分实现代码:BOOL CSMTP::get_response( UINT response_expected )//输入参数为希望的应答码
    {
    ……
    // m_wsSMTPServer为CSocket的类对象,调用Receive()将应答码接收到缓存
    // response_buf中
    m_wsSMTPServer.Receive( response_buf, RESPONSE_BUFFER_SIZE )
    sResponse = response_buf;
    sscanf( (LPCTSTR)sResponse.Left( 3 ), _T( "%d" ), &response );
    pResp = &response_table[ response_expected ];
    file://检验收到的应答码是否是所希望得到的
    if( response != pResp->nResponse )
    {
    ……//不相等的话进行错误处理
    return FALSE;
    }
    return TRUE;
    }   会话的各个部分比较类似,都是命令--应答方式,而且均成对出现,下面是本文的重点也是实现的关键部分--在程序控制下完成对SMTP命令的格式化以及对命令的发送和对邮件服务器应答码的检验处理://格式化并发送HELLO命令,并接收、验证服务器应答码
    gethostname( local_host, 80 );
    sHello.Format( _T( "HELO %s\r\n" ), local_host );
    m_wsSMTPServer.Send( (LPCTSTR)sHello, sHello.GetLength() );
    if( !get_response( GENERIC_SUCCESS ) ) file://检验应答码是否为250
    {
    ……
    return FALSE;
    }
    file://格式化并发送MAIL命令,并接收、验证服务器应答码
    sFrom.Format( _T( "MAIL From: <%s>\r\n" ), (LPCTSTR)msg->m_strFrom );
    m_wsSMTPServer.Send( (LPCTSTR)sFrom, sFrom.GetLength() );
    if( !get_response( GENERIC_SUCCESS ) ) file://检验应答码是否为250
    return FALSE;
    file://格式化并发送RCPT命令,并接收、验证服务器应答码
    sEmail=(LPCTSTR)msg->m_strTo;
    sTo.Format( _T( "RCPT TO: <%s>\r\n" ), (LPCTSTR)sEmail );
    m_wsSMTPServer.Send( (LPCTSTR)sTo, sTo.GetLength() );
    if(!get_response( GENERIC_SUCCESS )) file://检验应答码是否为250
    return FALSE;
    file://格式化并发送DATA命令,并接收、验证服务器应答码
    sTemp = _T( "DATA\r\n" );
    m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
    if( !get_response( DATA_SUCCESS ) ) file://检验应答码是否为354
    return FALSE;
    file://发送根据RFC 822文档规定格式化过的邮件头
    m_wsSMTPServer.Send( (LPCTSTR)msg->m_strHeader, msg->m_strHeader.GetLength() );
    ……
    file://发送根据RFC 822文档规定格式化过的邮件体
    sTemp = msg->m_strBody;
    if( sTemp.Left( 3 ) == _T( ".\r\n" ) )
    sTemp = _T( "." ) + sTemp;
    while( (nPos = sTemp.Find( szBad )) > -1 )
    {
    sCooked = sTemp.Mid( nStart, nPos );
    sCooked += szGood;
    sTemp = sCooked + sTemp.Right( sTemp.GetLength() - (nPos + nBadLength) );
    }
    m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
    file://发送内容数据结束标志"<CRLF>.<CRLF>",并检验返回应答码
    sTemp = _T( "\r\n.\r\n" );
    m_wsSMTPServer.Send( (LPCTSTR)sTemp, sTemp.GetLength() );
    if( !get_response( GENERIC_SUCCESS ) )// 检验应答码是否为250
    return FALSE;   到此为止,已基本在程序中体现出了SMTP协议的会话流程,能在Socket套接字所提供的网络通讯能力基础之上实现以SMTP命令和SMTP应答码为基本会话内容的通讯交互过程,从而最终实现SMTP协议对电子邮件的发送。
      

  4.   

    我用CSocket 发邮件, 可 SMTP 服务器总给我这个信息553 You are not authorized to send mail as <MAIL FROM:[email protected]>,
    authentication is required我不知道如何认证, 看了RFC文档, 上面竟然也没有提到!
      

  5.   

    smtp认证方式选择"auth login"即可!