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

📄 client.cpp

📁 VC++语言中级教材,讲授网络编程中语言的运用技术
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// Client.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "Client.h"
#include <winsock2.h>
#include <afxsock.h>
#include <assert.H>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <string>
#include <time.h>
#include <algorithm>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// The one and only application object

CWinApp theApp;
using namespace std;

#define BUFFER_BLOCK_SIZE 4096
#define DEAL_SOCK_ERROR(retCode,sock)	if((retCode)==SOCKET_ERROR || (retCode)==0)\
										{										\
											cout<<"Sock error: "<<GetLastError()<<endl;\
											closesocket(sock);					\
											return -1;							\
										}
#define DEAL_RETURN_CODE(c)	if((c)!='+' && (c)!=0) { return 1; }

//Command line scan
int ClientCommandResolve();
void InputLine(string & str);

//Local mailbox management
void MailBoxName(const string& username, const string& server, string& mailBoxName);
void GivenUniqueFileName(const string& dir,const string& subject,	string& name,
					string postfix=".eml");

//Analysisist of mail struct
void DecodingBase64(const char* src, char* des);
void DecodingBase64Adv(const char* src, int length, char* des);
UCHAR SixBitDecodeIndex(char a);
BOOL FilterHead(ifstream& file, BOOL& bBase64,int& contentType,string& tagStr,
				string majorSplitPart="");
BOOL SimpleMail(ifstream& file, BOOL bBase64, string& text);
void SubResolve(ifstream& file,BOOL bBase64, string& splitTag,string& text);
void SubResolveAdv(ifstream& file,BOOL bBase64, string& splitTag,char** result, int& length);
void WriteAttachmentToFile(const string& dir,
						   const string& filename,
						   const char* content,
						   int length,
						   string& newfilename);

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

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

void DataBody(  ifstream& file,
			    const string& mailbox,
				BOOL bBase64,
				int contentType,
				string& tagStr,	//if content==2 , it standards the filename else majorSplitTag
				string& bodytext,
				string& bodytexthtml,
				map<string, string> & attachmentNames);

//POP3 Client Agent Application Functions
int ReceiveMail(const string& serverHostName,	 
			 UINT serverPort, 
			 const string& username, 
			 const string& pass,
			 const string& mailboxname);
int RetrieveAllEmail(SOCKET& sock, const string& mailboxname, BOOL bDel);


//Login
int Login(const string& proxyServerName, u_int proxyPort,
		  const string& proxyUser, const string& proxyPass,
		  const string& serverHostName, UINT serverPort, 
		  const string& username, const string& pass,
		  SOCKET& sock, string& mailboxname);

//Command
int STAT(SOCKET sock,int& numOfMails);
int RETR(SOCKET sock,int mailID, string& content);
int DELE(SOCKET sock,int mailID);
int LIST(SOCKET sock,int mailID, int& length);
int RSET(SOCKET sock);
int QUIT(SOCKET sock);



//mail's UID related
int GetAllNewMailsID(SOCKET sock, const string& mailboxname, vector<int>& newMailID, vector<string>& newMailUID);
void WriteMailToFile(const string& mailboxname, const string& content, string& filename);
void PrintMail(const string& mailboxname, const string& filename);
void RenameFileName(string& filename);
void UTF8Decode(const std::string& src, std::string& des);
void GetMailsUIDList(const string& mailboxname, vector<string>& uniqueIDArray);
void WriteDownloadMailUID(const string& mailboxname, const string& UID);

//Socks5 proxy related
u_long ConvertHostnameToLongHostAddress(const char * destAddress);
int Socks5StartIPv4(const string& proxyServerHostName,
				u_int proxyServerPort,
				const string& username, 
				const string& pass,
				u_long destAddress,
				u_int destPort,
				SOCKET& sock);
BOOL ReceiveMessage(SOCKET sock, char* buffer, int bufferLen);

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	ClientCommandResolve();
	return 0;
}

void InputLine(string & str)
{
	char ch;
	str="";
	while((ch = getchar())!= '\n')
		str+=ch;
}

