现在发送邮件都要SMTP验证,我要用CSocket写发送邮件的程序,请问如何加入SMTP验证?在线等待,最好有原代码,愿意500分相赠。

解决方案 »

  1.   

    也是通过smtp协议。只是这时候发送服务器工作在一个客户端的方式,接收服务器工作在一个smtp服务器方式。
        Email(Encode) -> a SMTP Relay Server -> Remote SMTP Server(远程邮局)。非常简单,邮件编码后被递送到一个SMTP转交服务器上,该服务器对信件分检(到同一邮局的被放在一起)后,根据优先级以及信件的先后次序被发送到远程邮局的SMTP服务器上。换句话说,只要我们知道了SMTP转交服务器是如何确定远程邮局SMTP服务器的地址的,就可以轻松地将饶开SMTP Relay Server直接递送到远程邮局服务器。 
        SMTP Relay Server是如何确定远程邮局服务器的地址的呢?如果你熟悉域名解析,就知道是怎么回事了,我们知道电子邮件的地址由两部分构成[email protected],邮箱(postbox)和地址(address.com),给域名服务器发送指令查询"address.com”的远程邮局服务器的地址即可找到远程邮局SMTP服务器的IP 地址,该指令查询是被称作MX(Mail Exchange)邮件交换服务器的地址查询。远程邮局SMTP服务器的地址可能不止一个,这时,你可根据信件优先级的不同,将对应优先级的信件发到对应地址的远程邮局SMTP服务器,当然,你也可以不管三七二十一,随便选一个SMTP服务器发送。查询该域名的MX记录(Mail eXchanger),如163.com的MX记录
    http://www.codeguru.com/internet/SimpleDNSResolver.html....(有关认证命令)
    C:  AUTH LOGIN
    S: 334 VXNlcm5hbWU6
    C: c3RldmVuX3h1
    S:  334 UGFzc3dvcmQ6
    C: c3RldmVu
    S: 235 go ahead
    ......
      

  2.   

    to:回复人: kingbird(core dump)
    谢谢!原理我已经理解了,你给的URL我没能上去,以后再看。现在的问题是:
      1.我如何进行MX查询,用gethostbyname()行吗?你所说的“163.com的MX记录”是不是就是163.com的IP地址,如果不是,我如何“给域名服务器发送指令查询"address.com”的远程邮局服务器的地址”
      2.得到了地址后,能不能用原来的方法就可以发送邮件?(方法如下)
    BOOL CMailDlg::SendMailMessage(LPCTSTR szServer, 
       LPCTSTR szFrom, 
       LPCTSTR szTo, 
       LPCTSTR szSubject, 
       LPCTSTR szMessage)
    {
    // Construct a socket from the derived class
    CSocketX theSocket; // And create the socket descriptor
    if (!theSocket.Create())
    {
    AfxMessageBox("Socket creation failed");
    return FALSE;
    }  // Connect to the server
    if (!theSocket.Connect(szServer, 25))
    {
    AfxMessageBox("Could not connect to server");
    return FALSE;
    } // General purpose strings
    CString strCommand;
    CString strResponse; // Set timeout to 10 seconds
    UINT uTimeOut = 10000; // Read the "HELO" response from the server
    if (theSocket.Receive(strResponse, uTimeOut) == SOCKET_ERROR)
    {
    ReportSocketError(theSocket.GetLastError());
    return FALSE;
    } // and check to see if we're talking to an
    // SMTP server
    if (strResponse.Left(3) != _T("220"))
    {
    CString strError = "ERROR: Not a valid SMTP server response\r\n";
    strError += strResponse;
    AfxMessageBox(strError);
    theSocket.Send("QUIT\r\n");
    return FALSE;
    } // Send the "FROM" line
    strCommand = "MAIL FROM:<";
    strCommand += szFrom;
    strCommand += ">\r\n";
    theSocket.Send(strCommand);

    // and check the response
    if (theSocket.Receive(strResponse, uTimeOut) == SOCKET_ERROR)
    {
    ReportSocketError(theSocket.GetLastError());
    return FALSE;
    }
    if (strResponse.Left(3) != _T("250"))
    {
    CString strError = "ERROR: Sender rejected\r\n";
    strError += strResponse;
    AfxMessageBox(strError);
    theSocket.Send("QUIT\r\n");
    return FALSE;
    } // Send the "RCPT" line
    strCommand = "RCPT TO:<";
    strCommand += szTo;
    strCommand += ">\r\n";
    theSocket.Send(strCommand); // and check the response
    if (theSocket.Receive(strResponse, uTimeOut) == SOCKET_ERROR)
    {
    ReportSocketError(theSocket.GetLastError());
    return FALSE;
    }
    if (strResponse.Left(3) != _T("250"))
    {
    CString strError = "ERROR: Recipient rejected\r\n";
    strError += strResponse;
    AfxMessageBox(strError);
    theSocket.Send("QUIT\r\n");
    return FALSE;
    } // Send the "DATA" line
    theSocket.Send("DATA\r\n"); // and check the response
    if (theSocket.Receive(strResponse, uTimeOut) == SOCKET_ERROR)
    {
    ReportSocketError(theSocket.GetLastError());
    return FALSE;
    }
    if (strResponse.Left(3) != _T("354"))
    {
    CString strError = "ERROR: DATA command rejected\r\n";
    strError += strResponse;
    AfxMessageBox(strError);
    theSocket.Send("QUIT\r\n");
    return FALSE;
    } // Send the "Subject" line
    strCommand = "Subject: ";
    strCommand += szSubject;
    strCommand += "\r\n";
    theSocket.Send(strCommand); // No response from server expectd // Send the message data
    // This code assumes the message
    // data contains CRLF pairs 
    // where appropriate.
    if (theSocket.Send(szMessage) == SOCKET_ERROR)
    {
    ReportSocketError(theSocket.GetLastError());
    return FALSE;
    } // No response from server expectd // Send the termination line
    theSocket.Send("\r\n.\r\n"); // and check the response
    if (theSocket.Receive(strResponse, uTimeOut) == SOCKET_ERROR)
    {
    ReportSocketError(theSocket.GetLastError());
    return FALSE;
    }
    if (strResponse.Left(3) != _T("250"))
    {
    CString strError = "ERROR: Message body rejected\r\n";
    strError += strResponse;
    AfxMessageBox(strError);
    theSocket.Send("QUIT\r\n");
    return FALSE;
    } // Send the "QUIT" line
    theSocket.Send("QUIT\r\n"); return TRUE;
    }CSocketX的头文件:
    class CSocketX : public CSocket
    {
    DECLARE_DYNAMIC(CSocketX);// Implementation
    public:
    int Send(LPCTSTR lpszStr, UINT uTimeOut = 0, int nFlags = 0);
    int Receive(CString& str, UINT uTimeOut = 0, int nFlags = 0);
    BOOL SetTimeOut(UINT uTimeOut);
    BOOL KillTimeOut();protected: 
    virtual BOOL OnMessagePending();private: 
    int m_nTimerID;
    };
    CSocketX的实现部分:
    int CSocketX::Send(LPCTSTR lpszStr, UINT uTimeOut, int nFlags)
    {
    // If a timeout value was specified, set it
    if (uTimeOut > 0)
    SetTimeOut(uTimeOut); // Call base class function
    int nRet = CSocket::Send(lpszStr, strlen(lpszStr), nFlags); // If we previously set a timeout
    if (uTimeOut > 0)
    {
    KillTimeOut();
    // If the operation timedout, set a more
    // natural error message
    if (GetLastError() == WSAEINTR)
    SetLastError(WSAETIMEDOUT);
    }
    return nRet;
    }
    int CSocketX::Receive(CString& str, UINT uTimeOut, int nFlags)
    {
    static char szBuf[256];
    memset(szBuf, 0, sizeof(szBuf)); // If a timeout value was specified, set it
    if (uTimeOut > 0)
    SetTimeOut(uTimeOut); // Call base class function
    int nRet = CSocket::Receive(szBuf, sizeof(szBuf), nFlags); // If we previously set a timeout
    if (uTimeOut > 0)
    {
    KillTimeOut();
    // If the operation timedout, set a more
    // natural error message
    if (nRet == SOCKET_ERROR)
    {
    if (GetLastError() == WSAEINTR)
    SetLastError(WSAETIMEDOUT);
    }
    } // Fill in the CString reference
    str = szBuf;
    return nRet;
    }BOOL CSocketX::OnMessagePending() 
    {
    MSG msg; // Watch for our timer message
    if(::PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_NOREMOVE))
    {
    // If our timer expired...
    if (msg.wParam == (UINT) m_nTimerID)
    {
    // Remove the message
    ::PeekMessage(&msg, NULL, WM_TIMER, WM_TIMER, PM_REMOVE);
    // And cancel the call
    CancelBlockingCall();
    return FALSE;
    }
    }
    // Call base class function
    return CSocket::OnMessagePending();

    BOOL CSocketX::SetTimeOut(UINT uTimeOut) 

    m_nTimerID = SetTimer(NULL,0,uTimeOut,NULL);
    return m_nTimerID;

    BOOL CSocketX::KillTimeOut() 

    return KillTimer(NULL,m_nTimerID);

      

  3.   

    http://www.vckbase.com/code/listcode.asp?mclsid=9
    还是用控件吧
      

  4.   

    组件虽好,但是没有原代码。不管怎样,先谢谢jiaojianjj(菩提树)了。
    能人快来take分
      

  5.   

    MX记录不等同于域名地址。这需要查询DNS才能取得写出你的邮箱,把DNS查询程序发给你。
      

  6.   

    [email protected]
    先谢过了
      

  7.   

    同意:ahao(天·狼·星星)
    奇怪,他问的是怎么实现验证,怎么都回答MX查询呢多两个 Base64 编码不就完了吗,教别人发垃圾邮件啊?
      

  8.   

    你用sniff抄几个包就明白了,有些客户端用的是base64直接编码,发送,
    不带命令行,但服务器端用POP3的命令方式。
      

  9.   

    两种方法我都想学啊,希望能给一个Demo程序,我的Email写在上面。
    多谢。
      

  10.   

    没有看到email啊。我做了一个demo。有兴趣email:[email protected]