c++ 实现邮件发送功能

2023-11-01

系列服务器开发


前言

在这里插入图片描述
常用的电子邮件协议有SMTP、POP3、IMAP4,它们都隶属于TCP/IP协议簇,默认状态下,分别通过TCP端口25、110和143建立连接。
SMTP的全称是"SimpleMailTransferProtocol",即简单邮件传输协议
POP全称是邮局协议,负责从邮件服务器中检索电子邮件。
IMAP全称互联网信息访问协议,是一种优于POP的新协议。


一、SMTP是什么?

SMTP是一种提供可靠且有效的电子邮件传输的协议。SMTP是建立在FTP文件传输服务上的一种邮件服务,主要用于系统之间的邮件信息传递,并提供有关来信的通知。SMTP独立于特定的传输子系统,且只需要可靠有序的数据流信道支持,SMTP的重要特性之一是其能跨越网络传输邮件,即“SMTP邮件中继”。使用SMTP,可实现相同网络处理进程之间的邮件传输,也可通过中继器或网关实现某处理进程与其他网络之间的邮件传输。

SMTP是一个相对简单的基于文本的协议。在其之上指定了一条消息的一个或多个接收者(在大多数情况下被确认是存在的),然后消息文本会被传输。可以很简单地通过telnet程序来测试一个SMTP服务器。SMTP使用TCP端口25。Sendmail是最早使用SMTP的邮件传输代理之一。

SMTP协议工作机制
虽然SMTP涉及的是发送电子邮件,但是整理和传送邮件的工作是由不同的服务器完成的,称为:POP(邮局协议)和IMAP(Internet消息访问协议)。通常它工作在两种情况下:一是邮件从客户机传输到服务器;二是从某一个服务器传输到另一个服务器。

SMTP的连接和发送过程
(a)建立TCP连接
(b)客户端发送HELLO命令以标识发件人自己的身份,然后客户端发送MAIL命令;服务器端以OK作为响应,表明准备接收
(c)客户端发送RCPT命令,以标识该电子邮件的计划接收人,可以有多个RCPT行;服务器端则表示是否愿意为收件人接收邮件
(d)协商结束,发送邮件,用命令DATA发送
(e)以.表示结束输入内容一起发送出去
(f)结束此次发送,用QUIT命令退出

二、使用SMTP使用步骤

本文基于sendemail可执行程序,通过进程调用来实现的邮件发送。

sendEmail发送邮件
sendEmail是一个轻量级,命令行的SMTP邮件客户端。如果你需要使用命令行发送邮件,那么sendEmail是非常完美的选择:使用简单并且功能强大。

1.下载编译,命令行使用

sendEmail 官网:http://caspian.dotconf.net/menu/Software/SendEmail/
sendEmail 下载:sendEmail-v1.56.tar.gz

1、sendEmail 下载
sendEmail-v1.56.tar.gz

2、解压、安装
tar zxvf sendEmail-v1.56.tar.gz
cd sendEmail-v1.56
cp sendEmail /usr/local/bin/


可以通过查看帮助
sendEmail --help

简单发送邮件案例
sendEmail -f ttlsafrom@163.com -t 12312311231@qq.com -s smtp.163.com -u "主题测试" -o message-content-type=html -o message-charset=utf-8 -o tls=no -xu ttlsafrom@163.com -xp HUKINXIAW -m "test"

Feb 15 09:22:15 localhost sendEmail[3536]: Email was sent successfully!
参数解释:
sendEmail      主程序
-f ttlsafrom@163.com          发件人邮箱
-s smtp.163.com               发件人邮箱的smtp服务器
-u "我是邮件主题"                邮件的标题
-o message-content-type=html   邮件内容的格式,html表示它是html格式
-o message-charset=utf8        邮件内容编码
-xu ttlsafrom@163.com          发件人邮箱的用户名
-xp HUKINXIAW                  发件人邮箱密码
-m "我是邮件内容"                邮件的具体内容
-t 12312311231@163.com         收件箱
-cc                            表示抄送
-bcc                           表示暗抄送

如何获取客户端授权码即xp后面的参数:
1)在web端登录邮箱后,进入设置—>邮箱设置—>POP3/SMTP/IMAP设置页面
如果您还未开启授权码,请了解开启步骤。请参考(https://note.youdao.com/ynoteshare/index.html?id=f9fef46114fb922b45460f4f55d96853&type=note&_time=1664544625625)
如果您已经开启过授权码,但是忘记了之前的授权码是多少。
那您可以新增一个授权码,并且不会影响之前已经设置好的客户端。(最多可以新增5个授权码,任意一个授权码都可以登录使用任意客户端)
2)点击新增授权码,按照提示扫码发送短信,或者手动发送短信即可。然后就可以看到您新的授权码了。

