mfc 发送邮件外加附件

本文主要是关于如何在mfc中如何发送邮件外加附件的~
首先要对smtp和mime这两部分有一定的了解,smtp是全称是简单的邮件传输协议,而协议是认为规定的规则,有一定的格式要求,一点错误都不可以。我在这儿犯错了,调试了好久。
  smtp:规定示例如下(已经跟服务器连接上了)
"EHLO hello\r\n" \\hello 是一个字符串随便啥都可以,就向服务器发送问好信号
"AUTH LOGIN\r\n"        \\向服务器说我要登录了
"账号\r\n" \\账号密码都要经过base64编码,输入完账号密码之后如果成功的的话, \\服务器会返回编号235
"密码\r\n"
"MAIL FROM: <str>\r\n"   \\从哪个邮箱发送的,str指的是你自己此时登录的邮箱
"RCPT TO:<str>\r\n" \\给谁发送的,str指的是目标邮箱,你是向谁发送的
"DATA\r\n" \\跟服务器说你准备要发送内容了
"From:sendername<SendFrom>\r\n"\\sendername顾名思义就是发送者的姓名(可以随便写)
"To: str\r\n"            \\给谁发送的,str指的是目标邮箱,你是向谁发送的,如果没有发送  \\这一条的话,会出现发送密信
"Subject:Str\r\n"  \\str:发送的主题
"Content-type:text/html;Charset=gb2312\r\n" \\说你是按照html格式发送的
"Content-Transfer-Encoding:8bit\r\n\r\n"   \\你传送的格式,是8位的
"Content\r\n\r\n" \\Content你的发送内容
"\r\n.\r\n" \\发送结束的标志
UINT ThreadFunc(LPVOID lpParam)
{
	pInfo* tempp = (pInfo*) lpParam;
	pInfo* p=tempp;
		
	int sockfd = 0;
	struct sockaddr_in their_addr = {0};
	char buf[1500] = {0};
	char rbuf[1500] = {0};
	char login[128] = {0};
	char pass[128] = {0};
#ifdef WIN32
	WSADATA WSAData;
	WSAStartup(MAKEWORD(2, 2), &WSAData);
#endif
	memset(&their_addr, 0, sizeof(their_addr));
	their_addr.sin_family = AF_INET;
	their_addr.sin_port = htons(25);

	their_addr.sin_addr.s_addr = inet_addr("123.125.50.132");//smtp 服务器
	// 连接邮件服务器,如果连接后没有响应,则2 秒后重新连接
	sockfd = open_socket((struct sockaddr *)&their_addr);
	memset(rbuf,0,1500);
	while(recv(sockfd, rbuf, 1500, 0) == 0)
	{
		printf("reconnect...\n");
		Sleep(2);
		//close(sockfd);
		sockfd = open_socket((struct sockaddr *)&their_addr);

		memset(rbuf,0,1500);
	}

	printf("%s\n", rbuf);

	// EHLO
	memset(buf, 0, 1500);
	sprintf(buf, _T("EHLO abcdefg-PC\r\n"));
	send(sockfd, buf, strlen(buf), 0);
	memset(rbuf, 0, 1500);
	recv(sockfd, rbuf, 1500, 0);
	printf("%s\n", rbuf);

	// AUTH LOGIN
	memset(buf, 0, 1500);
	sprintf(buf, "AUTH LOGIN\r\n");
	send(sockfd, buf, strlen(buf), 0);
	printf("%s\n", buf);
	memset(rbuf, 0, 1500);
	recv(sockfd, rbuf, 1500, 0);
	printf("%s\n", rbuf);

	// USER
	memset(buf, 0, 1500);
	sprintf(buf,p->user);//邮箱账号
	//AfxMessageBox(p->user);
	memset(login, 0, 128);
	base64(login, buf, strlen(buf));
	sprintf(buf, "%s\r\n", login);
	//AfxMessageBox(p->pwd);
	send(sockfd, buf, strlen(buf), 0);
	printf("%s\n", buf);
	memset(rbuf, 0, 1500);
	recv(sockfd, rbuf, 1500, 0);
	printf("%s\n", rbuf);

	// PASSWORD
	sprintf(buf, p->pwd);//邮箱密码
	memset(pass, 0, 128);
	base64(pass, buf, strlen(buf));
	sprintf(buf, "%s\r\n", pass);
	send(sockfd, buf, strlen(buf), 0);
	printf("%s\n", buf);

	memset(rbuf, 0, 1500);
	recv(sockfd, rbuf, 1500, 0);
	printf("%s\n", rbuf);

	// MAIL FROM
	memset(buf, 0, 1500);
	sprintf(buf, "MAIL FROM: <%s>\r\n",p->user);
	send(sockfd, buf, strlen(buf), 0);
	memset(rbuf, 0, 1500);
	recv(sockfd, rbuf, 1500, 0);
	printf("%s\n", rbuf);


	// RCPT TO 第一个收件人
	sprintf(buf, "RCPT TO:<%s>\r\n", "329636271@qq.com");
	//sprintf(buf, "RCPT TO:<%s>\r\n", p->recipt);
	send(sockfd, buf, strlen(buf), 0);
		
	// DATA 准备开始发送邮件内容
	sprintf(buf, "DATA\r\n");
	send(sockfd, buf, strlen(buf), 0);
	memset(rbuf, 0, 1500);
	recv(sockfd, rbuf, 1500, 0);
	printf("%s\n", rbuf);

	// 发送邮件内容,\r\n.\r\n内容结束标记
	CString	str;
	CString  sendername = "zwy";
	CString SendFrom =p->user;
	CString Subject = "LOL";
	CString Content="zwy is here";
	CString BOUNDARY="zwy";
	CString strTmp;
	str="From:"+sendername+"<"+SendFrom+">\r\n";
	str+="To: 329636271@qq.com\r\n";
	str+="Subject:"+Subject+"\r\n";
	str+="MIME_Version:1.0\r\n";
	str+="Content-type:multipart/mixed;Boundary=" + BOUNDARY +"\r\n\r\n";
	send(sockfd, str, strlen(str), 0);
	
	str="--";
	str+=BOUNDARY;
	str+="\r\n";
	str+="Content-type:text/html;Charset=gb2312\r\n";
	str+="Content-Transfer-Encoding:8bit\r\n\r\n";
	str+=Content+"\r\n\r\n";
	send(sockfd, str, strlen(str), 0);

	strTmp="\r\n--";
	strTmp+=BOUNDARY;
	strTmp+="\r\n";
	///......Content-Type:application/octet-stream
	strTmp+="Content-Type:application/octet-stream; name=att.jpg\r\n";
	strTmp+="Content-Transfer-Encoding:base64\r\n\r\n";
	
	//strTmp+="YWFhYWFhYWFhYWFhYWFhYWFh\r\n\r\n";
	send(sockfd,strTmp,strTmp.GetLength(),0);
		ZBase64 mybase;
		CString fFile = "F:\\MyProjects\\sm\\sm\\yy.jpg";
		FILE * fin = fopen(fFile,"rb");
		FILE * fout = fopen("tt.jpg","wb");
		int m_size = 228;
		char * imgbuf = new char[1500];
		char * imgbuf2 = new char[1500];
		memset(imgbuf,0,sizeof(imgbuf));
		int m_read = fread(imgbuf,1,m_size,fin);

		while(m_read == m_size)
		{
			fwrite(imgbuf,1,m_size,fout);
			memset(imgbuf2,0,sizeof(imgbuf2));
			str = mybase.Encode((unsigned char*)imgbuf,m_read);
			send(sockfd,str,str.GetLength(),0);
			memset(imgbuf,0,m_size);
			m_read = fread(imgbuf,1,m_size,fin);
		}
		str.Format("ni hao a %d",m_read);
		AfxMessageBox(str);
		fwrite(imgbuf,1,m_read,fout);
		if(m_read > 0)
		{
			fwrite(imgbuf,1,m_read,fout);
			memset(imgbuf2,0,m_size);
			//base64(imgbuf2,imgbuf,m_read);
			str = mybase.Encode((unsigned char*)imgbuf,m_read);
			str+="\r\n\r\n";
			send(sockfd,str,str.GetLength(),0);
		}else{
			str="\r\n\r\n";
			send(sockfd,str,str.GetLength(),0);
		}
		delete []imgbuf;
		delete []imgbuf2;
		fclose(fin);
		fclose(fout);/**/

	str="\r\n--";
	str+=BOUNDARY+"\r\n";
	str+="\r\n.\r\n";
	send(sockfd, str, strlen(str), 0);

	memset(rbuf, 0, 1500);
	recv(sockfd, rbuf, 1500, 0);
	if(!CheckResponse(sockfd,"250")) AfxMessageBox("fasongchengong");;
	str.Format("fanhui %d",sockfd);
	AfxMessageBox(str);
	// QUIT
	sprintf(buf, "QUIT\r\n");
	send(sockfd, buf, strlen(buf), 0);
	memset(rbuf, 0, 1500);
	recv(sockfd, rbuf, 1500, 0);
	printf("%s\n", rbuf);

	// VC2005 需要使用
	closesocket(sockfd);
	//	close(sockfd);
#ifdef WIN32
	WSACleanup();
#endif
	return 0;
}
#pragma once

