c++程序发送邮件、MATLAB程序发送邮件

用过几年MATLAB之后,开始逐渐转向c++。MATLAB优点在于语法简单、系统自带的函数充足、数据可视化容易。缺点是除了矩阵相关操作外,速度较慢,在迭代、逻辑判断中更加明显。有时候这是无法避免的。c++速度就要快很多,支持多线程,其他方面就挺繁琐的了。

整理一下两者发送邮件的程序,在计算完成后通知我,对我这样的懒人挺有用的。


MATLAB发邮件,写成一个函数比较方便。

比如:我要发给:xxx@qq.com , 主题是:hello , 内容是:ok,我的D盘有个文件 m2m.m作为附件,

调用方式为:

mail2me('xxx@qq.com','hello','ok','D:\m2m.m')  %输入全是字符串

%----------------------------------------------------------------------

function mail2me(mail,subject,content,DataPath)

try  %用try语句,断网时自动跳过

MailAddress = '2015xxxxxx@student.cup.edu.cn';%用来发邮件的地址

password = 'xxxxxxxxxxx'; %密码

setpref('Internet','E_mail',MailAddress);

setpref('Internet','SMTP_Server','smtp.cup.edu.cn');%邮件服务器smtp

setpref('Internet','SMTP_Username',MailAddress);

setpref('Internet','SMTP_Password',password);

props = java.lang.System.getProperties;

props.setProperty('mail.smtp.auth','true');

sendmail(mail,subject,content,DataPath);

catch

   

end


end

%--------------------------------------------------------------------

注:完成发送需要前往邮箱设置开启SMTP服务。还可以通过命令system('systeminfo')将计算机信息写入邮件中,再加入计算进度等内容是不是很方便呢?另外使用命令pcode mail2me就能给程序打包加密了,谁也看不到函数内部的密码。




c++发邮件


//先定义个头文件吧---


#ifndef __SMTP_H__ //避免重复包含  

#define __SMTP_H__  


#include <iostream>  

#include <list>  

#include <WinSock2.h>  

using namespace std;


const int MAXLEN = 1024;

const int MAX_FILE_LEN = 6000;