2.代码实现


#pragma once
#include <string>

class MailParam
{
public:
     std::string _from_name;
     std::string _from;
     std::string _to_name1;
     std::string _to_email1;
     std::string _server;
     std::string _server_token;     
};
class MailImpl
{
public:    
     MailImpl();
     ~MailImpl();
     void init(MailParam &param);      
     bool sendMailByExe(const std::string &title,const std::string &content);
private:
     std::string _from_name;
     std::string _from;
     std::string _to_name1;
     std::string _to_email1;
     std::string _server;
     std::string _server_token;
private:
     MailImpl(const MailImpl&)=delete;
     MailImpl& operator=(const MailImpl&)=delete;   
};


#include "sendmail.h"
#include <iostream>

MailImpl::MailImpl()
{
}

MailImpl::~MailImpl()
{
}

void MailImpl::init(MailParam &param) 
{
    _from_name = param._from_name;
    _from = param._from;
    _to_name1 = param._to_name1;
    _to_email1 = param._to_email1;
    _server = param._server;
    _server_token = param._server_token;     
}


bool MailImpl::sendMailByExe(const std::string &title,const std::string &content)
{
    bool result = true;
    do{
        const auto from_name = _from_name;
        const auto from =  _from;
        const auto to_name1 =_to_name1;
        const auto to_email1 = _to_email1;
        const auto server = _server;
        const auto server_token = _server_token;
        
        //check if configured
        if(from_name.length() ==0 ||
            from.length() ==0 ||
            server.length() ==0 ||
            server_token.length() ==0
        ){
            std::cout<< "email configure no has congiure info"<<std::endl;
            result = false;
            break;             
        }
        if( (to_name1.length() ==0 || to_email1.length() == 0) ){
            std::cout<< "email configure no has receiver"<<std::endl;
            result = false;
            break;             
        }

        //./sendEmail -f ******@163.com -t ***@qq.com 
        //-s smtp.163.com -u "new msg need to notify" 
        //-o message-content-type=html -o message-charset=utf-8 -o tls=no 
        //-xu *****@163.com -xp HUKINXIAWCHAHARJ -m "test"
        //-a /opt/vplatform/attachment.txt 
        
        char cmd[1024] = {0};
        std::string path =  "/opt/app/sendEmail";
        std::string subject = title;
        std::string format = "-o message-content-type=html -o message-charset=utf-8 -o tls=no";
        
        int ret = 0;
        if(to_name1.length()>0 && to_email1.length()>0){
            std::string body = from_name + ":" + to_name1 + "," + content;
            sprintf(cmd, "%s -f %s -t %s -s %s -u %s %s -xu %s -xp %s -m %s"
            ,path.c_str(),from.c_str(),to_email1.c_str()
            ,server.c_str(),subject.c_str(),format.c_str()
            ,from.c_str(),server_token.c_str(),body.c_str());
            ret = system(cmd);
            std::cout<< "call email send result "<< ret << std::endl;
        }
        if(ret != 0){
            result = false;
            break;
        }
    }while(false);

    return result;
}


总结

