利用POP3协议,如何提取收到邮件的附件?

Wolfe 2004-03-02 12:33:01
我用POP3协议收到了邮件的全文包括经过BASE64编码的附件,怎样才能把这段附件编码提取出来呢?邮件中好像没有附件的起始和结束标志啊,是不是每个发送邮件的smtp服务器都有约定的附件起始和结束标记?
...全文
1268 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
Wolfe 2004-04-06
  • 打赏
  • 举报
回复
// Base64Dec.h: interface for the CBase64Dec class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_BASE64DEC_H__317D83B2_2990_434F_BF3C_33483F34A7DF__INCLUDED_)
#define AFX_BASE64DEC_H__317D83B2_2990_434F_BF3C_33483F34A7DF__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "stdafx.h"
#include <windows.h>
typedef unsigned char uchar;
class CBase64Dec
{
private:
//HFILE m_hfile;
HANDLE m_hfile;
uchar m_uchStoredChars[4];
int m_iChars;
public:
enum { RESULT_OK = 0, RESULT_ERROR = -1 };

CBase64Dec() : m_hfile(NULL), m_iChars(0) {};
virtual ~CBase64Dec()
{
if (m_hfile != NULL)
//_lclose(m_hfile);
{
CloseHandle(m_hfile);
m_hfile=NULL;
}
};

int OpenFile(char * pszFileName);
int DecodeLine(char * pszLine, int nLineLen);
int DecodeLine(char * pszLine, int nLineLen, uchar * uchBuffer, int nBufferLen);
};

#endif // !defined(AFX_BASE64DEC_H__317D83B2_2990_434F_BF3C_33483F34A7DF__INCLUDED_)


// Base64Dec.cpp: implementation of the CBase64Dec class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Base64Dec.h"