static const char base64Char[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";


struct FILEINFO /*用来记录文件的一些信息*/

{

char fileName[128]; /*文件名称*/

char filePath[256]; /*文件绝对路径*/

};


class CSmtp

{

public:

CSmtp(void);

CSmtp(

int port,

string srvDomain,   //smtp服务器域名  

string userName,    //用户名  

string password,    //密码  

string targetEmail, //目的邮件地址  

string emailTitle,  //主题  

string content       //内容  

);

public:

~CSmtp(void);

public:

int port;

public:

string domain;

string user;

string pass;

string targetAddr;

string title;

string content;

/*为了方便添加文件,删除文件神马的,使用list容器最为方便,相信大家在数据结构里面都学过*/

list <FILEINFO *> listFile;


public:

char buff[MAXLEN + 1];

int buffLen;

SOCKET sockClient;  //客户端的套接字  

public:

bool CreateConn(); /*创建连接*/


bool Send(string &message);

bool Recv();


void FormatEmailHead(string &email);//格式化要发送的邮件头部  

int Login();

bool SendEmailHead();       //发送邮件头部信息  

bool SendTextBody();        //发送文本信息  

//bool SendAttachment();        //发送附件  

int SendAttachment_Ex();

bool SendEnd();

public:

void AddAttachment(string &filePath); //添加附件  

void DeleteAttachment(string &filePath); //删除附件  

void DeleteAllAttachment(); //删除所有的附件  


void SetSrvDomain(string &domain);

void SetUserName(string &user);

void SetPass(string &pass);

void SetTargetEmail(string &targetAddr);

void SetEmailTitle(string &title);

void SetContent(string &content);

void SetPort(int port);

int SendEmail_Ex();

/*关于错误码的说明:1.网络错误导致的错误2.用户名错误3.密码错误4.文件不存在0.成功*/

char* base64Encode(char const* origSigned, unsigned origLength);

};


#endif // !__SMTP_H__


//-------------------------------------------------------------------------------------




//源文件添加Smtp.cpp

#include "Smtp.h"  

#include <iostream>  

#include <fstream>  

using namespace std;


#pragma  comment(lib, "ws2_32.lib") /*链接ws2_32.lib动态链接库*/  


/*base64采用别人的编码,不过,这不是重点,重点是我完成了我的一个比较好的邮件发送客户端*/

char* CSmtp::base64Encode(char const* origSigned, unsigned origLength)

{

unsigned char const* orig = (unsigned char const*)origSigned; // in case any input bytes have the MSB set  

if (orig == NULL) return NULL;


unsigned const numOrig24BitValues = origLength / 3;

bool havePadding = origLength > numOrig24BitValues * 3;

bool havePadding2 = origLength == numOrig24BitValues * 3 + 2;

unsigned const numResultBytes = 4 * (numOrig24BitValues + havePadding);

char* result = new char[numResultBytes + 3]; // allow for trailing '/0'  


// Map each full group of 3 input bytes into 4 output base-64 characters:  

unsigned i;

for (i = 0; i < numOrig24BitValues; ++i)

{

result[4 * i + 0] = base64Char[(orig[3 * i] >> 2) & 0x3F];

result[4 * i + 1] = base64Char[(((orig[3 * i] & 0x3) << 4) | (orig[3 * i + 1] >> 4)) & 0x3F];

result[4 * i + 2] = base64Char[((orig[3 * i + 1] << 2) | (orig[3 * i + 2] >> 6)) & 0x3F];

result[4 * i + 3] = base64Char[orig[3 * i + 2] & 0x3F];

}


// Now, take padding into account.  (Note: i == numOrig24BitValues)  

if (havePadding)

{

result[4 * i + 0] = base64Char[(orig[3 * i] >> 2) & 0x3F];

if (havePadding2)

{

result[4 * i + 1] = base64Char[(((orig[3 * i] & 0x3) << 4) | (orig[3 * i + 1] >> 4)) & 0x3F];

result[4 * i + 2] = base64Char[(orig[3 * i + 1] << 2) & 0x3F];

}

else

{

result[4 * i + 1] = base64Char[((orig[3 * i] & 0x3) << 4) & 0x3F];

result[4 * i + 2] = '=';

}

result[4 * i + 3] = '=';

}


result[numResultBytes] = '\0';

return result;

}

CSmtp::CSmtp(void)

{

this->content = "";

this->port = 25;

this->user = "";

this->pass = "";

this->targetAddr = "";

this->title = "";

this->domain = "";


WORD wVersionRequested;

WSADATA wsaData;

int err;

wVersionRequested = MAKEWORD(2, 1);

err = WSAStartup(wVersionRequested, &wsaData);

this->sockClient = 0;


}


CSmtp::~CSmtp(void)

{

DeleteAllAttachment();

closesocket(sockClient);

WSACleanup();

}



CSmtp::CSmtp(

int port,

string srvDomain,

string userName,

string password,

string targetEmail,

string emailTitle,

string content

)

{

this->content = content;

this->port = port;

this->user = userName;

this->pass = password;

this->targetAddr = targetEmail;

this->title = emailTitle;

this->domain = srvDomain;


WORD wVersionRequested;

WSADATA wsaData;

int err;

wVersionRequested = MAKEWORD(2, 1);

err = WSAStartup(wVersionRequested, &wsaData);

this->sockClient = 0;

}


bool CSmtp::CreateConn()

{

//为建立socket对象做准备,初始化环境  

SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); //建立socket对象  

SOCKADDR_IN addrSrv;

HOSTENT* pHostent;

pHostent = gethostbyname(domain.c_str());  //得到有关于域名的信息  


addrSrv.sin_addr.S_un.S_addr = *((DWORD *)pHostent->h_addr_list[0]); //得到smtp服务器的网络字节序的ip地址    

addrSrv.sin_family = AF_INET;

addrSrv.sin_port = htons(port);

int err = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));   //向服务器发送请求  

if (err != 0)

{

return false;

 

}

this->sockClient = sockClient;

if (false == Recv())

{

return false;

}

return true;

}


bool CSmtp::Send(string &message)

{

int err = send(sockClient, message.c_str(), message.length(), 0);

if (err == SOCKET_ERROR)

{

return false;

}

string message01;

cout << message.c_str() << endl;

return true;

}


bool CSmtp::Recv()

{

memset(buff, 0, sizeof(char)* (MAXLEN + 1));

int err = recv(sockClient, buff, MAXLEN, 0); //接收数据  

if (err == SOCKET_ERROR)

{

return false;

}

buff[err] = '\0';

cout << buff << endl;

return true;

}


int CSmtp::Login()