通过本文的学习,应该多smtp协议发送邮件有个大致的了解,本文是基于c++实现的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++ 实现邮件发送功能 的相关文章

  • 为什么这个 Web api 控制器不并发?

    我有一个 Web API 控制器 里面有以下方法 public string Tester Thread Sleep 2000 return OK 当我调用它 10 次 使用 Fiddler 时 我预计所有 10 次调用都会在大约 2 秒后
  • C# 方法重载决策不选择具体的泛型覆盖

    这个完整的 C 程序说明了这个问题 public abstract class Executor
  • 未找到 Boost 库,但编译正常

    我正在尝试在 C 中使用 boost 的文件系统 使用时看起来编译没问题 c c Analyse c o Analyse o g W Wall L usr local lib lboost filesystem lboost system
  • 循环遍历 C 结构中的元素以提取单个元素的值和数据类型

    我有一个要求 我有一个 C 语言的大结构 由大约 30 多个不同数据类型的不同元素组成 typedef struct type1 element1 type2 element2 type3 element3 type2 element4 1
  • 如何将 SOLID 原则应用到现有项目中

    我对这个问题的主观性表示歉意 但我有点卡住了 我希望之前处理过这个问题的人能够提供一些指导和建议 我有 现在已经成为 一个用 C 2 0 编写的非常大的 RESTful API 项目 并且我的一些类已经变得巨大 我的主要 API 类就是一个
  • RestSharp获取序列化输出

    我正在寻找一种方法来访问 AddBody 调用的序列化结果 我正在使用内置的 RestSharp 序列化器 例子 class Foo public string FooField void SendRecord var f new Foo
  • 在 C# 中,如何根据在 gridview 行中单击的按钮引用特定产品记录

    我有一个显示产品网格视图的页面 该表内有一列 其中有一个名为 详细信息 的超链接 我想这样做 以便如果用户单击该特定产品的详细信息单元格 将打开一个新页面 提供有关该产品的更多信息 我不确定如何确定哪个Product记录链接的详细信息以及我
  • C++中判断unicode字符是全角还是半角

    我正在编写一个终端 控制台 应用程序 该应用程序应该包装任意 unicode 文本 终端通常使用等宽 固定宽度 字体 因此要换行文本 只需计算字符数并观察单词是否适合一行并采取相应的操作 问题是 Unicode 表中的全角字符在终端中占用了
  • 在 C# 中检查 PowerShell 执行策略的最佳方法是什么?

    当你跑步时Get ExecutionPolicy在 PowerShell 中 它得到有效的执行政策 https learn microsoft com en us powershell module microsoft powershell
  • 从网页运行 ClickOnce 应用程序,无需用户操作

    我们有一个基于 Java 的 Web 应用程序以及用 C 编写的相同应用程序 如果 java 检查器发现客户端计算机上没有安装 Java 则应该运行该应用程序 这个想法是运行 C 单击一次 http en wikipedia org wik
  • 如何递归取消引用指针(C++03)?

    我正在尝试在 C 中递归地取消引用指针 如果传递一个对象 那就是not一个指针 这包括智能指针 我只想返回对象本身 如果可能的话通过引用返回 我有这个代码 template
  • 不可变类与结构

    以下是类与 C 中的结构的唯一区别 如果我错了 请纠正我 类变量是引用 而结构变量是值 因此在赋值和参数传递中复制结构的整个值 类变量是存储在堆栈上的指针 指向堆上的内存 而结构变量作为值存储在堆上 假设我有一个不可变的结构 该结构的字段一
  • memcpy/memmove 到联合成员,这是否设置“活动”成员?

    重要说明 一些评论者似乎认为我是从工会抄袭的 仔细看memcpy 它从普通旧地址复制uint32 t 它不包含在联合中 另外 我正在复制 通过memcpy 到工会的特定成员 u a16 or u x in a union 不直接到整个联盟本
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • 模板类的模板构造函数的 C++ 显式模板特化

    我有一个像这样的课程 template
  • 如何解压 msgpack 文件?

    我正在将 msgpack 编码的数据写入文件 在编写时 我只是使用 C API 的 fbuffer 如 我为示例删除了所有错误处理 FILE fp fopen filename ab msgpack packer pk msgpack pa
  • 将 Lambda 表达式树与 IEnumerable 结合使用

    我一直在尝试了解有关使用 Lamba 表达式树的更多信息 因此我创建了一个简单的示例 这是代码 如果作为 C 程序粘贴到 LINQPad 中 它可以工作 void Main IEnumerable
  • Visual Studio 2015 - Web 项目上缺少共享项目参考选项卡

    我从 MSDN 订阅升级到 Visual Studio 2015 因为我非常兴奋地阅读有关共享项目的信息 当我们想要做的只是重用代码时 不再需要在依赖项中管理 21382 个 nuget 包 所以我构建了一个测试共享项目 其中包含一些代码
  • 了解 Lambda 表达式和委托 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我已经尝试解决这个问题很长一段时间了 阅读在线博客和文章 但到目前为止还没有成功 什么是代表 什么是 Lambda 表达式 两者的优点
  • 无法将字符串文字分配给装箱的 std::string 向量

    这是我的类型系统的简化版本 include