int ClientCommandResolve()
{
	string serverHostName;
	UINT serverPort=0;
	string senderAddr;
	vector<string> recptAddrs;
	string username;
	string pass;
	string date;
	vector<string> from;
	vector<string> to;
	vector<string> cc;
	vector<string> bcc;
	string subject;
	string bodytext;
	string bodyhtml;
	map<string, string>attachments;
	string mailboxname;

	string proxyServerName;
	u_int  proxyPort;
	string proxyUser;
	string proxyPass;

	serverPort=110;

//	serverHostName="";
//	username="";
//	pass="";
//	proxyServerName="10.214.50.251";
//	proxyPort=1080;
//	proxyUser="";
//	proxyPass="";

	char paraCommand[BUFFER_BLOCK_SIZE];
	int  pos=0;
	int iResult;
	string str;

	WSADATA wsaData;
	if(WSAStartup(MAKEWORD( 2, 2 ), &wsaData)!=0)
	{
		cerr<<"socket init error"<<endl;
		return -1;
	}
	
	while(1)
	{
		//POP3 Server host name
		if(serverHostName.length()==0)	//for testing
		while(1)
		{
			cout<<"POP3 Server Host Name:";
			cout.flush();
			InputLine(str);
			iResult=sscanf(str.c_str(),"%s",paraCommand);
			if(iResult==EOF)
			{
				cout<<"Input server host name"<<endl;
				continue;
			}
			serverHostName=paraCommand;
			break;
		}
		
		//POP3 Server Port
		if(serverPort==0)	//for testing
		while(1)
		{
			cout<<"POP3 Server Port:";
			cout.flush();
			InputLine(str);
			iResult=sscanf(str.c_str(),"%s",paraCommand);
			if(iResult!=EOF)
			{
				serverPort=atoi(paraCommand);
				if(serverPort<=0)
				{
					cout<<"Invalid port."<<endl;
					continue;
				}
			}
			break;
		}

		//USER NAME
		if(username.length()==0)	//for testing
		while(1)
		{
			cout<<"USER NAME:";
			cout.flush();
			InputLine(str);
			iResult=sscanf(str.c_str(),"%s",paraCommand);
			if(iResult==EOF)
			{
				cout<<"Input user name for authentication."<<endl;
				continue;
			}
			username=paraCommand;
			break;
		}

		//PASS
		if(pass.length()==0)	//for testing
		while(1)
		{
			cout<<"PASSWORD:";
			cout.flush();
			InputLine(str);
			iResult=sscanf(str.c_str(),"%s",paraCommand);
			if(iResult==EOF)
			{
				cout<<"Input password."<<endl;
				continue;
			}
			pass=paraCommand;
			break;
		}
		
		//Proxy
		if(proxyServerName.length()==0)	//for testing
		{
			cout<<"Proxy?";
			cout.flush();
			InputLine(str);
			if(str=="y" || str=="Y")
			{
				cout<<"Proxy Server Addr:";
				InputLine(proxyServerName);
				cout<<"Proxy Server Port:";
				InputLine(str);
				sscanf(str.c_str(),"%d",&proxyPort);
				cout<<"Proxy Server Username:";
				InputLine(proxyUser);
				cout<<"Proxy Server Pass:";
				InputLine(proxyPass);
			}
		}

		cout<<"Receiving Mail....."<<endl;
		
		//define mail box
		SOCKET sock;
		int retCode;
		retCode=Login(proxyServerName, proxyPort, proxyUser, proxyPass, serverHostName,serverPort,username,pass,sock,mailboxname);
		DEAL_RETURN_CODE(retCode);
		retCode=RetrieveAllEmail(sock,mailboxname,FALSE);
		DEAL_RETURN_CODE(retCode);
		
		cout<<"QUIT?";
		cout.flush();
		InputLine(str);
		if(str=="y"||str=="Y")
		{
			cout<<"Bye!"<<endl;
			return -1;
		}
	}
	return 0;
}

//write all mail's UID into mailboxname.log file
void GetMailsUIDList(const string& mailboxname, 
					 vector<string>& uniqueIDArray)
{
	char buffer[BUFFER_BLOCK_SIZE];
	string filename;
	ifstream file;

	uniqueIDArray.clear();
	filename= string(".\\")+mailboxname+"\\UID.log";
	file.open(filename.c_str());
	if(file.fail())
	{
		file.close();
		ofstream nfile(filename.c_str());
		assert(!nfile.fail());
		nfile.close();
		return;
	}
	while(!file.eof())
	{
		file>>buffer;
		uniqueIDArray.push_back(buffer);
	}
	file.close();
}

