⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 client.cpp

📁 VC++语言中级教材,讲授网络编程中语言的运用技术
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	mailBoxName=string(".\\")+mailBoxName;
	hSearch = FindFirstFile(mailBoxName.c_str(), &FileData);
	if (hSearch == INVALID_HANDLE_VALUE||
		FileData.dwFileAttributes!=FILE_ATTRIBUTE_DIRECTORY)
	{
		CreateDirectory(mailBoxName.c_str(),NULL);
	}
	mailBoxName=username+"."+server;
	FindClose(hSearch);
}


void GivenUniqueFileName(const string& dir,
					const string& subject,
					string& name,
					string postfix)
{
	//if subject is NULL,
	WIN32_FIND_DATA FileData;
	HANDLE hSearch;
	char buffer[BUFFER_BLOCK_SIZE];
	int count=1;
	string curdir=".\\";
	string title=subject;
	RenameFileName(title);
	sprintf(buffer,"%s",postfix.c_str());
	while(1)
	{
		name=curdir+dir+"\\"+title+buffer;
		hSearch = FindFirstFile(name.c_str(), &FileData);
		if (hSearch == INVALID_HANDLE_VALUE)
			break;
		if(FileData.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)
		{
			hSearch = FindFirstFile(name.c_str(), &FileData);
			if (hSearch == INVALID_HANDLE_VALUE)
				break;
		}
		sprintf(buffer,"(%d)%s",count++,postfix.c_str());
	}
	FindClose(hSearch);
}

void ResolveOneLineWords(const char* text, string& buffer)
{
	char *tP;
	string src;
	if((tP=strstr(text,"?B?"))==NULL)
	{
		if(text[0]==' ')
			buffer=text+1;
		else
			buffer=text;
		return;
	}
	else
	{
		if(strstr(text,"=?")==NULL ||strstr(text,"?=")==NULL)
		{
			buffer=text;
			return;
		}
		tP+=3;
		while(*tP!='?')
			src+=*tP++;
		assert(src.length()%4==0);
		tP= new char[(src.length()/4+1)*3];
		DecodingBase64(src.c_str(),tP);
		std::string des;
		UTF8Decode(tP, des);
		buffer=tP;
		delete[] tP;
		tP=strstr(text,"?=");
		tP+=2;
		buffer+=tP;
	}
}

void UTF8Decode(const std::string& src, std::string& des)
{
	char str[BUFFER_BLOCK_SIZE];
	std::string::size_type pos=0;
	BOOL bBase64=FALSE;
	WCHAR wszUserName[BUFFER_BLOCK_SIZE/2];          // Unicode user name
//	int length=MultiByteToWideChar( CP_ACP, 0, addr.c_str(),addr.length()+1, wszUserName,   
//		sizeof(wszUserName)/sizeof(WCHAR));
	int length=MultiByteToWideChar( CP_ACP, 0, src.c_str(),src.length()+1, wszUserName,   
		sizeof(wszUserName)/sizeof(WCHAR));
	WideCharToMultiByte(CP_UTF8, 0, wszUserName, wcslen(wszUserName),
		str, BUFFER_BLOCK_SIZE,NULL,NULL);
	des=des;
}

int RetrieveAllEmail(SOCKET& sock,const string& mailboxname, BOOL bDel)
{
	int numOfMails;
	string content;
	string filename;
	int i;
	int retCode;
	vector<int> newMailID;
	vector<string> newMailUID;

	retCode=STAT(sock,numOfMails);
	DEAL_RETURN_CODE(retCode);

	retCode=GetAllNewMailsID(sock, mailboxname, newMailID, newMailUID);

	//RETR
	for(i=0; i<newMailID.size(); i++)
	{
		retCode=RETR(sock, newMailID[i], content);
		DEAL_RETURN_CODE(retCode);
		if(bDel)
		{
			retCode=DELE(sock,newMailID[i]);
			DEAL_RETURN_CODE(retCode);
		}
		WriteMailToFile(mailboxname, content,filename);
		PrintMail(mailboxname, filename);
		WriteDownloadMailUID(mailboxname,newMailUID[i]);
	}
//	retCode=RSET(sock);
//	DEAL_RETURN_CODE(retCode);
	retCode=QUIT(sock);	//leave transaction state, enter UPDATE state, all deleted files are removed
	DEAL_RETURN_CODE(retCode);
	return 0;
}

