源文件:
#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 = "qurqur@163.net"; pREI->strTo = "qurqur@163.net; 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