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

1,测试用的主函数


#include "Csmtp.h"
#pragma comment(lib, "Kernel32.lib")  int main()
{Csmtp mail(25,"smtp.126.com","xxx@126.com",// 来源邮箱"xxx",   //密码"xxx.com" //目标邮箱);if (!mail.CReateSocket()){cout << "ReateSocket failed!" << endl;return -1;//}//标题默认是主机名,内容默认是ipmail.setTitle("test mail");mail.setContent("this is content.");//附件路径错误,不影响邮件正文的发送。mail.addfile("test.jpg"); //添加附件//mail.addfile("test2.png"); //添加附件mail.SendMail(); //类主函数system("pause");return 0;
}

2, Csmtp类定义

#include <iostream>
#include <string>
#include <vector>
#include <fstream>  #include <WinSock2.h>  //适用平台 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 <string> filename;  //存储附件名的向量public:Csmtp(int _port, //端口25string _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 <afx.h>//异常类
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<string>::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 << "无法打开文件!" << endl;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 << "length:" << length << endl;// 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 << "WSAStartup(0:successful):" << err << endl;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 << "获取主机信息失败..." << endl;}//title = namebuf;// 邮件标题content = ip_list; //主机ipsockClient = 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 << "connect:" << err << endl;//telnet smtp.126.com 25 连接服务器结束buff[recv(sockClient, buff, 500, 0)] = '\0';cout<<"connect:"<<buff<<endl;message = "ehlo 126.com\r\n";send(sockClient, message.c_str(), message.length(), 0);buff[recv(sockClient, buff, 500, 0)] = '\0';cout<<"helo:"<<buff<<endl;message = "auth login \r\n";send(sockClient, message.c_str(), message.length(), 0);buff[recv(sockClient, buff, 500, 0)] = '\0';cout<<"auth login:"<<buff<<endl;//上传邮箱名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<<"usrname:"<<buff<<endl;//上传邮箱密码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<<"password:"<<buff<<endl;message = "mail from:<" + user + ">\r\nrcpt to:<" + target + ">\r\n";send(sockClient, message.c_str(), message.length(), 0);buff[recv(sockClient, buff, 500, 0)] = '\0';cout<<"mail from: "<<buff<<endl;buff[recv(sockClient, buff, 500, 0)] = '\0';cout<<"rcpt to: "<<buff<<endl;message = "data\r\n";//data要单独发送一次send(sockClient, message.c_str(), message.length(), 0);buff[recv(sockClient, buff, 500, 0)] = '\0';cout<<"data: "<<buff<<endl;///-----------------------------------------DATA-------------------------------------//要使用Csmtp 发送附件, 需要对Csmtp 头信息进行说明, 改变Content-type 及为每一段正文添加BOUNDARY 名,cout << "-------------------DATA------------------------" << endl;//  头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<<"end_qwertyuiop:"<<buff<<endl;message = "QUIT\r\n";send(sockClient, message.c_str(), message.length(), 0);buff[recv(sockClient, buff, 500, 0)] = '\0';cout << "Send mail is finish:" << buff << endl;return 0;
}

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

