c语言socket smtp 邮件 附件,C++实现含附件的邮件发送功能

C++实现邮件发送程序在vs2013测试通过,一共3个文件,发邮件的程序封装为Csmtp 类。

e84d6043e7b4edf1b6a575a141b74b48.png

1.测试用的主函数

//

#include "Csmtp.h"

#pragma comment(lib, "Kernel32.lib")

int main()

{

Csmtp mail(

25,

"smtp.126.com",

"username@126.com",// 来源邮箱

"pwd",

"username@126.com" //目标邮箱

);

if (!mail.CReateSocket())

{

cout << "ReateSocket failed!" << endl;

return -1;//

}

mail.setTitle("test mail");

mail.setContent("this is content.");

mail.addfile("test1.png"); //添加附件

mail.addfile("test2.png"); //添加附件

mail.SendMail(); //类主函数

return 0;

}

2.Csmtp类定义

#include

#include

#include

#include

#include //适用平台 Windows

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

// POP3服务器(端口:110) Csmtp服务器(端口:25)

using namespace std;

class Csmtp

{

int port;

string domain;

string user;

string pass;

string target;

string title; //邮件标题

string content; //邮件内容

HOSTENT* pHostent;

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

vector filename; //存储附件名的向量

public:

Csmtp(

int _port, //端口25

string _domain, //域名

string _user, //发送者的邮箱

string _pass, //密码

string _target) //目标邮箱

:port(_port),domain(_domain),user(_user),pass(_pass), target(_target){};//内容

bool CReateSocket();

void setTitle(string tem){title = tem;}

void setContent(string tem){content = tem;}

int SendAttachment(SOCKET &sockClient);

int SendMail();

void addfile(string str){filename.push_back(str);}

};

3. Csmtp 类的实现

#include "Csmtp.h"

//#include //异常类

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

char* 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;

}

int Csmtp::SendAttachment(SOCKET &sockClient) /*发送附件*/

{

for (std::vector::iterator iter = filename.begin();iter != filename.end(); iter++)

{

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

string path=*iter;

ifstream ifs(path, ios::in | ios::binary); //'或链接2个属性,以输入、二进制打开'

if (false == ifs.is_open())

{

cout<

return 1;

}

string sendstring;

sendstring = "--@boundary@\r\nContent-Type: application/octet-stream; name=\"1.jpg\"\r\n";

sendstring += "Content-Disposition: attachment; filename=\"1.jpg\"\r\n";

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

send(sockClient, sendstring.c_str(), sendstring.length(), 0);

//infile.read((char*)buffer,sizeof(数据类型));

// get length of file:

ifs.seekg (0, ifs.end);

int length = ifs.tellg();

ifs.seekg (0, ifs.beg);

cout<

// allocate memory:

char * buffer = new char [length];

// read data as a block:

ifs.read (buffer,length);

ifs.close();

char *pbase;

pbase = base64Encode(buffer, length);

delete[]buffer;

string str(pbase);

delete[]pbase;

str+="\r\n";

int err =send(sockClient, str.c_str(), strlen(str.c_str()), 0);

if (err != strlen(str.c_str()))

{

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

return 1;

}

}

return 0;

}

bool Csmtp::CReateSocket()

{

WSADATA wsaData;

WORD wVersionRequested = MAKEWORD(2, 1);

//WSAStarup,即WSA(Windows SocKNDs Asynchronous,Windows套接字异步)的启动命令

int err = WSAStartup(wVersionRequested, &wsaData);

cout<

char namebuf[128]; //获得本地计算机名

string ip_list;

if(0==gethostname(namebuf,128))

{

struct hostent* pHost; //获得本地IP地址

pHost=gethostbyname(namebuf); //pHost返回的是指向主机的列表

for (int i=0;pHost!=NULL&&pHost->h_addr_list[i]!=NULL;i++)

{

string tem = inet_ntoa(*(struct in_addr *)pHost->h_addr_list[i]);

ip_list += tem;

ip_list += "\n";

}

}

else

{

cout<

}

//

title=namebuf;// 邮件标题

content=ip_list; //主机ip

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

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

if (pHostent == NULL)

{

printf( "创建连接失败,也许没联网!\n" );

return false;

}

return true;

}

int Csmtp::SendMail()

{

char *ecode;

char buff[500]; //recv函数返回的结果

int err = 0;

string message; //

SOCKADDR_IN addrServer; //服务端地址

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

addrServer.sin_family = AF_INET;

addrServer.sin_port = htons(port); //连接端口25

//int connect (SOCKET s , const struct sockaddr FAR *name , int namelen );

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

cout<

//telnet smtp.126.com 25 连接服务器结束

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

message="ehlo 126.com\r\n";

send(sockClient, message.c_str(), message.length(), 0);

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

message="auth login \r\n";

send(sockClient, message.c_str(), message.length(), 0);

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

//上传邮箱名

message=user;

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

message = ecode;

message += "\r\n";

delete[]ecode;

send(sockClient, message.c_str(), message.length(), 0);

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

//上传邮箱密码

message=pass;

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

message = ecode;

delete[]ecode;

message += "\r\n";

send(sockClient, message.c_str(), message.length(), 0);

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

message="mail from:\r\nrcpt to:\r\n";

send(sockClient, message.c_str(), message.length(), 0);

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

message="data\r\n";//data要单独发送一次

send(sockClient, message.c_str(), message.length(), 0);

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

///-----------------------------------------DATA-------------------------------------

//要使用Csmtp 发送附件, 需要对Csmtp 头信息进行说明, 改变Content-type 及为每一段正文添加BOUNDARY 名,

cout<

// 头

message="from:"+user+"\r\nto:"+target+"\r\nsubject:"+title+"\r\n";

message += "MIME-Version: 1.0\r\n";

message += "Content-Type: multipart/mixed;boundary=@boundary@\r\n\r\n";

send(sockClient, message.c_str(), message.length(), 0);

// 正文

message = "--@boundary@\r\nContent-Type: text/plain;charset=\"gb2312\"\r\n\r\n"+content+"\r\n\r\n";

send(sockClient, message.c_str(), message.length(), 0);

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

// 发送附件

SendAttachment(sockClient);

/*发送结尾信息*/

message = "--@boundary@--\r\n.\r\n";

send(sockClient, message.c_str(), message.length(), 0);

buff[recv(sockClient, buff, 500, 0)]='\0';

//cout<

message="QUIT\r\n";

send(sockClient, message.c_str(), message.length(), 0);

buff[recv(sockClient, buff, 500, 0)]='\0';

cout<

return 0;

}

容易理解的简化版可以点击->这里

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值