email.cpp

来自「解析email的源代码。 mine协议 解码译码」· C++ 代码 · 共 517 行

CPP
517
字号
#include "email.h"
#include <algorithm>
#include <fstream>
#include <iostream>
using namespace std;

string& trimLeft(string& str);
string trimRight(string& str);
string& removeEnter(string& str);
string dealWithHead(string& head);


//---------------------
//mail_node的构造函数
mail_node::mail_node()
{
	code=plain;
	content_type=text;
	tag=nohtml;
	bodyBeg=NULL;
	bodyEnd=NULL;
	bound="";
	uncodeContent="";
}

Xcontent_type mail_node::getContent_type()
{return content_type;}

Xtag mail_node::getTag()
{return tag;}

Xcode mail_node::getCode()
{return code;}

Xmail_nodes& mail_node::getMail_nodes()
{
	return mail_nodes;
}

string& mail_node::getContent()
{
	content=removeEnter(trimRight(trimLeft(content)));
	return content;
}
//--------------------------
//mail的构造函数
mail::mail()
{
	from="";
	subject="";
	to="";
}


string mail::getSubject()
{
	subject=dealWithHead(subject);
	return subject;
}

string mail::getFrom()
{
	from=dealWithHead(from);
	return	from;
}

string mail::getTo()
{
	to=dealWithHead(to);
	return to;
}


//-----------------------------
//node load

mail* mail_node::getMail()
{
	return Mail;
}

char* mail_node::nodeload(const char* str)
{
	//提取文本/html类型,编码,文档结构
	//标记body开始部分,结束部分
	char* p=(char*)str;
	char* pEnd=p;
	string lowtemp="",temp="";                        //临时存储用
	string::size_type pos;
	
	if(pEnd==NULL)
		return NULL;
	while(*(pEnd)!=NULL)
	{//
		if(*pEnd=='\n')
		{
			temp.assign(p,pEnd);
			temp=trimLeft(temp);
			lowtemp=temp;
			if(!temp.empty())
			{
				for(int i=0; i<temp.size(); i++)
					{lowtemp[i]=char(tolower(lowtemp[i]));}                   //转成小写
				pos=0;
				if((pos=lowtemp.find("content-type:"))!=string::npos)
				{
					if((pos=lowtemp.find("text"))!=string::npos)
					{
						content_type=text;pos=0;
					}
					if((pos=lowtemp.find("multipart"))!=string::npos)
					{
						content_type=multipart;pos=0;
						if((pos=lowtemp.find("boundary"))!=string::npos)
						{
							string::size_type pre,back;
							pre=temp.find_first_of("\"",pos);
							back=temp.find_last_of("\"",temp.size());
							bound.assign(temp,pre+1,back-pre-1);
							pos=0;
						}
					}
					if((pos=lowtemp.find("html"))!=string::npos)
					{
						tag=html;pos=0;
					}
					if((pos=lowtemp.find("plain"))!=string::npos)
					{
						tag=nohtml;pos=0;
					}
				}
				if((pos=lowtemp.find("boundary"))!=string::npos)
				{
					string::size_type pre,back;
					pre=temp.find_first_of("\"",pos);
					back=temp.find_last_of("\"",temp.size());
					bound.assign(temp,pre+1,back-pre-1);
					pos=0;
				}
				if((pos=lowtemp.find("content-transfer-encoding:"))!=string::npos)
				{
					if((pos=lowtemp.find("base64"))!=string::npos)
					{
						code=Base64;pos=0;
					}
					if((pos=lowtemp.find("quoted-printable"))!=string::npos)
					{
						code=qp;pos=0;
					}
				}

				temp="";lowtemp="";
			}
			else
			{
				break;
			}
			p=pEnd+1;
		}
		pEnd++;
	}

	//查找边界
	p=++pEnd;             //定位到第一个空行后面第一个字符

	if(content_type==text)
	{
		bodyBeg=p;
		while(*(pEnd+1)!=NULL)
		{
			pEnd++;
		}
		bodyEnd=pEnd;
		content.assign(bodyBeg,bodyEnd);
	}

	//multipart的情况的处理
	if(content_type==multipart)
	{
		bodyBeg=p;
		char *f=NULL, *e=NULL;               //f指向子结点的头,e指向字节点的尾
		while(*(pEnd+1)!=NULL)
		{
			if(*pEnd=='\n')
			{
				temp.assign(p,pEnd);
				if((pos=temp.find(bound))!=string::npos)
				{
					if(f==NULL)
					{
						e=pEnd+1;
						f=e;
					}
					else
					{
						e=p-1;
						string node_fulltext="";
						node_fulltext.assign(f,e);
						node_fulltext=trimLeft(node_fulltext);
						mail_node* node = new mail_node;
						node->Mail=Mail;
						char* end;
						if((end = node->nodeload(node_fulltext.c_str()))==NULL)
						{
							delete node;
							return NULL;
						}
						mail_nodes.push_back(node);
					}
				}
				p=pEnd+1;
			}
			pEnd++;
		}
		bodyEnd=pEnd;
		content.assign(bodyBeg,bodyEnd);
		return pEnd;
	}
	//------------------------------------------------------------
	return pEnd;
}


