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

📄 client.cpp

📁 smtp c语言下的实现 smtp c语言下的实现smtp c语言下的实现
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			//unfinished. Here should save the transaction into file.
		}
		
		cout<<"QUIT?";
		cout.flush();
		InputLine(str);
		if(str=="y"||str=="Y")
		{
			cout<<"Bye!"<<endl;
			return -1;
		}
		recptAddrs.clear();
		from.clear();
		to.clear();
		cc.clear();
		bcc.clear();
		subject="";
		bodytext="";
		bodytexthtml="";
		attachments.clear();
	}
	return 0;
}

//for multiple response code
int GetResponseCode(SOCKET sock,int correctCode,string& str)
{
	int retCode;
	char buffer[BUFFER_BLOCK_SIZE+1];
	str="";
	while(1)
	{
		retCode=recv(sock,buffer,BUFFER_BLOCK_SIZE,0);
		if(retCode==SOCKET_ERROR || retCode==0)
			return -1;
		buffer[retCode]='\0';
		cout<<buffer;
		cout.flush();
		str+=buffer;
		if(ResponsedCodeFinished(str))
		{
			if(atoi(str.c_str())==correctCode)
				return 0;
			else
				return 1;
		}
	}
}

BOOL ResponsedCodeFinished(const string& str)
{
	if(str[str.length()-2]!='\r' || str[str.length()-1]!='\n')
		return FALSE;
	if(str[3]!='-')
		return TRUE;
	char code[4];
	int beginCode=atoi(str.c_str());
	itoa(beginCode,code,10);
	std::string::size_type pos=str.rfind(code,str.length()-1);
	return str[pos+3]==' ';
}