{

string sendBuff;

sendBuff = "EHLO ";

sendBuff += user;

sendBuff += "\r\n";


if (false == Send(sendBuff) || false == Recv()) //既接收也发送  

{

return 1; /*1表示发送失败由于网络错误*/

}


sendBuff.empty();

sendBuff = "AUTH LOGIN\r\n";

if (false == Send(sendBuff) || false == Recv()) //请求登陆  

{

return 1; /*1表示发送失败由于网络错误*/

}


sendBuff.empty();

int pos = user.find('@', 0);

sendBuff = user.substr(0, pos); //得到用户名  


char *ecode;

/*在这里顺带扯一句,关于string类的length函数与C语言中的strlen函数的区别,

strlen计算出来的长度,只到'\0'字符为止,

而string::length()函数实际上返回的是string类中字符数组的大小,

你自己可以测试一下,这也是为什么我下面不使用string::length()的原因*/


ecode = base64Encode(sendBuff.c_str(), strlen(sendBuff.c_str()));

sendBuff.empty();

sendBuff = ecode;

sendBuff += "\r\n";

delete[]ecode;


if (false == Send(sendBuff) || false == Recv()) //发送用户名,并接收服务器的返回  

{

return 1; /*错误码1表示发送失败由于网络错误*/

}


sendBuff.empty();

ecode = base64Encode(pass.c_str(), strlen(pass.c_str()));

sendBuff = ecode;

sendBuff += "\r\n";

delete[]ecode;


if (false == Send(sendBuff) || false == Recv()) //发送用户密码,并接收服务器的返回  

{

return 1; /*错误码1表示发送失败由于网络错误*/

}


if (NULL != strstr(buff, "550"))

{

return 2;/*错误码2表示用户名错误*/

}


if (NULL != strstr(buff, "535")) /*535是认证失败的返回*/

{

return 3; /*错误码3表示密码错误*/

}

return 0;

}


bool CSmtp::SendEmailHead()     //发送邮件头部信息  

{

string sendBuff;

sendBuff = "MAIL FROM: <" + user + ">\r\n";

if (false == Send(sendBuff) || false == Recv())

{

return false; /*表示发送失败由于网络错误*/

}



sendBuff.empty();

sendBuff = "RCPT TO: <" + targetAddr + ">\r\n";

if (false == Send(sendBuff) || false == Recv())

{

return false; /*表示发送失败由于网络错误*/

}


sendBuff.empty();

sendBuff = "DATA\r\n";

if (false == Send(sendBuff) || false == Recv())

{

return false; //表示发送失败由于网络错误  

}


sendBuff.empty();

FormatEmailHead(sendBuff);

if (false == Send(sendBuff))

//发送完头部之后不必调用接收函数,因为你没有\r\n.\r\n结尾,服务器认为你没有发完数据,所以不会返回什么值  

{

return false; /*表示发送失败由于网络错误*/

}

return true;

}


void CSmtp::FormatEmailHead(string &email)

{/*格式化要发送的内容*/

email = "From: ";

email += user;

email += "\r\n";


email += "To: ";

email += targetAddr;

email += "\r\n";


email += "Subject: ";

email += title;

email += "\r\n";


email += "MIME-Version: 1.0";

email += "\r\n";


email += "Content-Type: multipart/mixed;boundary=qwertyuiop";

email += "\r\n";

email += "\r\n";

}


bool CSmtp::SendTextBody()  /*发送邮件文本*/

{

string sendBuff;

sendBuff = "--qwertyuiop\r\n";

sendBuff += "Content-Type: text/plain;";

sendBuff += "charset=\"gb2312\"\r\n\r\n";

sendBuff += content;

sendBuff += "\r\n\r\n";

return Send(sendBuff);

}


int CSmtp::SendAttachment_Ex() /*发送附件*/

{

for (list<FILEINFO *>::iterator pIter = listFile.begin(); pIter != listFile.end(); pIter++)

{

cout << "Attachment is sending ~~~~~" << endl;

cout << "Please be patient!" << endl;

string sendBuff;

sendBuff = "--qwertyuiop\r\n";

sendBuff += "Content-Type: application/octet-stream;\r\n";

sendBuff += " name=\"";

sendBuff += (*pIter)->fileName;

sendBuff += "\"";

sendBuff += "\r\n";


sendBuff += "Content-Transfer-Encoding: base64\r\n";

sendBuff += "Content-Disposition: attachment;\r\n";

sendBuff += " filename=\"";

sendBuff += (*pIter)->fileName;

sendBuff += "\"";


sendBuff += "\r\n";

sendBuff += "\r\n";

Send(sendBuff);

ifstream ifs((*pIter)->filePath, ios::in | ios::binary);

if (false == ifs.is_open())

{

return 4; /*错误码4表示文件打开错误*/

}

char fileBuff[MAX_FILE_LEN];

char *chSendBuff;

memset(fileBuff, 0, sizeof(fileBuff));

/*文件使用base64加密传送*/

while (ifs.read(fileBuff, MAX_FILE_LEN))

{

//cout << ifs.gcount() << endl;  

chSendBuff = base64Encode(fileBuff, MAX_FILE_LEN);

chSendBuff[strlen(chSendBuff)] = '\r';

chSendBuff[strlen(chSendBuff)] = '\n';

send(sockClient, chSendBuff, strlen(chSendBuff), 0);

delete[]chSendBuff;

}

//cout << ifs.gcount() << endl;  

chSendBuff = base64Encode(fileBuff, ifs.gcount());

chSendBuff[strlen(chSendBuff)] = '\r';

chSendBuff[strlen(chSendBuff)] = '\n';

int err = send(sockClient, chSendBuff, strlen(chSendBuff), 0);


if (err != strlen(chSendBuff))

{

cout << "文件传送出错!" << endl;

return 1;

}

delete[]chSendBuff;

}

return 0;

}