/////////////////////////////////////////////////////////////////////////////
// BASE64CODE
const char szBASE64CODE[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define ENCODE_BYTE(b) szBASE64CODE[((char)b) & 077];
/////////////////////////////////////////////////////////////////////////////
// CBase64 message handlers

int DecodeValue(const int c)
{
// Note that this works only on ASCII machines.
if ('A' <= c && c <= 'Z')
return c - 'A';
if ('a' <= c && c <= 'z')
return c - 'a' + 26;
if ('0' <= c && c <= '9')
return c - '0' + 52;
if (c == '+')
return 62;
if (c == '/')
return 63;
if (c == '=')
return -1;
return -2;
}


/////////////////////////////////////////////////////////////////////////////
// Function: CBase64Dec::OpenFile
// Description:
// Open a file that we can write the characters to.
/////////////////////////////////////////////////////////////////////////////
int CBase64Dec::OpenFile(char * pszFileName)
{
// Open the file. Handle any errors.
//m_hfile = _lopen(pszFileName, OF_WRITE);
m_hfile=CreateFile(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

//if (m_hfile == HFILE_ERROR)
if (m_hfile == NULL)
{
m_hfile = NULL;
return RESULT_ERROR;
}
else
return RESULT_OK;
}

/////////////////////////////////////////////////////////////////////////////
// Function: CBase64Dec::DecodeLine
// Description:
// Decode a line of data and write the bytes to the open file.
/////////////////////////////////////////////////////////////////////////////
int CBase64Dec::DecodeLine(char * pszLine, int nLineLen)
{
DWORD Written;
uchar * uchBuffer = new uchar[nLineLen];
int nDecodedLen = DecodeLine(pszLine, nLineLen, uchBuffer, nLineLen);
if (nDecodedLen >= 0)
{
//if (_lwrite(m_hfile, (LPCSTR)uchBuffer, nDecodedLen) == (UINT)HFILE_ERROR)
if (WriteFile(m_hfile, (LPCSTR)uchBuffer, nDecodedLen, &Written, NULL) == NULL)
nDecodedLen = RESULT_ERROR;
}
delete[] uchBuffer;
return nDecodedLen;
}

/////////////////////////////////////////////////////////////////////////////
// Function: CBase64Dec::DecodeLine
// Description:
// Simply decode a line of bytes. Note that a file doesn't
// have to be opened to use this member function. Returns
// the count of the decoded bytes or -1 on error.
/////////////////////////////////////////////////////////////////////////////
int CBase64Dec::DecodeLine(char * pszLine, int nLineLen,
uchar * uchBuffer, int nBufferLen)
{
int iLineIndex = 0;
int iBufferIndex = 0;

while (iLineIndex < nLineLen)
{
// Group together four characters for decode.
while (iLineIndex < nLineLen && m_iChars < 4)
{
int c = pszLine[iLineIndex++];
// Ignore characters that aren't BASE64 characters
// (e.g., spaces, CRLF, etc.).
if (DecodeValue(c) != -2)
m_uchStoredChars[m_iChars++] = (uchar) c;
}

if (m_iChars == 4)
{
// We've got four characters, so decode them.
m_iChars = 0;

// Decode first byte.
if (iBufferIndex == nBufferLen) return RESULT_ERROR;
uchBuffer[iBufferIndex++] = (uchar) (((uchar)DecodeValue(m_uchStoredChars[0]) << 2) | ((uchar)DecodeValue(m_uchStoredChars[1]) >> 4));

// Decode second byte.
if (iBufferIndex == nBufferLen)
return RESULT_ERROR;
if (m_uchStoredChars[2] == '=')
return iBufferIndex;
uchBuffer[iBufferIndex++] = (uchar) (((uchar)DecodeValue(m_uchStoredChars[1]) << 4) | ((uchar)DecodeValue(m_uchStoredChars[2]) >> 2));

// Decode third byte.
if (iBufferIndex == nBufferLen)
return RESULT_ERROR;
if (m_uchStoredChars[3] == '=')
return iBufferIndex;
uchBuffer[iBufferIndex++] = (uchar) (((uchar)DecodeValue(m_uchStoredChars[2]) << 6) | ((uchar)DecodeValue(m_uchStoredChars[3])));
}
}

// Return the count of decoded bytes.
return iBufferIndex;
}
Wolfe 2004-04-06
  • 打赏
  • 举报
回复
/////////////////////////////////////////////////////////
//
//解析文件路径为strPath的邮件
//
/////////////////////////////////////////////////////////
BOOL CReceiverDlg::DealMail(CString strPath)
{
CStdioFile file;
if (!file.Open(strPath,CFile::modeRead))
{
DWORD dw=GetLastError();
CString str="无法打开文件: "+strPath;
MessageBox(str);
return FALSE;
}

bool bHasAtt=false;
CString strLine;
while (file.ReadString(strLine)) //读出一行
{
if (strLine.Find("--#BOUNDARY#")>=0) //行中包含此串,有附件
{
bHasAtt=true;
break;
}
}


//得到邮件发送IP
CString strIp="";
file.SeekToBegin();
while (file.ReadString(strLine))
{
if (strLine.Find("Received: from")==0)
{
strIp=strLine;
break;
}
}


//得到邮件的日期
CString strDate="";
file.SeekToBegin();
while (file.ReadString(strLine)) //读出一行
{
if (strLine.Find("Date:")==0)
{
int n=strLine.Find(",");
n++;
CString strDay=strLine.Mid(n+1,2);
n=n+4;
int n2=strLine.Find(" ",n);
CString strMonth=strLine.Mid(n,3);
strDate=strMonth+"-"+strDay;
break;
}
}

file.Close();

if (!bHasAtt) //没有附件
{
return TRUE;
}
//有附件,提出附件存盘
CString strDir;
m_editDir.GetWindowText(strDir);
//得到上级目录
int n=strDir.ReverseFind('\\');
strDir=strDir.Left(n);
strDir=strDir+"\\"+strMacId;
strDir=strDir+"\\"+strDate;
//目录不存在则创建
CFileFind finder;
if (!finder.FindFile(strDir))
{
SECURITY_ATTRIBUTES sec_att;
sec_att.nLength=20000000;
sec_att.lpSecurityDescriptor=NULL;
sec_att.bInheritHandle=TRUE;
CreateDirectory(strDir,&sec_att);
}
else finder.Close();

SaveAttToDisk(strDir,strPath); //把邮件文件strPath中的附件提取出来存放在strDir目录下

return TRUE;
}

///////////////////////////////////////////////////////////////
//
//把邮件文件strPath中的附件提取出来存放在strDir目录下
//
///////////////////////////////////////////////////////////////
int CReceiverDlg::SaveAttToDisk(CString strDir,CString strPath)
{
CString sAttFileName;
CStdioFile rawFile;
if (!rawFile.Open(strPath,CFile::modeRead))
return -1; //无法打开文件
CString sLine;
bool bAtt=false;
int nEmpLine=0;
CBase64Dec* pB64D=new CBase64Dec();

int nAttNum=1;

BOOL bGetLine=TRUE;
while(bGetLine)
{
bGetLine=rawFile.ReadString(sLine);
int nStart=sLine.Find("filename=");
if (nStart>=0)
{
CString strTmp=sLine.Left(nStart+9);
sAttFileName=sLine;
sAttFileName.Replace(strTmp,"");
sAttFileName.Replace("\"","");
//由邮件文件名strPath构造附件名,绝对路经.
//存放目录为strDir
ConstructFileName(nAttNum,strPath,strDir,sAttFileName);
bAtt=true;
int nRet=pB64D->OpenFile(sAttFileName.GetBuffer(sAttFileName.GetLength()));
if (nRet==-1)
{
delete pB64D;
rawFile.Close();
return -1;
}
}
if (bAtt)
{
if (strstr(sLine,"filename="))
continue;
if (sLine=="")
{
if (nEmpLine==0)
{
nEmpLine++;
continue;
}
}
// then begin encoded attachment!
CString strSet="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
if (sLine=="" || strSet.Find(sLine.GetAt(0))<0) //end of attachment
{
delete pB64D;
pB64D=new CBase64Dec();
if (sLine.Find("--#BOUNDARY#--")>=0) //完
{
goto ok;
}
nAttNum++; //附件数加1
bAtt=false;
nEmpLine=0;

continue;
}
int nLen=strlen(sLine);
pB64D->DecodeLine(sLine.GetBuffer(nLen),nLen);
}
}
if (!bAtt) //no "filename=" in raw, means no attachment
{
rawFile.Close();
delete pB64D;
pB64D=NULL;
return 0;
}

ok:
delete pB64D;
pB64D=NULL;
rawFile.Close();
return 1;
}
Wolfe 2004-04-06
  • 打赏
  • 举报
回复
我没空去研究MIME,由于发送邮件程序也是我自己做的,所以接收邮件程序就按照发送时的格式解析,我的源代码:
werty 2004-04-06
  • 打赏
  • 举报
回复
to Wolfe:
收到了,多谢;我发送邮件的过程和你所说的一样,但还是有人说验证不够。

1、敢问高手们,收费邮件有什么要求?
2、邮件的提取:我发现移动梦网转过来的邮件,附件表示为:
--=====000_Dragon473416408613_=====
Content-Type: application/octet-stream;
name="msg.rar"
Content-Transfer-Encoding: base64
没有关键字:Content-Disposition,不知道该怎么解
Wolfe 2004-04-06
  • 打赏
  • 举报
回复
To lvenlee:用上面的CBase64Dec类解码没错。
To vanter:我了base64,但不了解MIME,用MIME怎么判断?恐怕没有一个通用的解析标准吧?
myzcoldking, llprince,多谢了!

To werty,给你发到邮箱里了
醉马不肖 2004-04-06
  • 打赏
  • 举报
回复
mime
lvenlee 2004-04-04
  • 打赏
  • 举报
回复
我也用BASE64解过附件,可是输出到文件还是无法还原成源文件呢,是如何问题??
vanter 2004-03-30
  • 打赏
  • 举报
回复
楼主的研究方向错了
POP3只负责收信,要分析信的内容,需要了解base64和mime,
我做过这方面的内容,没在网上找到好的源码,所以可以说至今没有公开的完善的解码程序.
希望楼主做好后能公开出来.
nanjue98 2004-03-30
  • 打赏
  • 举报
回复
楼主:在MIME中有"ATTCH"附件的表示格式的,只需要看看MIME规范
再提出“ATTCH”部分并用BASE64解码就OK了
nanjue98 2004-03-30
  • 打赏
  • 举报
回复
楼主:只需要看看MIME规范就能找到答案了
在MIME格式中就有“attach”的表示形式的,只需要把相应于“attach”的那段信息提出解码就能解决问题
myzcoldking 2004-03-29
  • 打赏
  • 举报
回复
这是OUTLook中的一封带附件的信的传输数据:
--=====000_Dragon473416408613_=====
Content-Type: text/plain;
charset="GB2312"
Content-Transfer-Encoding: quoted-printable

hello,=C2=ED=D3=D1=D6=BE=A3=AC

=09=B8=BD=BC=FE=D6=D0=B5=C4=C4=DA=C8=DD=CA=C7=D4=DB=C3=C7=C8=ED=BC=FE=D1=A7=D4=BA=D0=A3=D3=D1=C2=BC=B5=C4=B9=DC=C0=ED=D4=B1=C1=F4=D1=D4=B5=C4=D4=B4=CE=C4=BC=FE=A3=AC=CF=D6=BC=C4=B8=F8=C4=E3
=09=09=09=09

=09Best regards. =09=09=09
=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1JiaLong.Wang
=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A12003-08-01

##########
以上是信件的内容,实际是以下:
hello,马友志,

附件中的内容是咱们软件学院校友录的管理员留言的源文件,现寄给你


Best regards.
        JiaLong.Wang
                 2003-08-01
###############################

--=====000_Dragon473416408613_=====
Content-Type: application/octet-stream;
name="msg.rar"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="msg.rar"

UmFyIRoHAM+QcwAADQAAAAAAAABQm3RAgDEAvwIAAFQEAAACPd3bQVxaAS8dMxEAIAAAAGNoZWNr
YWRkX3NhdmUuYXNwDh1REQijzYFXv/5P/we3GCafHBAhIyZtkmhok1gIG5oyPZe5l4bjM+JnwNBY
。。。。。。。。。。。。。

############
这个部分就是附件内容了,呵呵
######################

这些内容是用"--=====000_Dragon473416408613_====="分割的,而这个字符串是唯一的,他是由“--”和boundary="=====000_Dragon473416408613_====="组成的。

而有没有附件就看Header部分的Content-Type: multipart/mixed;当然这里会有许多类型,POP3(rfc822)中并没有规定,在MIME中应该有规定,你可以参考。

怎么样,现在可以从你收到的数据中提取附件了吧! 呵呵,祝你好运!
myzcoldking 2004-03-29
  • 打赏
  • 举报
回复
X-Message-Info: JGTYoYF78jEHjJx36Oi8+Q1OJDRSDidP
Received: from mta2.x263.net ([211.150.96.22]) by mc6-f35.law1.hotmail.com with Microsoft SMTPSVC(5.0.2195.5600);
Thu, 31 Jul 2003 22:04:49 -0700
Received: from wangjialong (localhost [127.0.0.1])
by mta2.x263.net (Postfix) with ESMTP id 87ACF34232
for <myzcoldking@hotmail.com>; Fri, 1 Aug 2003 13:01:42 +0800 (CST)
Received: from wangjialong (unknown [61.185.224.66])
by antispam-2 (Coremail:www.263.net) with SMTP id q+DJADX0KT9VD+BC.1
for <myzcoldking@hotmail.com>; Fri, 01 Aug 2003 13:01:44 +0800 (CST)
X-Originating-IP: [61.185.224.66]
From: "=?GB2312?Q?=CD=F5=BC=D3=C1=FA?=" <ddf3@263.net>
Reply-To: ddf3@263.net
To: =?GB2312?Q?=C2=ED=D3=D1=D6=BE?= <myzcoldking@hotmail.com>
Subject: =?GB2312?Q?=D0=A3=D3=D1=C2=BC=D4=B4=B4=FA=C2=EB?=
Organization: =?GB2312?Q?=CE=F7=B0=B2=C8=ED=BC=FE=D4=B0=D2=D7=B0=B2=D0=C5=D3=D0=CF=DE=D4=F0=C8=CE=B9=AB=CB=BE?=
X-mailer: Foxmail 4.2 [cn]
Disposition-Notification-To: "=?GB2312?Q?=CD=F5=BC=D3=C1=FA?=" <ddf3@263.net>
Mime-Version: 1.0
Content-Type: multipart/mixed;
boundary="=====000_Dragon473416408613_====="
Date: Fri, 1 Aug 2003 13:1:45 +0800
Message-Id: <20030801050142.87ACF34232@mta2.x263.net>
Return-Path: ddf3@263.net
X-OriginalArrivalTime: 01 Aug 2003 05:04:49.0750 (UTC) FILETIME=[6F489F60:01C357EA]

This is a multi-part message in MIME format.

--=====000_Dragon473416408613_=====
Content-Type: text/plain;
charset="GB2312"
Content-Transfer-Encoding: quoted-printable

hello,=C2=ED=D3=D1=D6=BE=A3=AC

=09=B8=BD=BC=FE=D6=D0=B5=C4=C4=DA=C8=DD=CA=C7=D4=DB=C3=C7=C8=ED=BC=FE=D1=A7=D4=BA=D0=A3=D3=D1=C2=BC=B5=C4=B9=DC=C0=ED=D4=B1=C1=F4=D1=D4=B5=C4=D4=B4=CE=C4=BC=FE=A3=AC=CF=D6=BC=C4=B8=F8=C4=E3
=09=09=09=09

=09Best regards. =09=09=09
=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1JiaLong.Wang
=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A1=A12003-08-01

--=====000_Dragon473416408613_=====
Content-Type: application/octet-stream;
name="msg.rar"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="msg.rar"

UmFyIRoHAM+QcwAADQAAAAAAAABQm3RAgDEAvwIAAFQEAAACPd3bQVxaAS8dMxEAIAAAAGNoZWNr
YWRkX3NhdmUuYXNwDh1REQijzYFXv/5P/we3GCafHBAhIyZtkmhok1gIG5oyPZe5l4bjM+JnwNBY
+MIRj0KyJGEhEIyI/I1YoDA3wFY9D4GKyMmapu3d7t5uboxQ8F3p26r9VVdcqrzxy65zLrlVyru8
n6ujkrp/vBJPOvr7nrtKMQKjAsuwMKCjbTSInnECTif//0m4495871p9dULw3nlyfIQOyabQuqkm
N8GMeIDWDujxyOM6MT48uf2BqPlNKl5cvFRifn5HiooiLiXzpqCTm1S8ejhMiccLigWQlVXT02QF
Z5W3iCUsawoGH5a5Y3NzWs2Z1seaHtZS6jrbzaxvJSihzwJbq55SCRdxRV120o+cyvlg4aXTmZIc
pO0WlMZcYL1d+uOyzVU9Ox4HrkdLKFpYsCyxZpr9kYcPAwYmKagmprdF4PSSzBZ45y7I24HyakmI
qZzpMeFZtRQdFKdQPe1axwks49p/yfUI70jluDaApGhB1aOnx0sbSAUsptuHGKbsEIkIrHVTisrZ
oMBQ/Uwd+C7As6aIFlAUaBejBvd7yekAQIA6AOTHr9xnkW4ql4u72LpF7g3uERalATi0CTTUbXqp
fiKfYv/FI1IjD0IK+j6Kxu2SInpVpQE3bDu8Hn+0IaEyO2RS4dnihDLc9dip+v9NnxQiumxbNZub
zPRkW2/3OL2cEINE6/Qtgx2RGx5YRxtrXRd337MIUbZcE1p8iM8G53+YpmeUzFZWz6nw+7582VVm
n/6HrbFPU5ZIp59XLYI8Ow2sVXmBaVvW2vlDzTdGRZEjA4qfTNZXB/U4v0lPGmzMycDJldXIzpWR
jhQ6gtEVg91dwzUXs8f3f1UTBkj6wk3Af5l0YHX9FOl5vhv73l8Ox993b1fB6/r7dSr7ur8d7b2q
VPf8er3ClSLyiu0qb9FSwe8OREwv7+P4V38dcxPygOk/dECAKwDLBQAAcRUAAAIkoBCNW10BLx0z
CwAgAAAAYWRkc29mdC5hc3AMAVEMzM/NQVfZsB/D7Sw5G5Ik026xZEUWA20lIgE4pGjeh3xo0k6k
jIemHobjsE+YtgooFvjILYBA3LAILJbI4xHIKHIBfCgWiwXyvwMgoFCJTbR0pbpKTaSoUcD9aUA2
c3cznM6Vut58xnbudHNHN4DunOgYM5uE+kr3o0bDTWRUcSECkmoI4xFdZaOFpgx+czCwZWJu7Tbi
llprince 2004-03-28
  • 打赏
  • 举报
回复
人民邮电出版社 2003.1月出版的 《Visual C++网络通信协议分析与应用实现》有详细介绍,可以看看。
werty 2004-03-28
  • 打赏
  • 举报
回复
有那位大哥了解邮件的发送,smtp所谓的身份验证是怎么回事,希望交流: wqwanghunan@163.net
大脚板 2004-03-22
  • 打赏
  • 举报
回复
去看看MIME编码
stonesky 2004-03-22
  • 打赏
  • 举报
回复
赞成楼上的
Wolfe 2004-03-20
  • 打赏
  • 举报
回复
上面的你好像什么也没说啊
robyman 2004-03-19
  • 打赏
  • 举报
回复
看来你对此还了解的少,如果让你自己去研究协议或邮件的格式,可能要花一点点时间.
如果不愿意就找代码,不会很难,我建议你去研究一下*.eml文件的格式就明白了(在加上协议).
Fly1980 2004-03-15
  • 打赏
  • 举报
回复
关注

4,359

社区成员

发帖
与我相关
我的任务
社区描述
通信技术相关讨论
社区管理员
  • 网络通信
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