c++ 发邮件(含附件)相关推荐

  1. 1.3windows命令行下使用blat发邮件带附件

    windows命令行bat批处理脚本的应用之blat程序自动发邮件  1.3windows命令行下使用blat发邮件带附件  __游旗丶引莫(孙忠)  发邮件脚本模板  rem  ----邮件内容-- ...

  2. Scala发邮件(带附件,无论是本地文件和hdfs文件或df或rdd)

    @羲凡--只为了更好的活着 Scala发邮件(带附件,无论是本地文件和hdfs文件或df或rdd) 在有些spark任务执行完后需要通知我们该任务已经执行结束,发邮件到某个邮箱是最直接的方式.那如何用 ...

  3. python发邮件添加附件(十)

    #一.python发邮件添加附件 这是一个神奇的工具,要好好学哦 !!! import smtplib# 1.发送人账号 sendAddress = 'xxx@qq.com' # 2.发送人授权码 p ...

  4. Java Mail---SMTP协议-Java发邮件(带附件)演示过程

    转载请注明出处: http://blog.csdn.net/qq_26525215 本文源自[大学之旅_谙忆的博客] JavaMail-API简介: 邮件客户端的主要任务是向邮件服务器发送邮件,以及接 ...

  5. Spring Boot 发邮件和附件,超实用!

    Spring Boot集成邮件服务竟如此简单,快速掌握邮件业务类的核心逻辑和企业邮件的日常服务. 什么是SMTP? SMTP全称为Simple Mail Transfer Protocol(简单邮件传 ...

  6. python接口自动化-发邮件带附件

    自动化脚本运行完成以后需要发邮件给相关负责人,那么怎样发送邮件呢,邮件里边又是怎么带附件的呢,今天我们就来了解一下. 1.发送邮件不带附件 首先创建一个py文件,名称为send_main.py,文件内 ...

  7. python自动化发邮件(带附件及正文显示图片)

    一.python自动发送邮件-(附件及正文图片) 带附件邮件(1) 前言:一般我们发送邮件,整体的逻辑是这样的,先登录邮箱,发件人,收件人,主题,附件,内容 尝试自动发邮件,并且携带附件,代码如下 f ...

  8. Java 发邮件-带附件且正文html格式

    入职新公司不久,接到一个给用户发邮件的需求,有两点需要说明的:1)正文需要格式化:2)需要带附件. 大概了解了一下需求,我马上开始思考,现有项目中是否有类似的接口可以支持,如果可以支持,那我就不用再开 ...

  9. python用outlook自动发邮件_python调用outlook发送exchange邮件(含附件)

    最近在解决一个问题,就是生成每日数据的报表,然后利用邮件群发给各位同事.由于主要工作不在这,为了节省时间,所以选择了使用python语言. 选择发送邮件时,有人可能会说直接使用smtp库不就行吗?为啥 ...

  10. python自动办公-发邮件带附件

    这一篇的话区别于上一篇在于增加了添加附件的功能,增大邮件的功能 import smtplib 1.发送人账号 sendAddress = '928606004@qq.com' 2.发送人你授权码(邮箱 ...

最新文章

  1. AI人才报告 | AI稳超互联网平均薪资,哪些细分领域最受追捧?
  2. LINUX按照物理地址预取,linux – 如何以编程方式禁用硬件预取?
  3. java 中线程的创建方式
  4. QML基本可视化元素--Text
  5. ​浅谈Asp.net的sessionState
  6. 083_html5应用程序缓存
  7. xgboost模型在centos系统下的可视化
  8. 『数据库』朴实无华且枯燥的数据库文章--关系数据理论
  9. 前端进阶(8) - 前端开发需要了解的工具集合:webpack, eslint, prettier, ...
  10. python package安装包_安装Python包(第三方库)
  11. pywin32 获取窗口句柄_Excel VBA | 这个窗口居然关不掉
  12. 深入浅出Docker 镜像 | 技术头条
  13. java char占用多少字节_Java虚拟机:Java对象大小、对象内存布局及锁状态变化
  14. 孔板流量计计算公式_带你全面了解各种流量计!
  15. ENVI实现归一化建筑物指数(NDBI)实验操作
  16. TCPIP协议详解内容总结
  17. 三大开源bi工具_Power BI与同类工具对比,行业应用该选谁?
  18. 利用计算机技术设计直流稳压电源,基于单片机的直流稳压电源的设计(本科)毕业论文.doc...
  19. 长期不上班是种怎样的体验?
  20. 思科N9K交换机配置QOS

热门文章

  1. 米兔机器人 自由模式_成人床下也可以有玩具:MI 小米 米兔积木机器人 开箱体验...
  2. Ubuntu18右上角输入法图标突然消失,而且无法输入中文
  3. 部分互联网公司及通信公司校招时间表及薪资(参考2017)
  4. 腾讯-腾讯云citybase产品白皮书
  5. 树莓派连接人体感应模块HC-SR501
  6. 双臂模式DPVS+RPM安装教程
  7. C. 实验7_3_奇数偶数
  8. Sql语句将两列合并成一列
  9. win7如何解除锁定计算机,Win7电脑键盘数字键被锁了怎么解锁(图文)
  10. 【AI_数学知识】概率论