bool CSmtp::SendEnd() /*发送结尾信息*/

{

string sendBuff;

sendBuff = "--qwertyuiop--";

sendBuff += "\r\n.\r\n";

if (false == Send(sendBuff) || false == Recv())

{

return false;

}

cout << buff << endl;

sendBuff.empty();

sendBuff = "QUIT\r\n";

return (Send(sendBuff) && Recv());

}


int CSmtp::SendEmail_Ex()

{

if (false == CreateConn())

{

return 1;

}

//Recv();  

int err = Login(); //先登录  

if (err != 0)

{

return err; //错误代码必须要返回  

}

if (false == SendEmailHead()) //发送EMAIL头部信息  

{

return 1; /*错误码1是由于网络的错误*/

}

if (false == SendTextBody())

{

return 1; /*错误码1是由于网络的错误*/

}

err = SendAttachment_Ex();

if (err != 0)

{

return err;

}

if (false == SendEnd())

{

return 1; /*错误码1是由于网络的错误*/

}

return 0; /*0表示没有出错*/

}


void CSmtp::AddAttachment(string &filePath) //添加附件  

{

FILEINFO *pFile = new FILEINFO;

strcpy_s(pFile->filePath, filePath.c_str());

const char *p = filePath.c_str();

strcpy_s(pFile->fileName, p + filePath.find_last_of("\\") + 1);

listFile.push_back(pFile);

}


void CSmtp::DeleteAttachment(string &filePath) //删除附件  

{

list<FILEINFO *>::iterator pIter;

for (pIter = listFile.begin(); pIter != listFile.end(); pIter++)

{

if (strcmp((*pIter)->filePath, filePath.c_str()) == 0)

{

FILEINFO *p = *pIter;

listFile.remove(*pIter);

delete p;

break;

}

}

}


void CSmtp::DeleteAllAttachment() /*删除所有的文件*/

{

for (list<FILEINFO *>::iterator pIter = listFile.begin(); pIter != listFile.end();)

{

FILEINFO *p = *pIter;

pIter = listFile.erase(pIter);

delete p;

}

}


void CSmtp::SetSrvDomain(string &domain)

{

this->domain = domain;

}


void CSmtp::SetUserName(string &user)

{

this->user = user;

}


void CSmtp::SetPass(string &pass)

{

this->pass = pass;

}

void CSmtp::SetTargetEmail(string &targetAddr)

{

this->targetAddr = targetAddr;

}

void CSmtp::SetEmailTitle(string &title)

{

this->title = title;

}

void CSmtp::SetContent(string &content)

{

this->content = content;

}

void CSmtp::SetPort(int port)

{

this->port = port;

}





//然后是主程序


#include "Smtp.h"  

#include <iostream>  

using namespace std;


int main()

{


CSmtp smtp(

25,                    /*smtp端口*/

"smtp.163.com",                 /*smtp服务器地址*/

"exxxxx@163.com",    /*你的邮箱地址*/

"xxxxxxxxx",                  /*邮箱密码*/

"xxxx@qq.com",    /*目的邮箱地址*/

"成功了!",                          /*主题*/

"测试邮件!"       /*邮件正文*/

);

/**

//添加附件时注意,\一定要写成\\,因为转义字符的缘故

string filePath("D:\\m2m.m");

smtp.AddAttachment(filePath);

*/

string filePath("D:\\m2m.m");

smtp.AddAttachment(filePath);

/*还可以调用CSmtp::DeleteAttachment函数删除附件,还有一些函数,自己看头文件吧!*/

//filePath = "C:\\Users\\李懿虎\\Desktop\\sendEmail.cpp";  

//smtp.AddAttachment(filePath);  


int err;

if ((err = smtp.SendEmail_Ex()) != 0)

{

if (err == 1)

cout << "错误1: 由于网络不畅通,发送失败!" << endl;

if (err == 2)

cout << "错误2: 用户名错误,请核对!" << endl;

if (err == 3)

cout << "错误3: 用户密码错误,请核对!" << endl;

if (err == 4)

cout << "错误4: 请检查附件目录是否正确,以及文件是否存在!" << endl;

}

system("pause");

return 0;

}


注:上述c++程序对163邮箱可直接使用,其他邮箱在 Smtp.cpp中CSmtp::Login()函数

这一句 int pos = user.find('@', 0);  略有不同,具体是把@换为空格,然后在主程序目标地址后加一个空格。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值