void WriteDownloadMailUID(const string& mailboxname, const string& UID)
{
	string filename;
	ofstream file;

	filename= ".\\"+mailboxname+"\\UID.log";
	file.open(filename.c_str(),(ios::app|ios::out)&(~ios::trunc));
	if(file.fail())
	{
		file.close();
		file.open(filename.c_str());
		if(file.fail())
		{
			cerr<<"Fail opening file "<<filename.c_str()<<endl;
			return;
		}
		file<<UID.c_str()<<endl;
		return;
	}
	file.seekp(0,ios::end);
	file<<UID.c_str()<<endl;
	file.close();
}

int ReceiveMail(const string& serverHostName,	 
			 UINT serverPort, 
			 const string& username, 
			 const string& pass,
			 const string& mailboxname)
{
	sockaddr_in serverAddr;
	int retCode;
	SOCKET sock;
	hostent * host;
	char buffer[BUFFER_BLOCK_SIZE];

	host=gethostbyname(serverHostName.c_str());
	if(host==NULL)
	{
		cout<<"Cann't resolve this host name: "<<GetLastError()<<endl;
		return -1;
	}

	sock=socket(AF_INET, SOCK_STREAM,0);
	serverAddr.sin_addr=*(struct in_addr*)host->h_addr;
	serverAddr.sin_family=AF_INET;
	serverAddr.sin_port=htons(serverPort);
	cout<<"Connecting to "<<inet_ntoa(serverAddr.sin_addr)<<endl;
	cout.flush();
	if(connect(sock,(const sockaddr*)&serverAddr,sizeof(sockaddr))==SOCKET_ERROR)
	{
		cout<<"Cannot connect to Server: "<<serverHostName.c_str()<<endl;
		cout.flush();
		closesocket(sock);
		return -1;
	}
	//1. welcome words
	retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
	DEAL_SOCK_ERROR(retCode,sock);
	buffer[retCode]='\0';
	cout<<buffer;
	DEAL_RETURN_CODE(buffer[0]);

	//2. USER NAME
	sprintf(buffer,"USER %s\r\n",username.c_str());
	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]);

	//2. password
	sprintf(buffer,"PASS %s\r\n",username.c_str());
	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]);

	RetrieveAllEmail(sock,mailboxname,FALSE);

	
	//2. QUIT
	if(QUIT(sock)==-1)
		return -1;
	closesocket(sock);
	return 0;
}

int Login(const string& proxyServerName,
			u_int proxyPort,
			const string& proxyUser,
			const string& proxyPass,
			const string& serverHostName,	 
			UINT serverPort, 
			const string& username, 
			const string& pass,
			SOCKET& sock,
			string& mailboxname)
{
	sockaddr_in serverAddr;
	int retCode;
	hostent * host;
	char buffer[BUFFER_BLOCK_SIZE];

	//create an user mailbox
	MailBoxName(username,serverHostName,mailboxname);

	if(proxyServerName.length())
	{
		u_long addr=ConvertHostnameToLongHostAddress(serverHostName.c_str());
		if(Socks5StartIPv4(proxyServerName,proxyPort,proxyUser,proxyPass,addr,serverPort,sock)!=0)
			return 1;
	}
	else
	{
		host=gethostbyname(serverHostName.c_str());
		if(host==NULL)
		{
			cout<<"Cann't resolve this host name: "<<GetLastError()<<endl;
			return -1;
		}

		sock=socket(AF_INET, SOCK_STREAM,0);
		serverAddr.sin_addr=*(struct in_addr*)host->h_addr;
		serverAddr.sin_family=AF_INET;
		serverAddr.sin_port=htons(serverPort);
		cout<<"Connecting to "<<inet_ntoa(serverAddr.sin_addr)<<endl;
		cout.flush();
		if(connect(sock,(const sockaddr*)&serverAddr,sizeof(sockaddr))==SOCKET_ERROR)
		{
			cout<<"Cannot connect to Server: "<<serverHostName.c_str()<<endl;
			cout.flush();
			closesocket(sock);
			return -1;
		}
	}
	
	//1. welcome words
	retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
	DEAL_SOCK_ERROR(retCode,sock);
	buffer[retCode]='\0';
	cout<<buffer;
	DEAL_RETURN_CODE(buffer[0]);

	//2. USER NAME
	sprintf(buffer,"USER %s\r\n",username.c_str());
	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]);

	//2. Password
	sprintf(buffer,"PASS %s\r\n",pass.c_str());
	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;
}

void MailBoxName(const string& username,
				 const string& server,
				 string& mailBoxName)
{
	WIN32_FIND_DATA FileData;
	HANDLE hSearch;
	mailBoxName=username+"."+server;

⌨️ 快捷键说明

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