#pragma warning(disable:4786) 
#include <string>
using namespace std;
class ZBase64
{
public:
	ZBase64(void);
		/*编码
	DataByte
		[in]输入的数据长度,以字节为单位
	*/
	CString Encode(const unsigned char* Data,int DataByte);

	/*解码
	DataByte
		[in]输入的数据长度,以字节为单位
	OutByte
		[out]输出的数据长度,以字节为单位,请不要通过返回值计算
		输出数据的长度
	*/
	CString Decode(const char* Data,int DataByte,int& OutByte);
	~ZBase64(void);
};
int open_socket(struct sockaddr * addr)
{
	int sockfd = 0;
	sockfd=socket(PF_INET, SOCK_STREAM, 0);
	if(sockfd < 0)
	{
		fprintf(stderr, "Open sockfd(TCP) error!\n");
		exit(-1);
	}
	if(connect(sockfd, addr, sizeof(struct sockaddr)) < 0)
	{
		fprintf(stderr, "Connect sockfd(TCP) error!\n");
		exit(-1);
	}
	return sockfd;

}

bool CheckResponse(int m_socket,const char* RecvCode)
{
	try
	{
		char Buf[1024]={0};
		if(recv(m_socket,Buf,1024,0) == SOCKET_ERROR) return false;
		//AfxMessageBox(Buf);
		return RecvCode[0] == Buf[0] && \
			RecvCode[1] == Buf[1] && \
			RecvCode[2] == Buf[2] ? true : false;
	}
	catch(...)
	{
		return false;
	}
}