string& mail_node::getUncodeContent()
{
	if(content_type==text)
	{
		if(code==Base64)
		{
			unBase64(getContent(),uncodeContent);
			if(tag==html)
			{
				uncodeContent=convertHtml(uncodeContent);
			}
			return uncodeContent;
		}
		else if(code==qp)
		{
			DecodeQuoted(getContent(),uncodeContent,getContent().size());
			if(tag==html)
			{
				uncodeContent=convertHtml(uncodeContent);
			}
			return uncodeContent;
		}
		else 
		{
			uncodeContent=content;
			if(tag==html)
			{
				uncodeContent=convertHtml(uncodeContent);
			}
			return uncodeContent;
		}		
	}
	else
		return uncodeContent;
}


void mail_node::setMail(mail* Mail)
{
	this->Mail=Mail;
}


//--------------------------------
//mail load
void mail::load(const char* str)
{
	mail_node* node = new mail_node;
	setMail(this);	
	//------------------------------------------------
	//提取发件人,收件人,主题
	char* p=(char*)str;
	char* pEnd=p;
	string lowtemp="",temp="";                        //临时存储用
	
	while(*(pEnd)!=NULL)
	{//
		if(*pEnd=='\n')
		{
			temp.assign(p,pEnd);
			temp=trimLeft(temp);
			lowtemp=temp;
			if(!temp.empty())
			{
				for(int i=0; i<temp.size(); i++)
					{lowtemp[i]=char(tolower(lowtemp[i]));}                   //转成小写

				string::size_type pos=0;
				if(lowtemp.compare(0,5,"from:")==0)
				{from.assign(temp,pos+5,temp.size());pos=0;}
				if(lowtemp.compare(0,3,"to:")==0)
				{to.assign(temp,pos+3,temp.size());pos=0;}
				if(lowtemp.compare(0,8,"subject:")==0)
				{subject.assign(temp,pos+8,temp.size());pos=0;}
				temp="";
				lowtemp=temp;
			}
			else
				break;
			p=pEnd+1;
		}
		pEnd++;
	}
	//-------------------------------------------------------------
	bodyBeg=++p;
	char* end;
	if((end = node->nodeload(str))==NULL)
	{
		delete node;
	}	
	else
	{
		bodyEnd=end;
		content.assign(bodyBeg,bodyEnd);
		mail_nodes.push_back(node);
	}
}

string& mail::getfile(const char* str)
{
	ifstream ifile(str);
	if(!ifile)
	{
		cerr<<"file can not be open!";
		return fulltext;
	}
	string temp="";
	while(!ifile.eof())
	{
		getline(ifile,temp);
		fulltext+=temp;
		fulltext+="\n";
	}
	return fulltext;
}

