使用SMTP协议发邮件

使用SMTP协议发邮件,通过测试163能够正常使用,其余邮箱可能没法正常使用。开发环境:Windows XP 32 + VS2005windows

代码以下:socket

#include <winsock2.h>
#pragma comment( lib, "ws2_32.lib" )

#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <string>
using namespace std;

#pragma warning( disable : 4996 )

#define RECIVER "你的邮箱@163.com"
#define ACCOUNT "你的邮箱帐号"
#define PASSWORD "你的邮箱密码"
#define SMTP_SERVER "smtp.163.com"
#define SMTP_PORT 25

#define SENDER RECIVER
#define TITLE "test_smtp_mail"

#define MAIL_END "\r\n.\r\n"

const char BASE_CODE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

int Base64Encode( char* src, int src_len, char* dst )
{
    int dst_len = 0;
    while(src_len > 0)
    {
        *dst++ = BASE_CODE[(src[0] >> 2 ) & 0x3F];
        if(src_len > 2)
        {    
            *dst++ = BASE_CODE[((src[0] & 3) << 4) | (src[1] >> 4)];
            *dst++ = BASE_CODE[((src[1] & 0xF) << 2) | (src[2] >> 6)];
            *dst++ = BASE_CODE[src[2] & 0x3F];
        }
        else
        {    
            switch(src_len)
            {
            case 1:
                *dst ++ = BASE_CODE[(src[0] & 3) << 4 ];
                *dst ++ = '=';
                *dst ++ = '=';
                break;
            case 2:
                *dst ++ = BASE_CODE[((src[0] & 3) << 4) | (src[1] >> 4)];
                *dst ++ = BASE_CODE[((src[1] & 0x0F) << 2) | (src[2] >> 6)];
                *dst ++ = '=';
                break;
            }
        }
        src += 3;
        src_len -= 3;
        dst_len +=4;
    }
    *dst = 0;
    return dst_len;
}

class Socket
{
public:
    Socket( const char* peer_name, int peer_port )
    {
        HOSTENT* peer_host = gethostbyname( peer_name );
        if( !peer_host )
        {
            printf( "Socket:gethostbyname(%s) failed, error=%d!", peer_name, GetLastError() );
            return;
        }

        sockaddr_in addr;
        memset( &addr, 0, sizeof( addr ) );
        addr.sin_family = AF_INET;
        addr.sin_port = htons( peer_port );
        addr.sin_addr = *(struct in_addr*)peer_host->h_addr;

        _sock = socket( PF_INET, SOCK_STREAM, 0 );
        if( connect( _sock, ( const sockaddr* )&addr, sizeof( sockaddr ) ) != 0 )
        {
            printf( "Socket:connect(%s %d) failed, error=%d!", peer_name, peer_port, GetLastError() );
            closesocket( _sock );
            return;
        }

        printf( "Connect %s %d\r\n", peer_name, peer_port );
    }

    ~Socket()
    {
        closesocket( _sock );
    }

    void Send( char* data, int data_len )
    {
        send( _sock, data, data_len, 0 );
        printf( "[Send] %s", data );
    }

    void SendEx( char* format, ... )
    {
        char data[1024];
        int data_len = 1024;

        va_list vl;
        va_start( vl, format );
        vsprintf( data, format, vl );
        va_end( vl );

        Send( data, ( int )strlen( data ) );
    }

    int Recv( OUT char* data, int data_len )
    {
        int recv_len = recv( _sock, data, data_len, 0 );
        printf( "[Recv] %s", data );

        return recv_len;
    }

    int TempRecv()
    {
        char data[1024];
        int data_len = 1024;
        memset( data, 0, sizeof( char ) * 1024 );
        return Recv( data, data_len );
    }

private:
    SOCKET _sock;
};

class Mail
{
public:
    Mail( const char* sender, const char* reciver, const char* title, const char* content )
    {
        _sender = sender;
        _reciver = reciver;
        _title = title;
        _content = content;
    }

public:
    string _sender;
    string _reciver;
    string _title;
    string _content;
};

class SMTPWrap
{
public:
    SMTPWrap() {}

    ~SMTPWrap() {}

    void SendMail( Mail& mail, const char* smtp_server, int smtp_port )
    {
        Socket sock( smtp_server, smtp_port );
        sock.TempRecv();

        sock.SendEx( "EHLO %s\r\n", mail._sender.c_str() );
        sock.TempRecv();

        // login
        {
            sock.SendEx( "AUTH LOGIN\r\n" );
            sock.TempRecv();

            char buf[1024];
            memset( buf, 0, sizeof( char ) * 1024 );
            Base64Encode( ACCOUNT, ( int )strlen( ACCOUNT ), buf );
            sock.SendEx( "%s\r\n", buf );
            sock.TempRecv();

            memset( buf, 0, sizeof( char ) * 1024 );
            Base64Encode( PASSWORD, ( int )strlen( PASSWORD ), buf );
            sock.SendEx( "%s\r\n", buf );
            sock.TempRecv();
        }

        // mail head
        {
            sock.SendEx( "MAIL FROM:<%s>\r\n", mail._sender.c_str() );
            sock.TempRecv();
            
            sock.SendEx( "RCPT TO:<%s>\r\n", mail._reciver.c_str() );
            sock.TempRecv();
        }

        // mail body
        {
            sock.SendEx( "DATA\r\nSubject:%s\r\nFrom:%s\r\nTo:%s\r\n\r\n%s%s", 
                mail._title.c_str(), mail._sender.c_str(), mail._reciver.c_str(), mail._content.c_str(), MAIL_END );
        }

        sock.SendEx( "QUIT\r\n" );
        sock.TempRecv();
    }
};

void InitNet()
{
    WSAData data;
    WSAStartup( MAKEWORD( 2, 2 ), &data );
}

void ReleaseNet()
{
    WSACleanup();
}

void main()
{
    InitNet();
    
    Mail mail( SENDER, RECIVER, TITLE, "这是封测试邮件\r\nabcdefg1234567" );

    SMTPWrap smtp;
    smtp.SendMail( mail, SMTP_SERVER, SMTP_PORT );

    getch();
    ReleaseNet();
}
View Code