存储邮件信息的结构:
struct ContentHeader{
int nType;//=(1)0 text/plain, =(1)1 text/html, =(1)2 maybe attach
AnsiString strTransferEncoding;
AnsiString strContent;
AnsiString strFileName;//for attachment
};
处理每一行的函数,处理完成存入结构体ContehtHeader,并存入链表CHList( TList* )
void __fastcall TRecvMailThread::DealLine(char* line, int len)
{
int pos;
AnsiString strLine( line );
AnsiString strTemp( line );
strLine = strLine.LowerCase();
switch( nItemKind )
{
case 0 :
if( strLine == "" && nItems >= 1 )//第一部分结束
{
nItemKind = 1;//进入下一部分
break;
}
if( ( pos = strLine.AnsiPos( "from:" ) ) == 1 )
{
if( strFrom == "" )
{
strFrom = strTemp.SubString( pos + 5, len - pos - 4 );
if( strFrom[ 1 ] == 0x20 )
strFrom = strFrom.SubString( 2, strFrom.Length() - 1 );
nItems ++;
}
}
else if( ( pos = strLine.AnsiPos( "to:" ) ) == 1 )
{
if( strTo == "" )
{
strTo = strTemp.SubString( pos + 3, len - pos - 2 );
if( strTo[ 1 ] == 0x20 )
strTo = strTo.SubString( 2, strTo.Length() - 1 );
nItems ++;
}
}
else if( ( pos = strLine.AnsiPos( "subject:" ) ) == 1 )
{
if( strSubject == "" )
{
strSubject = strTemp.SubString( pos + 8, len - pos - 7 );
if( strSubject[ 1 ] == 0x20 )
strSubject = strSubject.SubString( 2, strSubject.Length() - 1 );
nItems ++;
}
}
else if( ( pos = strLine.AnsiPos( "content-type: multipart" ) ) != 0 )
{
if( ( pos = strLine.AnsiPos( "boundary=" ) ) != 0 )
{
strNormalBoundary = strTemp.SubString( pos + 9, len - pos - 8 );
if( strNormalBoundary[ 1 ] == '\"' )
strNormalBoundary = strNormalBoundary.SubString( 2, strNormalBoundary.Length() - 2 );
bBoundary = true;
}
}
else if( ( pos = strLine.AnsiPos( "boundary=" ) ) != 0 )
{
strNormalBoundary = strTemp.SubString( pos + 9, len - pos - 8 );
if( strNormalBoundary[ 1 ] == '\"' )
strNormalBoundary = strNormalBoundary.SubString( 2, strNormalBoundary.Length() - 2 );
bBoundary = true;
}
else if( ( pos = strLine.AnsiPos( "content-type: text/plain" ) ) != 0 )
{
nTextKind = 0;
pCH->nType = 0;
}
else if( ( pos = strLine.AnsiPos( "content-type: text/html" ) ) != 0 )
{
nTextKind = 1;
pCH->nType = 1;
}
else if( ( pos = strLine.AnsiPos( "content-transfer-encoding: " ) ) != 0 )
{
strTempEncode = strLine.SubString( pos + 27, len - pos - 26 );
pCH->strTransferEncoding = strTempEncode;
}
break;
case 1 :
if( bBoundary )
{
if( strTemp.AnsiPos( strNormalBoundary ) != 0 )
{
file://找到边界,
nItemKind = 2;
nItems = 0;
bBoundary = false;
}
}
else
{
file://没有边界,以下为邮件正文部分,至 "." 结束
pCH->strContent = strTemp;
nItemKind = 111;
}
break;
case 111 :
if( strLine != "." )
{
pCH->strContent += strTemp;
pCH->strContent += "\r\n";
}
else
{
CHList->Add( pCH );
nItemKind = ALL_READY;
}
break;
case 2 :
file://在此查找Content-Type, Content-Transfer-Encoding, boundary, Content-Disposition等
//.........
if( strLine == "" && nItems >= 1 )
{
file://进入下一部分
nItemKind = 3;
nItems = 0;
break;
}
if( ( pos = strLine.AnsiPos( "content-type:" ) ) != 0 )
{
nItems ++;
if( strLine.AnsiPos( "multipart/" ) != 0 )
{
if( ( pos = strLine.AnsiPos( "boundary=" ) ) != 0 )
{
strExpandBoundary = strTemp.SubString( pos + 9, len - pos - 8 );
if( strExpandBoundary[ 1 ] == '\"' )
strExpandBoundary = strExpandBoundary.SubString( 2, strExpandBoundary.Length() - 2 );
bBoundary = true;
}
nItemKind = 222;
break;
}
if( strLine.AnsiPos( "text/plain" ) != 0 )
nTextKind = 0;
else if( strLine.AnsiPos( "text/html" ) != 0 )
nTextKind = 1;
else
nTextKind = 2;
pCH->nType = nTextKind;
}
else if( ( pos = strLine.AnsiPos( "content-transfer-encoding:" ) ) != 0 )
{
nItems ++;
pCH->strTransferEncoding = strLine.SubString( pos + 27, len - pos - 26 );
}
else if( strLine.AnsiPos( "content-disposition:" ) != 0 )
{
if( ( pos = strLine.AnsiPos( "filename=\"" ) ) != 0 )
{
nItems ++;
pCH->strFileName = strTemp.SubString( pos + 10, len - pos - 10 );
bAttach = true;
}
}
else if( ( pos = strLine.AnsiPos( "filename=\"" ) ) != 0 )
{
nItems ++;
pCH->strFileName = strTemp.SubString( pos + 10, len - pos - 10 );
bAttach = true;
}
break;
case 3 :
file://接收内容to pCH->strContent
if( strTemp == "." )
{
CHList->Add( pCH );
nItemKind = ALL_READY;
break;
}
if( strTemp.AnsiPos( strNormalBoundary ) != 0 )
{
CHList->Add( pCH );
if( strTemp.AnsiPos ( strNormalBoundary + "--" ) == 0 )//未到最后
{
nItemKind = 2;
pCH = new ContentHeader;
}
else
{
nItemKind = ALL_READY;
break;
}
}
else
{
pCH->strContent += strTemp;
pCH->strContent += "\r\n";
}
break;
case 222 :
file://Microsoft Outlook Express
if( bBoundary )
{
nItemKind = 333;
}
else if( ( pos = strLine.AnsiPos( "boundary=" ) ) != 0 )
{
strExpandBoundary = strTemp.SubString( pos + 9, len - pos - 8 );
if( strExpandBoundary[ 1 ] == '\"' )
strExpandBoundary = strExpandBoundary.SubString( 2, strExpandBoundary.Length() - 2 );
nItemKind = 333;
}
break;
case 333 :
if( ( pos = strTemp.AnsiPos( strExpandBoundary ) ) != 0 )
{
nItemKind = 444;
nItems = 0;
}
break;
case 444 :
file://在此查找Content-Type, Content-Transfer-Encoding, boundary, Content-Disposition等
//.........
if( strLine == "" && nItems >= 1 )
{
file://进入下一部分
nItemKind = 555;
nItems = 0;
break;
}
if( ( pos = strLine.AnsiPos( "content-type:" ) ) != 0 )
{
nItems ++;
strLine = strLine.SubString( pos + 13, len - pos - 12 );
if( strLine.AnsiPos( "text/plain" ) != 0 )
nTextKind = 10;
else if( strLine.AnsiPos( "text/html" ) != 0 )
nTextKind = 11;
else
nTextKind = 12;
pCH->nType = nTextKind;
}
else if( ( pos = strLine.AnsiPos( "content-transfer-encoding:" ) ) != 0 )
{
nItems ++;
pCH->strTransferEncoding = strLine.SubString( pos + 27, len - pos - 26 );
}
else if( strLine.AnsiPos( "content-disposition:" ) != 0 )
{
if( ( pos = strLine.AnsiPos( "filename=\"" ) ) != 0 )
{
nItems ++;
pCH->strFileName = strTemp.SubString( pos + 10, len - pos - 10 );
}
}
else if( ( pos = strLine.AnsiPos( "filename=\"" ) ) != 0 )
{
nItems ++;
pCH->strFileName = strTemp.SubString( pos + 10, len - pos - 10 );
}
break;
case 555 :
file://接收内容to pCH->strContent
if( strTemp == "." )
{
CHList->Add( pCH );
nItemKind = ALL_READY;
break;
}
if( strTemp.AnsiPos( strExpandBoundary ) != 0 )
{
CHList->Add( pCH );
pCH = new ContentHeader;
if( strTemp.AnsiPos ( strExpandBoundary + "--" ) == 0 )//未到最后
{
nItemKind = 444;
nItems = 0;
}
else
{
nItemKind = 1;
bBoundary = true;
break;
}
}
else
{
pCH->strContent += strTemp;
pCH->strContent += "\r\n";
}
break;
}
}
将收取的邮件原文分行处理
mail为TMemoryStream*, 存放的是邮件原文。
int __fastcall TRecvMailThread::DealMailInfo()
{
int len = mail->Size;
int rval, i = 0;
mail->Position = 0;
char line[ 1024 ];
nItems = 0;
nItemKind = 0;
nTextKind = 0;//default
bAttach = false;
bBoundary = false;
strFrom = "";
strTo = "";
strSubject = "";
strTempEncode = "";
pCH = new ContentHeader;//初始生成一ContentHeader结构
while( mail->Position < len )
{
if( i >= 1022 )//一行长度超出1024
{
line[ i ] = 0;
DealLine( line, i );
if( nItems == ALL_READY )
{
return 1;//完成
}
i = 0;
}
mail->ReadBuffer( line + i, 1 );
if( line[ i ] == '\r')
{
i ++;
mail->ReadBuffer( line + i, 1 );
if( line[ i ] == '\n')
{
line[ i - 1 ] = 0;
DealLine( line, i - 1 );
if( nItemKind == ALL_READY )
{
return 1;//完成
}
i = -1;
}
else
{
mail->Position -= 1;
i -= 1;
}
}
i ++;
}
return 1;
}