#include "StdAfx.h"
#include "ZBase64.h"

ZBase64::ZBase64(void)
{
}
CString ZBase64::Encode(const unsigned char* Data,int DataByte)
{
	//编码表
	const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

	//返回值
	string strEncode;

	unsigned char Tmp[3]={0};
	int LineLength=0;

	for(int i=0;i<(int)(DataByte / 3);i++)
	{
		Tmp[1] = *Data++;
		Tmp[2] = *Data++;
		Tmp[3] = *Data++;

		strEncode+= EncodeTable[Tmp[1] >> 2];
		strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
		strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
		strEncode+= EncodeTable[Tmp[3] & 0x3F];
		if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}
	}

	//对剩余数据进行编码
	int Mod=DataByte % 3;
	if(Mod==1)
	{
		Tmp[1] = *Data++;
		strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
		strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
		strEncode+= "==";
	}
	else if(Mod==2)
	{
		Tmp[1] = *Data++;
		Tmp[2] = *Data++;
		strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
		strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
		strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
		strEncode+= "=";
	}

	return strEncode.c_str();
}

CString ZBase64::Decode(const char* Data,int DataByte,int& OutByte)
{
	//解码表
	const char DecodeTable[] =
	{
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		62, // '+'
		0, 0, 0,
		63, // '/'
		52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
		0, 0, 0, 0, 0, 0, 0,
		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
		13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
		0, 0, 0, 0, 0, 0,
		26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
		39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
	};

	//返回值
	string strDecode;

	int nValue;
	int i= 0;

	while (i < DataByte)
	{
		if (*Data != '\r' && *Data!='\n')
		{
			nValue = DecodeTable[*Data++] << 18;
			nValue += DecodeTable[*Data++] << 12;
			strDecode+=(nValue & 0x00FF0000) >> 16;
			OutByte++;

			if (*Data != '=')
			{
				nValue += DecodeTable[*Data++] << 6;
				strDecode+=(nValue & 0x0000FF00) >> 8;
				OutByte++;

				if (*Data != '=')
				{
					nValue += DecodeTable[*Data++];
					strDecode+=nValue & 0x000000FF;
					OutByte++;
				}
			}
			i += 4;
		}
		else// 回车换行,跳过
		{
			Data++;
			i++;
		}
	}
	return strDecode.c_str();
}


ZBase64::~ZBase64(void)
{
}


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值