邮件解析(源码)

存储邮件信息的结构:

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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是 PHP 中使用 POP3 模块收取邮件的示例代码: ```php <?php /* POP3服务器信息 */ $pop3_server = "pop3.example.com"; $username = "your-email@example.com"; $password = "your-password"; /* 连接到 POP3 服务器 */ $pop3 = fsockopen("ssl://".$pop3_server, 995, $errno, $errstr, 30); /* 检查连接是否成功 */ if (!$pop3) { die("POP3 连接失败!"); } /* 接收 POP3 服务器返回的欢迎信息 */ $response = fgets($pop3, 1024); /* 发送登录命令 */ fputs($pop3, "USER $username\r\n"); $response = fgets($pop3, 1024); fputs($pop3, "PASS $password\r\n"); $response = fgets($pop3, 1024); /* 发送获取邮件列表命令 */ fputs($pop3, "LIST\r\n"); $response = fgets($pop3, 1024); /* 解析邮件列表 */ $emails = explode("\r\n", $response); array_shift($emails); array_pop($emails); /* 循环处理每一封邮件 */ foreach ($emails as $email) { /* 解析邮件大小和编号 */ list($number, $size) = explode(" ", $email); /* 发送获取邮件命令 */ fputs($pop3, "RETR $number\r\n"); /* 接收邮件内容 */ $content = ""; while (!feof($pop3)) { $content .= fgets($pop3, 1024); } /* 解析邮件信息 */ $header = ""; $body = ""; $is_header = true; $lines = explode("\r\n", $content); foreach ($lines as $line) { if ($is_header && strpos($line, ":") !== false) { $header .= $line."\r\n"; } else { $is_header = false; $body .= $line."\r\n"; } } /* 获取发件人信息 */ preg_match("/From: (.*)\r\n/i", $header, $matches); $from = $matches[1]; /* 获取收件人信息 */ preg_match("/To: (.*)\r\n/i", $header, $matches); $to = $matches[1]; /* 获取邮件主题 */ preg_match("/Subject: (.*)\r\n/i", $header, $matches); $subject = $matches[1]; /* 获取邮件日期 */ preg_match("/Date: (.*)\r\n/i", $header, $matches); $date = date("Y-m-d H:i:s", strtotime($matches[1])); /* 输出邮件信息 */ echo "主题:$subject<br>"; echo "发件人:$from<br>"; echo "收件人:$to<br>"; echo "日期:$date<br>"; echo "正文:<br>$body<br><br>"; } /* 发送退出命令 */ fputs($pop3, "QUIT\r\n"); /* 关闭 POP3 连接 */ fclose($pop3); ?> ``` 以上代码中,首先通过 `fsockopen()` 函数连接到 POP3 服务器,并发送登录命令进行身份验证。然后发送获取邮件列表命令,解析邮件大小和编号,并循环处理每一封邮件。对于每一封邮件,发送获取邮件命令,并解析邮件内容和邮件头信息,包括发件人、收件人、主题等。最后输出邮件信息,并发送退出命令关闭连接。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yueyue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值