随机推荐

  • matlab设计FIR滤波器

    方法1 通过fir1 函数进行设计 B fir1 N Wn 设计FIR低通滤波器 返回的滤波器参数保存在长度为N 1的数组B中 Wn为归一化截止频率 范围为0 1 截止频率用于区分过渡带和阻带 1处对应的是采样频率的一半 滤波器系数B是实的
  • Apifox接口自动化测试方法

    1 新建测试用例 2 输入名称 分组 优先级后点击确定 3 点击测试用例名称或者详情 4 添加步骤 两个方式都可以 5 选择要测试的接口后选择模式 复制 绑定 复制 复制一份数据 和原来的接口相互独立 互不影响 绑定 两边改动相护实时同步
  • 深度学习之MNIST数据集

    深度学习是以数据为驱动的技术 在使用深度学习进行科研或者工作当中 都离不开数据集 文章目录 前言 一 MNIST数据集是什么 二 使用步骤 1 下载数据集 2 完整代码 总结 前言 还有一些 如人脸数据集 地球信息的数据集 数据集来源有一些
  • docker日志设置定期清理

    docker日志设置定期清理 1 日志的查看docker logs 具体的参数 请查看help命令 docker logs help 2 清除日志文件docker日志的存储位置 var lib docker containers lt 容器
  • Redis学习笔记(一):CentOS7安装Redis4

    CentOS版本 CentOS Linux release 7 5 1804 Core Redis版本 Redis server v 4 0 9 1 安装 1 1下载 去官网找到下载地址https redis io download 右键复
  • Mysql优化5-选择合适的存储引擎

    一 如何选择存储引擎 myisam 存储 如果对事务要求不高 同时以查询新增为主的 主要考虑使用此引擎 比如bbs的发帖表 回复表 INNODB 存储 对事务要求比较高 保存的数据都是重要数据 比如订单表等等 Memory 存储 数据变化频
  • 人工智能-遗传算法

    一 简介 遗传算法 Genetic Algorithm GA 借鉴了生物学遗传进化的思想 模拟了种群进化过程中经历的繁殖 杂交 基因变异的自然选择和自然变异的过程 遗传算法是一种高效的进行全局搜索和优化的方法 能在 进化 过程中自适应获得适
  • CondaHTTPError: HTTP 000 CONNECTION FAILED for url

    该博客为 Ubuntu 相关 系列博客的第七篇 该系列博客主要对Ubuntu安装各种软件或者库进行一个记录 方便重装系统后快速恢复工作 在学习大数定理和中心极限定理时 发现几个程序 但是运行不了 anaconda没有安装matplotlib
  • Python实现栈

    Python实现栈 关于栈的介绍 请参考 https blog csdn net weixin 43790276 article details 104033337 栈的数据存储结构可以是顺序表 也可以是链表 本篇使用 Python 来分别
  • 使用 Python 和可视化编程控制树莓派机械臂myCobot

    myCobot 280 Pi 是一款 6 自由度多功能桌面机械臂 它由大象机器人研发 使用 Raspberry Pi 作为主控制器 该机器人结构紧凑 运行稳定 非常适合新手入门 它还可以使用多种语言进行编程 简单易用 功能丰富 适合那些有兴
  • MySQL用户权限(Host,User,Password)管理(mysql.user)

    1 新增用户 注 mysql数据库下user表中 Host和User为两个主键列 primary key 已经各版本下非空未设置默认字段 登录后 切换db mysql gt use mysql Reading table informati
  • GIt命令

    获取git授权密钥 ssh keygen t rsa C 换成自己邮箱 然后cat ssh id rsa pub 把控制台输出的内容复制 到gitee github gitlab等网页建立ssh密钥 git init 建立仓库 检出代码 1
  • alibaba开源框架easyexcel文件导出

    alibaba开源框架easyexcel使用 官方文档 https easyexcel opensource alibaba com docs current quickstart write 1 下载 Getter Setter Equa
  • 完整计算机组成系统,计算机组成原理与完整系统结构.doc

    计算机组成原理与完整系统结构 西安财经学院信息学院 计算机组成原理与系统结构 实验报告 实验名称 运算器实验 通用寄存器实验 移位寄存器实验 实验室实验楼418 实验日期 2012 11 27 2012 11 29 2012 12 4 一
  • 谁该来负责拥塞控制

    寻找一种 host 公平而非 packet 公平的方法 有趣的是 CSMA CD 网络就体现了这种方法 端到端拥塞控制算法 cca 准不准先不论 仅说让它们运行 被控制的流至少要持续 2 个 RTT 一条持续传输的流是多数 cca 的约束
  • Android 自定义图片裁剪框功能

    Android自定义图片裁剪框功能 大体的功能如上gif所示 最后蓝色裁剪框中的矩形图片区域可以进行截取并返回一个Bitmap对象 整个裁剪功能由两个自定义的View组件完成 首先是图片显示控件DragScaleView 主要完成图片的双指
  • 访问swagger-ui.html 404报错一秒解决

    访问swagger ui html 404报错一秒解决 搞了好半天终于找到了 1 首先和你spring boot是什么版本根本没关系 spring boot的版本完全可以用最新的 我的是2 6 6 2 主要是swagger的版本不能用3 0
  • vue首屏加载动画

    样式style
  • Codeforces Round #328 (Div. 2)(A B C D)

    Codeforces Round 328 Div 2 tags Codeforces 难得题目不难 结果比赛的时候C题差一分钟没交上去 不然怎么着都能涨个百来分啊 T T Codeforces Round 328 Div 2 A PawnC
  • c++ 实现邮件发送功能

    系列服务器开发 文章目录 系列服务器开发 前言 一 SMTP是什么 二 使用SMTP使用步骤 1 下载编译 命令行使用 2 代码实现 总结 前言 常用的电子邮件协议有SMTP POP3 IMAP4 它们都隶属于TCP IP协议簇 默认状态下