存储邮件信息的结构:
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;}