int SendMail(const string& proxyServerName,
			 UINT proxyServerPort,
			 const string& proxyUser,
			 const string& proxyPass,
			 const string& serverHostName,	 
			 UINT serverPort, 
			 const string& username, 
			 const string pass,
			 const string& senderAddr,
			 const vector<string >& recptAddress,
			 const vector<string >& from, //for most mail server, it only support youself address
			 const vector<string >& to,
			 const vector<string >& cc,
			 const vector<string >& bcc,
			 const string & subject,
			 const string & bodytext,
			 const string & bodyhtml,
			 const vector<string >&attachments)
{
	sockaddr_in serverAddr;
	SOCKET sock;
	hostent * host;
	char buffer[BUFFER_BLOCK_SIZE];
	int i;
	BOOL bHtml,bAttachment;
	string str;
	if(bodyhtml.length()==0)
		bHtml=FALSE;
	else
		bHtml=TRUE;
	if(attachments.size()==0)
		bAttachment=FALSE;
	else
		bAttachment=TRUE;

	if(proxyServerName.length()!=0)//using socks5 proxy
	{
		u_long addr=ConvertHostnameToLongHostAddress(serverHostName.c_str());
		if(Socks5StartIPv4(proxyServerName,proxyServerPort,proxyUser,proxyPass,addr,serverPort,sock)!=0)
		{
			cerr<<"Proxy server error!"<<endl;
		}
	}
	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
	DEAL_RETURN_CODE(GetResponseCode(sock,220,str));

	//2. HELO.
	//We omit HELO, because most Email Server needs authentication.

	//3. EHLO
	sprintf(buffer,"EHLO %s\r\n",senderAddr.c_str());
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	DEAL_RETURN_CODE(GetResponseCode(sock,250,str));

	//4. AUTH LOGIN. 
	//Most authentication takes AUTH LOGIN and AUTH PLAIN. Here we take AUTH LOGIN by default.
	sprintf(buffer,"AUTH LOGIN\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	DEAL_RETURN_CODE(GetResponseCode(sock,334,str));
	
	//2. USER NAME
	//User name is coded by base64.
	EncodingBase64(username.c_str(),buffer);
	strcat(buffer,"\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	DEAL_RETURN_CODE(GetResponseCode(sock,334,str));

	//2. password coded by base64
	EncodingBase64(pass.c_str(),buffer);
	strcat(buffer,"\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	DEAL_RETURN_CODE(GetResponseCode(sock,235,str));

	//2. MAIL FROM
	sprintf(buffer,"MAIL FROM:<%s>\r\n",senderAddr.c_str());
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	DEAL_RETURN_CODE(GetResponseCode(sock,250,str));

	//2. RCPT
	for(i=0;i<recptAddress.size();i++)
	{
		sprintf(buffer,"RCPT TO: <%s>\r\n",recptAddress[i].c_str());
		cout<<buffer;
		send(sock,buffer,strlen(buffer),0);
		DEAL_RETURN_CODE(GetResponseCode(sock,250,str));
	}

	//2. DATA
	sprintf(buffer,"DATA\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	DEAL_RETURN_CODE(GetResponseCode(sock,354,str));
	
	string majorSplitTag;

	//DATA head
	DataHead(from[0],to,cc,bcc,subject,bodytext,bodyhtml,bHtml,bAttachment,majorSplitTag,str);
	cout<<str.c_str();
	cout.flush();
	//send(sock,str.c_str(),str.length(),0);
	SendMessage(sock,str.c_str(),str.length());

	
	//DATA body
	DataBody(bHtml,bAttachment,majorSplitTag,bodytext,bodyhtml,attachments,str);
	cout<<str.c_str();
	cout.flush();
//	send(sock,str.c_str(),str.length(),0);
	SendMessage(sock,str.c_str(),str.length());
	DEAL_RETURN_CODE(GetResponseCode(sock,250,str));
	
	//2. QUIT
	strcpy(buffer,"QUIT\r\n");
	cout<<buffer;
	send(sock,buffer,strlen(buffer),0);
	DEAL_RETURN_CODE(GetResponseCode(sock,221,str));

	closesocket(sock);
	return 0;
}

//we donnot want to allocate another buffer for src, so we write this encoding 
void EncodingBase64(const char* src, char* des)
{
	assert(src&&des);
	char sixbit_encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	while(*src!=NULL)
	{
		*des++=sixbit_encoding[(UCHAR)*src++>>2]; //6
		if(*src==NULL)
		{
			*des++=sixbit_encoding[(*(src-1)&0x3)<<4];//2+4
			*des++='=';
			*des++='=';
			break;
		}
		else
		{
			*des++=sixbit_encoding[(*(src-1)&0x3)<<4 | UCHAR(*src)>>4];//2+4
			src++;
		}
		if(*src==NULL)
		{
			*des++=sixbit_encoding[(*(src-1)&0xF)<<2];//4+2
			*des++='=';
		}
		else
		{
			*des++=sixbit_encoding[(*(src-1)&0xF)<<2 | UCHAR(*src)>>6];//4+2
			*des++=sixbit_encoding[*src&0x3F];//6
			src++;
		}
	}
	*des=NULL;
}



void EncodingBase64Adv(const char* src, int length,char* des)
{
	int i=0;
	char sixbit_encoding[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	assert(des);
	while(i<length)
	{
		*des++=sixbit_encoding[(UCHAR)src[i++]>>2]; //6
		if(i==length)
		{
			*des++=sixbit_encoding[(src[i-1]&0x3)<<4];//2+4
			*des++='=';
			*des++='=';
			break;
		}
		else
		{
			*des++=sixbit_encoding[(src[i-1]&0x3)<<4 | UCHAR(src[i])>>4];//2+4
			i++;
		}
		if(i==length)
		{
			*des++=sixbit_encoding[(src[i-1]&0xF)<<2];//4+2
			*des++='=';
		}
		else
		{
			*des++=sixbit_encoding[(src[i-1]&0xF)<<2 | UCHAR(src[i])>>6];//4+2
			*des++=sixbit_encoding[src[i]&0x3F];//6
			i++;
		}
	}
	*des=NULL;
}

//For high efficient, pls rewrite it using looking-up table
UCHAR SixBitDecodeIndex(char a)
{
	if(a>='A'&&a<='Z')
		return a-'A';
	else if(a>='a'&&a<='z')
		return 26+a-'a';
	else if(a>='0'&&a<='9')
		return 52+a-'0';
	else if(a=='+')
		return 62;
	else if(a=='/')
		return 63;
	else if(a=='=')
		return 0;
	else
	{
		assert(FALSE);
		return -1;
	}
}

void DecodingBase64(const char* src, char* des)
{
	assert(src&&des);
	assert(strlen(src)%4==0);
	while(*src!=NULL)
	{
		*des++=SixBitDecodeIndex(*src)<<2 | SixBitDecodeIndex(*(src+1))>>4;	//6+2
		src++;
		*des++=SixBitDecodeIndex(*src)<<4 | SixBitDecodeIndex(*(src+1))>>2;//4+4
		src++;
		*des++=SixBitDecodeIndex(*src)<<6 | SixBitDecodeIndex(*(src+1));	//2+6
		src+=2;
	}
	*des=NULL;
}

void DecodingBase64Adv(const char* src, int length, char* des)
{
	int i=0;
	assert(des);
	assert(length%4==0);
	while(i<length)
	{
		*des++=SixBitDecodeIndex(src[i])<<2 | SixBitDecodeIndex(src[i+1])>>4;	//6+2
		i++;
		*des++=SixBitDecodeIndex(src[i])<<4 | SixBitDecodeIndex(src[i+1])>>2;//4+4
		i++;
		*des++=SixBitDecodeIndex(src[i])<<6 | SixBitDecodeIndex(src[i+1]);	//2+6
		i+=2;
	}
	*des=NULL;
}

void Date(string& buffer)
{
	struct tm *newtime;
	time_t aclock;
	struct _timeb tstruct;

	char str[BUFFER_BLOCK_SIZE];
	time( &aclock );
	newtime = localtime( &aclock );
	strftime( str, BUFFER_BLOCK_SIZE,"%a, %d %b %Y %X ", newtime);
	buffer=string("Date:")+str;
	
    _ftime( &tstruct );
	if(tstruct.timezone<0)
		sprintf(str,"+%.2d%.2d\r\n",-tstruct.timezone/60,-tstruct.timezone%60);
	else
		sprintf(str,"-%.2d%.2d\r\n",tstruct.timezone/60,tstruct.timezone%60);
	buffer+=str;
}


void MimeVersion(string & buffer)
{
	buffer="Mime-Version: 1.0\r\n";
}
void Subject(const string& title,string & buffer)
{
	char str[BUFFER_BLOCK_SIZE];
	string::size_type pos=0;
	BOOL bBase64=FALSE;
	WCHAR wszUserName[BUFFER_BLOCK_SIZE/2];          // Unicode user name
	int i;
	int length=MultiByteToWideChar( CP_ACP, 0, title.c_str(),title.length()+1, wszUserName,   
		sizeof(wszUserName)/sizeof(WCHAR));
	if(length==0 && title.length()!=0)
		bBase64=TRUE;
	for(i=0; i<length; i++)
	{
		if(wszUserName[i]  >= 256)
		{
			bBase64=TRUE;
			break;
		}
	}
	if(bBase64)
	{
		EncodingBase64(title.c_str(),str);
		buffer=string("Subject: ") + "=?gb2312?B?" + str + "?=\r\n";
	}
	else
	{
		buffer="Subject: "+title+"\r\n";
	}
}

void HeadTextTemple(const string& command,const string& addr,string & buffer, BOOL bPrintCommond)
{
	char str[BUFFER_BLOCK_SIZE],str2[BUFFER_BLOCK_SIZE];
	string::size_type pos=0;
	BOOL bBase64=FALSE;
	WCHAR wszUserName[BUFFER_BLOCK_SIZE/2];          // Unicode user name
	int i;
	int length=MultiByteToWideChar( CP_ACP, 0, addr.c_str(),addr.length()+1, wszUserName,   
		sizeof(wszUserName)/sizeof(WCHAR));

	buffer="";
	if(length==0)
		bBase64=TRUE;
	for(i=0; i<length; i++)
	{
		if(wszUserName[i]  >= 256)
		{
			bBase64=TRUE;
			break;
		}
	}
	if(bBase64)
	{
		if((pos=addr.find("<",pos))==string::npos)
		{
			if((pos=addr.find(" ",pos))==string::npos)
				return;
		}
		strcpy(str,addr.c_str());
		str[pos]=NULL;
		EncodingBase64(str,str2);
		if(bPrintCommond)
			buffer= command + ": \"=?gb2312?B?" + str2 + "?=\"" + (addr.c_str()+pos) + "\r\n";
		else
			buffer= string("\"=?gb2312?B?") + str2 + "?=\"" + (addr.c_str()+pos);
	}
	else
	{
		if((pos=addr.find("<",pos))==string::npos)
		{
			if(bPrintCommond)
				buffer=command + ": <" + addr + ">\r\n";
			else
				buffer=string("<") + addr + ">";
		}
		else
		{
			if(bPrintCommond)
				buffer=command + ": " + addr + "\r\n";
			else
				buffer= addr;
		}
	}
}

void From(const string& addr,string & buffer)
{
	HeadTextTemple("From", addr , buffer);
}
void To(const vector<string >& to,string & buffer)
{
	string str;
	buffer="To: ";
	for(int i=0;i<to.size();i++)
	{
		if(i!=0)
			buffer+=",";
		HeadTextTemple("To", to[i] , str, FALSE);
		buffer+=str;
	}
	buffer+="\r\n";
}
void Cc(const vector<string >& cc,string & buffer)
{
	string str;
	int i;
	buffer="";

⌨️ 快捷键说明

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