//程序处理中的辅助函数

string& trimLeft(string& str)
{//去掉空格和tab
	char* p=(char*)str.c_str();
	int i=0;
	while(p)
	{
		if(*p==' '||*p=='	')
		{
			p++;
			i++;
		}
		else
			break;
	}
	str.assign(str,i,str.size()-i);
	return str;
}

string trimRight(string& str)
{
	char* p=(char*)(str.end()-1);
	int i=0;
	while(p)
	{
		if(*p==' '||*p=='	'||*p=='\n')
		{
			p--;
			i++;
		}
		else
			break;
	}
	str.assign(str,0,str.size()-i);
	return str;
}

string& removeEnter(string& str)
{
	char* p=(char*)str.c_str();
	string::size_type pre=0, post=0;
	while((post=str.find_first_of("\n",pre))!=string::npos)
	{
		str.erase(p+post);
		pre=post;
	}
	return str;
}

void unBase64(string & content, string &uncoded)
{
	uncoded="";
	char t = NULL;
	char chuue[4] = {' ',' ',' ',' '};
	char chasc[3] = {' ',' ',' '};

	for(int k = 0; k < content.size()/4; k++)
	{
		for(int j = 0; j < 4; j++)
		{
			chuue[j] = *(content.c_str()+4*k+j);
		}
		int i,k=2;
		unsigned char t=NULL;
 
		for(i=0;i<4;i++)
		{
			if((*(chuue+i)>=65)&&(*(chuue+i)<=90)) *(chuue+i)-=65;
			else if((*(chuue+i)>=97)&&(*(chuue+i)<=122)) *(chuue+i)-=71;
			else if((*(chuue+i)>=48)&&(*(chuue+i)<=57)) *(chuue+i)+=4;
			else if(*(chuue+i)==43) *(chuue+i)=62;
			else if(*(chuue+i)==47) *(chuue+i)=63;
			else if(*(chuue+i)==61) *(chuue+i)=0;
		}

		for(i=0;i<3;i++)
		{
			*(chasc+i)=*(chuue+i)<<k;
			k+=2;
			t=*(chuue+i+1)>>(8-k);
			*(chasc+i)|=t;
		}
		uncoded.append(chasc, 3);
	}
}

void DecodeQuoted(string & content, string & uncoded, int size)
{
	char ch1;
	char ch2;
	char ch3;

	string temp2 = "";

	const char * p = content.c_str();

	int i = 0;                                                  //count

	while(i < size)
	{
		if(*p == ' ')
		{
			p++;
			i++;
			continue;
		}

		if(*p == '=')
		{		
			if(i < size)
			{
				ch1 = content[++i];
				ch2 = content[++i];
				ch3 = (ch1>'9'?(ch1-'A'+10):(ch1-'0'))*16+ (ch2>'9'?(ch2-'A'+10):(ch2-'0'));
				temp2 = ch3;
				uncoded = uncoded + temp2;
				i++;
				p+=3;
			}
			else
			{
				continue;
			}
		}
		else
		{
			temp2 = *p;
			uncoded = uncoded + temp2;
			p++;
			i++;
		}
	}
}

string& convertHtml(string& html)
{
	char* p=(char*)html.c_str();
	char* pre, *post;
	while(*p!=NULL)
	{
		if(*p=='<')
		{
			pre=p;
			p++;
		}
		else
			if(*p=='>')
		{
			post=p;
			html.erase(pre,post+1);
			post=pre;
			p=pre;
		}
		else
			p++;
	}
	return html;
}

string dealWithHead(string& head)
{
	string text=head;
	string::size_type pos=0;
	if((pos=head.find_last_of("?",head.size()))!=string::npos)
	{
		head.erase(pos,head.size()-pos);
		pos=head.find_last_of("?",head.size());
		head.erase(0,pos+1);
		unBase64(head,text);	
	}
	return text;
}




⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?