int STAT(SOCKET sock, int& numOfMails)
{
	char buffer[BUFFER_BLOCK_SIZE];
	int retCode;
	sprintf(buffer,"STAT\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
	DEAL_SOCK_ERROR(retCode,sock);
	buffer[retCode]='\0';
	cout<<buffer;
	DEAL_RETURN_CODE(buffer[0]);
	sscanf(buffer+3,"%d",&numOfMails);
	return 0;
}

int RETR(SOCKET sock, int mailID,string& content)
{
	char buffer[BUFFER_BLOCK_SIZE*10+1];
	char *tP;
	int retCode;
	int length;
	
	if(LIST(sock, mailID, length)!=0)
		return 1;

	sprintf(buffer,"RETR %d\r\n",mailID);
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE*10,0);
	DEAL_SOCK_ERROR(retCode,sock);
	buffer[retCode]='\0';
	cout<<buffer;
	DEAL_RETURN_CODE(buffer[0]);
	cout.flush();
	tP=strchr(buffer,int('\n'));
	tP++;
	content=tP;
	length-=content.length();
	while(length>0)
	{
		retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE*10,0);
		DEAL_SOCK_ERROR(retCode,sock);
		buffer[retCode]='\0';
		content+=buffer;
		length-=retCode;
	}
	return 0;
}

int DELE(SOCKET sock,int mailID)
{
	char buffer[BUFFER_BLOCK_SIZE+1];
	int retCode;
	sprintf(buffer,"DELE %d\r\n",mailID);
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
	DEAL_SOCK_ERROR(retCode,sock);
	buffer[retCode]='\0';
	cout<<buffer;
	DEAL_RETURN_CODE(buffer[0]);
	return 0;
}

int LIST(SOCKET sock,int mailID, int& length)
{
	char buffer[BUFFER_BLOCK_SIZE+1];
	int retCode;
	sprintf(buffer,"LIST %d\r\n",mailID);
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE*10,0);
	DEAL_SOCK_ERROR(retCode,sock);
	buffer[retCode]='\0';
	cout<<buffer;
	DEAL_RETURN_CODE(buffer[0]);
	sscanf(buffer+3,"%d%d",&mailID,&length);
	return 0;
}

