本文主要是关于如何在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" \\发送结束的标志
首先要对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)
{
}