源文件:
#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[url=mailto:test5678@163.com]@163.net";
pREI->strTo = "qurqur[url=mailto:test5678@163.net]@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