//cancel all mail tags which maked as deleted
int RSET(SOCKET sock)
{
	char buffer[BUFFER_BLOCK_SIZE+1];
	int retCode;
	strcpy(buffer,"RSET\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
	DEAL_SOCK_ERROR(retCode,sock);
	buffer[retCode]='\0';
	cout<<buffer;
	DEAL_RETURN_CODE(buffer[0]);
	return 0;
}

int QUIT(SOCKET sock)
{
	char buffer[BUFFER_BLOCK_SIZE];
	int retCode;
	strcpy(buffer,"QUIT\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
	DEAL_SOCK_ERROR(retCode,sock);
	buffer[retCode]='\0';
	cout<<buffer;
	DEAL_RETURN_CODE(buffer[0]);
	return 0;
}

int GetAllNewMailsID( SOCKET sock,
					 const string& mailboxname, 
					 vector<int>& newMailID,
					 vector<string>& newMailUID)
{
	char buffer[BUFFER_BLOCK_SIZE];
	string str,substr;
	int retCode;
	string::size_type pos,lastpos;
	vector<string> UIDList;
	int i;

	newMailID.clear();
	newMailUID.clear();
	strcpy(buffer,"UIDL\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	while(1)
	{
		retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
		DEAL_SOCK_ERROR(retCode,sock);
		buffer[retCode]='\0';
		cout<<buffer;
		cout.flush();
		str+=buffer;
		DEAL_RETURN_CODE(str[0]);
		if(strcmp(str.c_str()+str.length()-5,"\r\n.\r\n")==0)
			break;
	}
	lastpos=0;
	pos=0;
	//omit +OK\r\n
	pos=str.find("\r\n",pos);
	pos+=2;
	lastpos=pos;
	while((pos=str.find("\r\n",pos))!=string::npos)
	{
		substr=str.substr(lastpos,pos-lastpos);
		pos+=2;
		lastpos=pos;
		sscanf(substr.c_str(),"%d%s",&retCode,buffer);
		newMailID.push_back(retCode);
		newMailUID.push_back(buffer);
	}
	//pop the dot tag
	newMailID.pop_back();
	newMailUID.pop_back();

	GetMailsUIDList(mailboxname,UIDList);
	for(i=0; i<UIDList.size(); i++)
	{
		vector<string>::iterator ite; 
		if((ite=std::find(newMailUID.begin(),newMailUID.end(),UIDList[i]))!=newMailUID.end())
		{
			newMailID.erase(newMailID.begin()+(ite-newMailUID.begin()));
			newMailUID.erase(ite);
		}
	}
	cout<<"New Mail Num: "<<newMailID.size()<<endl;
	return 0;
}

//write to file
void WriteMailToFile(const string& mailboxname, const string& content, string& filename)
{
	string title;
	string str;
	string::size_type pos=0,endPos=0;
	if((pos=content.find("\r\n\r\n",pos))!=string::npos)
	{
		str=content.substr(0,pos);
		pos=0;
		if((pos=str.find("Subject:",pos))!=string::npos)
		{
			if(pos==0 || str[pos-1]=='\n')
			{
				endPos=pos;
				if((endPos=str.find('\r',endPos))!=string::npos)
				{
					title=str.substr(pos+8,endPos-pos-8);
				}
			}
		}
	}
	if(title.length()==0)
		title="1";
	ResolveOneLineWords(title.c_str(),str);
	title=str;
	GivenUniqueFileName(mailboxname,title,filename);
	ofstream file(filename.c_str(),ios::binary);
	assert(!file.fail());
	if(file.fail())
	{
		GivenUniqueFileName(mailboxname,"1",filename);
		file.open(filename.c_str(),ios::binary);
	}
	file.write(content.c_str(),content.length());
	file.close();
	filename=filename.substr(mailboxname.length()+3,filename.length()-3-mailboxname.length());
}

void RenameFileName(string& filename)
{
	char illegalChar[]="\\/:*?\"<>|";
	int i=0;
	string::size_type pos=0;
	while((pos=filename.find_first_of(illegalChar, pos))!=string::npos)
	{
		filename.replace(pos,1,"_");
	}
}

void PrintMail(const string& mailboxname, const string& filename)
{
	string sender;
	string date;
	string from,to,cc;
	string subject;
	string bodytext;
	string bodyhtml;
	map<string, string> attachmentNames;
	int iResult;
	iResult=ResolveMail(mailboxname,filename,sender,date,from,to,cc,subject,bodytext,bodyhtml,attachmentNames);
	cout<<"MailBox: "<<mailboxname.c_str()<<endl;
	cout<<"Subject:"<<subject.c_str()<<endl;
	cout<<"From:"<<from.c_str()<<endl;
	if(to.length())
		cout<<"From:"<<to.c_str()<<endl;
	if(cc.length())
		cout<<"Cc:"<<cc.c_str()<<endl;
	if(bodytext.length())
		cout<<"Mail content lists as follows:"<<endl<<bodytext.c_str()<<endl;
	if(bodyhtml.length())
		cout<<"Mail's html content lists as follows:"<<endl<<bodyhtml.c_str()<<endl;
	if(attachmentNames.size())
	{
		cout<<"Mail's attachments file names list as follows:"<<endl;
		for(map<string, string>::iterator pos=attachmentNames.begin() ; 
				pos!=attachmentNames.end() ; pos++)
			cout<<(*pos).first.c_str()<<endl;
	}
}

//contentType 0: only text/plain
//            1: only text/html
//            2: only attachment
//            3: mixed boundary majorSplitTag
int DataHead(ifstream& file,
			 string& senderAddr,
			 string& date,
			 string& from, //for most mail server, it only support youself address
			 string& to,
			 string& cc,
			 string & subject,
			 string & tagStr, //majorSplitTag or filename
			 int& contentType,	
			 BOOL& bBase64) //this parameters make effect only when contentType is 0,1,2
{
	string str;
	char buffer[BUFFER_BLOCK_SIZE];
	string::size_type pos=0;
	string command,result;
	BOOL bContextTypeState=FALSE;

	senderAddr="";
	from="";
	to="";
	cc="";
	subject="";
	tagStr="";
	//data head
	while(1)
	{
		file.getline(buffer,BUFFER_BLOCK_SIZE);
		str=buffer;
		if(str.length()==0)
			break;
		pos=0;
		if((pos=str.find(':',pos))!=string::npos)
		{
			bContextTypeState=FALSE;
			command=str.substr(0,pos);
			str=str.substr(pos+1,str.length()); //space
			if(command=="From")
				ResolveOneLineWords(str.c_str(),from);
			else if(command=="To")
				ResolveOneLineWords(str.c_str(),to);
			else if(command=="Subject")
				ResolveOneLineWords(str.c_str(),subject);
			else if(command=="Cc")
				ResolveOneLineWords(str.c_str(),cc);
			else if(command=="Date")
				date=str;
			else if(command=="Reply-To")
				ResolveOneLineWords(str.c_str(),senderAddr);
			else if(command=="Content-Type")
			{
				//here we deal three types
				//text/plain, multipart/alternative, multipart/mixed
				pos=0;
				if((pos=str.find("text/plain",pos))!=string::npos)
					contentType=0;
				else if((pos=str.find("text/html",pos))!=string::npos)
					contentType=1;
				else
					contentType=3;
				bContextTypeState=TRUE;
			}
			else if(command=="Content-Transfer-Encoding")
			{
				if(strstr(str.c_str(),"base64")!=NULL)
					bBase64=TRUE;
				else
					bBase64=FALSE;
			}
		}
		else
		{
			if(bContextTypeState)
			{
				pos=0;
				if(str.find("filename=",pos)!=string::npos)
				{
					if(str[0]=='\t')
					{
						pos=str.find("\"",pos);
						tagStr=str.substr(pos+1,str.length()-1);
						contentType=2; //only attachment
					}
				}
				else if(contentType==3)
				{
					if(strstr(str.c_str(),"boundary=")!=NULL && str[0]=='\t')
					{
						pos=0;
						pos=str.find('\"',pos);
						str=str.substr(pos+1,str.length());
						pos=0;
						pos=str.find('\"',pos);
						tagStr=str.substr(0,pos);
						tagStr=string("--") + tagStr;
					}
				}
			}
		}
	}
	return 0;
}

//A simple token analysis function. Using automatic finite machine.
BOOL ResolveMail(const string& mailboxname,
				const string& filename,
				 string& senderAddr,
				 string& date,
				 string& from, //for most mail server, it only support youself address
				 string& to,
				 string& cc,
				 string & subject,
				 string & bodytext,
				 string & bodyhtml,
				 map<string, string> & attachmentNames)
{
	string str=".\\";
	ifstream file;
	int contentType;
	string tagStr;
	BOOL bBase64;
	ofstream downloadFile;

	str=str+mailboxname+"\\"+filename;
	file.open(str.c_str());
	if(file.fail())
	{
		cout<<"Cannot open the specified mail."<<endl;
		return FALSE;
	}
	DataHead(file,senderAddr,date, from,to,cc,subject,tagStr,contentType,bBase64);

	//if content==2 , it standards the filename else majorSplitTag
	DataBody(file,mailboxname, bBase64, contentType, tagStr, bodytext, bodyhtml, 

⌨️ 快捷键说明

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