使用smtp发送邮件(源码)

类别:编程语言 点击:0 评论:0 推荐:

 

源文件:

#include <vcl.h>
#pragma hdrstop

#include "sendmail.h"
#include "mmsystem.h"

#pragma package(smart_init)

struct RecvEmailInfo
{
    AnsiString     strSubject, strFrom, strTo, strContent, strCmdDate, strCmdNum;
    int            nRecNum, nSendCount;
    TList         *AttachList;
};

struct AttachInfo
{
    AnsiString     FileName;
    int            Length;
    BYTE          *Content;
};
__fastcall TSendMailThread::TSendMailThread(bool CreateSuspended,int sleeptime )
 : TThread(CreateSuspended)
{
 Ftime           = sleeptime;
    FreeOnTerminate = true;
    nSendFlag       = -1;
    nCommandKind    = 0;
    strBoundary     = "----Mailor_of_qurqur.China----";

    RecvEmailList= new TList;


    /*TMemoryStream *ms = new TMemoryStream();
    ms->LoadFromFile( "d:\\test.txt" );
    RecvEmailInfo * pREI;
    AttachInfo * pAI;
    for( int i = 0; i < 5; i ++ )
    {
        pAI = new AttachInfo;
        pREI = new RecvEmailInfo;
        pAI->FileName = "test.txt";
        pAI->Length   = ms->Size;
        pAI->Content = new BYTE[ ms->Size ];
        ms->Position = 0;
        ms->ReadBuffer( pAI->Content, ms->Size );
        pREI->AttachList = new TList;
        pREI->AttachList->Add( pAI );
        pREI->strSubject = "humor";
        pREI->strFrom = "[email protected]";
        pREI->strTo   = "[email protected];
        pREI->strContent = "test";
        pREI->nSendCount = 5;
        RecvEmailList->Add( pREI );
    }
    delete ms;*/
}
void __fastcall TSendMailThread::Execute()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    int err;

    wVersionRequested = MAKEWORD( 2, 2 );

    err = WSAStartup( wVersionRequested, &wsaData );
    if ( err != 0 )
    {
        // Tell the user that we could not find a usable WinSock DLL.
        return;
    }
    if ( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 )
    {
        // Tell the user that we could not find a usable WinSock DLL.
        WSACleanup( );
        return;
    }
   
 while( !Terminated )
    {
        if( !bCanSendEmail )
        {
            Sleep( Ftime );
            continue;
        }
        SendDeal();
        Sleep( 10 );
    }
}
int __fastcall TSendMailThread::InitSocket()
{
    smtpclient = socket( AF_INET, SOCK_STREAM, 0 );
    if( smtpclient == INVALID_SOCKET )
    {
        return -1;
    }
    HOSTENT* hostinfo = gethostbyname( strSMTPServer.c_str() );
    if( hostinfo == NULL )
        return -1;

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons( nSMTPPort );
    memcpy( &server.sin_addr, *hostinfo->h_addr_list, sizeof( server.sin_addr ) );
    int rval = connect( smtpclient, ( struct sockaddr* )&server, sizeof( server ) );
    if( rval == SOCKET_ERROR )
    {
       // rval = WSAGetLastError();
        return -1;
    }
    return 0;
}
void __fastcall TSendMailThread::SendDeal()
{
    unsigned int new_time;
    char aa[ 8200 ];
    int err, len;
    switch( nSendFlag )
    {
    case -1 :
       if( HaveEmail() )
       {
           err = InitSocket();
           if( err == -1 )
           {
               nSendFlag = 1;

              strcpy( buf, "error" );

              nCommandKind = 9;

           }
           else
           {
               strBeginTime = Now().FormatString( "yyyy-mm-dd hh:mm:ss" );
               nSendFlag = 0;
               nCommandKind = 0;
           }
       }
    break;
    case 0 :
        len = recv( smtpclient, buf, 8192, 0 );
        if( len == SOCKET_ERROR )//err
        {
            nSendFlag = 1;

            nCommandKind = 9;

            break;
        }
        buf[ len ] = 0;
        nSendFlag = 1;
    break;
    case 1 :
        switch( nCommandKind )
        {
        case 0 :
            if( AnsiString( buf ).AnsiPos( "220" ) != 0 )
            {
                //连接成功,发送HELO
                strcpy( buf, "helo " );
                strcat( buf, strSMTPServer.c_str() );
                strcat( buf, "\r\n" );
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {

                    nCommandKind = 9;

                    strcpy( buf, "error" );

                    break;
                }
                nSendFlag = 0;
                nCommandKind = 2;
            }
            else
            {
                                    nCommandKind = 9;

                    strcpy( buf, "error" );;
            }
        break;
        case 2 ://受到HELO应答,身份验证
            if( AnsiString( buf ).AnsiPos( "250" ) != 0 )
            {
                strcpy( buf, "auth login" );
                strcat( buf, "\r\n" );
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {
                    nCommandKind = 9;

                    strcpy( buf, "error" );
                    break;
                }
                nSendFlag = 0;
                nCommandKind = 3;
            }
            else
            {
                    nCommandKind = 9;

                    strcpy( buf, "error" );
            }
        break;
        case 3 ://收到应答 用户名
           if( AnsiString( buf ).AnsiPos( "334" ) != 0 )
           {
               strcpy( buf, Encode_Name.c_str() );
               strcat( buf, "\r\n" );
               if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
               {
                    nCommandKind = 9;

                    strcpy( buf, "error" );
                   break;
               }
               nSendFlag = 0;
               nCommandKind = 4;
          }
          else
          {
              strcpy( buf, "mail from: " );
              strcat( buf, FromAddress.c_str() );
              strcat( buf, "\r\n" );
              if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
              {
                    nCommandKind = 9;

                    strcpy( buf, "error" );

                  break;
              }
              nSendFlag = 0;
              nCommandKind = 6;//no auth
          }
        break;
        case 4 ://受到应答 密码
            if( AnsiString( buf ).AnsiPos( "334" ) != 0 )
            {
                strcpy( buf, Encode_Key.c_str() );
                strcat( buf, "\r\n" );
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                    break;
                }
                nSendFlag = 0;
                nCommandKind = 5;
            }
            else
            {
                    nCommandKind = 9;

                    strcpy( buf, "error" );
            }
        break;
        case 5 ://应答  MAIL FROM
            if( AnsiString( buf ).AnsiPos( "235" ) != 0 )
            {
                strcpy( buf, "mail from: " );
                strcat( buf, FromAddress.c_str() );
                strcat( buf, "\r\n" );
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                    break;
                }
                nSendFlag = 0;
                nCommandKind = 6;
            }
            else
            {
                    nCommandKind = 9;

                    strcpy( buf, "error" );
            }
        break;
        case 6 ://应答  RCPT TO
            if( AnsiString( buf ).AnsiPos( "250" ) != 0 )
            {
                strcpy( buf, "rcpt to: " );
                strcat( buf, recv_temp->strTo.c_str() );
                strcat( buf, "\r\n" );
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                    break;
                }
                nSendFlag = 0;
                nCommandKind = 7;
            }
            else
            {
                    nCommandKind = 9;

                    strcpy( buf, "error" );
            }
        break;
        case 7 ://应答  DATA
            if( AnsiString( buf ).AnsiPos( "250" )!=0 )
            {
                strcpy( buf, "data\r\n" );
                strcat( buf, "\r\n" );
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                    break;
                }
                nSendFlag = 0;
                nCommandKind = 8;
            }
            else
            {
                    nCommandKind = 9;

                    strcpy( buf, "error" );
            }
        break;
        case 8 ://应答  内容
            if( AnsiString( buf ).AnsiPos( "354" )!=0 )
            {
                strcpy( buf, "Date: " );
                strcat( buf, FormatDateTime( "yyyy-mm-dd hh:nn:ss", Now() ).c_str() );
                strcat( buf, "\r\nSubject: " );
                strcat( buf, recv_temp->strSubject.c_str() );
                strcat( buf, "\r\nFrom: " );
                strcat( buf, recv_temp->strFrom.c_str() );
                strcat( buf, "\r\nTo: " );
                strcat( buf, recv_temp->strTo.c_str() );
                strcat( buf, "\r\n" );
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                    break;
                }
                if( recv_temp->AttachList != NULL && recv_temp->AttachList->Count > 0 )
                {
                    strcpy( buf, "MIME-Version: 1.0\r\n" );
                    strcat( buf, "Content-Type: multipart/mixed;\r\n" );
                    strcat( buf, "\tboundary=\"" );
                    strcat( buf, strBoundary.c_str() );
                    strcat( buf, "\"\r\n\r\n" );//space line
                    strcat( buf, "This is a multi-part message in MIME format.\r\n\r\n" );//space line
                    strcat( buf, ( "--" + strBoundary + "\r\n" ).c_str() );
                    strcat( buf, "Content-Type: text/plain;\r\n\tcharset=\"gb2312\"\r\n" );
                    strcat( buf, "Content-Transfer-Encoding: 7bit\r\n\r\n" );//space line
                    if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                    {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                        break;
                    }
                    if( SendMailText() == -1 )//发送邮件正文失败
                    {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                        break;
                    }
                    if( SendAttach() == -1 )//发送邮件附件失败
                    {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                        break;
                    }
                    strcpy( buf, ( "\r\n--" + strBoundary + "--\r\n" ).c_str() );
                    if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                    {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                        break;
                    }
                }
                else
                {
                    if( SendMailText() == -1 )//发送邮件正文失败
                    {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                        break;
                    }
                }
                strcpy( buf, "\r\n\r\n\r\n.\r\n");
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {
                    nCommandKind = 9;

                    strcpy( buf, "error" );                    break;
                }
                nSendFlag = 0;
                nCommandKind = 9;
            }
            else
            {
                    nCommandKind = 9;

                    strcpy( buf, "error" );            }
        break;
        case 9 ://应答 quit
            if( AnsiString( buf ).AnsiPos( "250" ) != 0 )
            {
                Fsuccess = 0;
                strEndTime = Now().FormatString( "yyyy-mm-dd hh:mm:ss" );
                RecvResult();
                if( HaveEmail() )
                {
                    strBeginTime = Now().FormatString( "yyyy-mm-dd hh:mm:ss" );
                    strcpy( buf, "mail from: " );
                    strcat( buf, FromAddress.c_str() );
                    strcat( buf, "\r\n" );
                    if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                    {
                        closesocket( smtpclient );
                        nSendFlag = -1;
                        break;
                    }
                    nSendFlag = 0;
                    nCommandKind = 6;
                }
                else
                {
                    strcpy( buf, "quit\r\n" );
                    if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                    {
                        closesocket( smtpclient );
                        nSendFlag = -1;
                        break;
                    }
                    nSendFlag = 0;
                    nCommandKind = 10;
                }
            }
            else
            {
                Fsuccess = 1;
                RecvResult();
                closesocket( smtpclient );
                nSendFlag = -1;
                Sleep( Ftime );
            }
        break;
        case 10 ://应答
            if( AnsiString( buf ).AnsiPos( "221" ) != 0 )
            {
            Sleep( Ftime );
            }
            nSendFlag = -1;
        break;
        }
    break;
    }
}
bool __fastcall TSendMailThread::HaveEmail()
{
         if( RecvEmailList->Count == 0 )
        {
                  return false;
        }
        else
        {
            recv_temp = ( RecvEmailInfo* )RecvEmailList->Items[ 0 ];
            RecvEmailList->Delete( 0 );
            return true;
        }
    }
    return false;
}
int __fastcall TSendMailThread::SendMailText()
{
    int pos, len;
    AnsiString strContent;
    while( ( pos = recv_temp->strContent.AnsiPos( "\r" ) ) != 0 )
    {
        len = recv_temp->strContent.Length();
        strContent += recv_temp->strContent.SubString( 1, pos );
        pos ++;
        if( recv_temp->strContent[ pos ] != '\n' )
           strContent += "\n";
        recv_temp->strContent = recv_temp->strContent.SubString( pos, len - pos + 1 );
    }
    strContent += recv_temp->strContent + "\r\n";
    while( ( pos = strContent.AnsiPos( "\r\n.\r\n" ) ) != 0 )
    {
        strContent = strContent.Insert( ".", pos + 2 );
    }
    len = 8192;
    AnsiString strSend;
    while( len <= strContent.Length() )
    {
        strSend = strContent.SubString( 1, len );
        strContent = strContent.SubString( len + 1, strContent.Length() - pos );
        if( SOCKET_ERROR == send( smtpclient, strSend.c_str(), strSend.Length(), 0 ) )
        {
            return -1;
        }
    }
    len = strContent.Length();
    if( len > 0 )
    {
        if( SOCKET_ERROR == send( smtpclient, strContent.c_str(), len, 0 ) )
        {
            return -1;
        }
    }
    return 0;
}
int __fastcall TSendMailThread::SendAttach()
{
    if( recv_temp->AttachList == NULL )
        return 0;
    TList* List = recv_temp->AttachList;
    AttachInfo *pAI;
    int         len, last;
    char       *chBuf;
    for( int i = 0; i < List->Count; i++ )
    {
        pAI = ( AttachInfo* )List->Items[ i ];
        if( pAI != NULL )
        {
            strcpy( buf, ( "\r\n--" + strBoundary + "\r\n" ).c_str() );
            strcat( buf, "Content-Type: application/octet-stream\r\n" );
            strcat( buf, "Content-Transfer-Encoding: base64\r\n" );
            strcat( buf, "Content-Disposition: attachment; filename=\"" );
            if( pAI->FileName == "" )
                pAI->FileName = "attach" + AnsiString( i );
            strcat( buf, ( pAI->FileName + "\"\r\n\r\n" ).c_str() );
            if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
            {
                return -1;
            }
            len = pAI->Length * 4 / 3 + 10;
            chBuf = new char[ len ];
            Encode_base64( pAI->Content, pAI->Length, chBuf, len );
            last = 0;
            while( len - last >= 76 )//78bytes per line
            {
                memcpy( buf, chBuf + last, 76 );
                last += 76;
                buf[ 76 ] = '\r';
                buf[ 77 ] = '\n';
                buf[ 78 ] = 0;
                if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
                {
                    return -1;
                }
            }
            memcpy( buf, chBuf + last, len - last );
            buf[ len - last ] = '\r';
            buf[ len - last + 1 ] = '\n';
            buf[ len - last + 2 ] = 0;
            if( SOCKET_ERROR == send( smtpclient, buf, strlen( buf ), 0 ) )
            {
                return -1;
            }
            delete [] chBuf;
        }
    }
    return 0;
}
void __fastcall TSendMailThread::RecvResult()
{
    int Num = recv_temp->nSendCount - 1;
    if( Fsuccess == 0 || Num == 0 )
    {
        Synchronize( SaveSend );
        if( recv_temp->AttachList != NULL )
        {
            AttachInfo* pAI;
            while( recv_temp->AttachList->Count > 0 )
            {
                pAI = ( AttachInfo* )recv_temp->AttachList->Items[ 0 ];
                if( pAI != NULL )
                {
                    delete [] pAI->Content;
                    delete pAI;
                }
            }
            delete recv_temp->AttachList;
        }
        delete recv_temp;
        recv_temp = NULL;
        Synchronize( Refresh );
    }
    else
    {
        recv_temp->nSendCount = Num;
        RecvEmailList->Add( recv_temp );
    }
}

头文件:

#ifndef sendmailH
#define sendmailH
#include <Classes.hpp>

struct RecvEmailInfo;
struct AttachInfo;


class TSendMailThread : public TThread
{
private:
 int                Ftime;     //休眠时间
    int                nRecNum;
    TMemoryStream     *SendBuf;
    AnsiString         strBeginTime, strEndTime, strBoundary;
    AnsiString         strSubject, strFrom, strTo, strContent, strCmdDate, strCmdNum;
    RecvEmailInfo     *recv_temp;
    BYTE               Fsuccess;//=0成功;=1失败;=2未发
    SOCKET             smtpclient;
    char               buf[ 8200 ];
    int                nCommandKind;
    int                nSendFlag;

    TList *RecvEmailList;

    int  __fastcall InitSocket();
    void __fastcall SaveSend();
    void __fastcall SendDeal();
    void __fastcall DealWait();
    void __fastcall RecvResult();
    void __fastcall Refresh();
    bool __fastcall HaveEmail();
    int  __fastcall SendMailText();
    int  __fastcall SendAttach();
protected:
 void __fastcall Execute();
public:
 __fastcall TSendMailThread(bool CreateSuspended,int sleeptime );
};

#endif

 

本文地址:http://com.8s8s.com/it/it30224.htm