SMTP协议解析及C/C++代码实现
SMTP 是一种应用层协议。 要发送邮件的客户端打开到 SMTP 服务器的 TCP 连接,然后通过该连接发送邮件。 SMTP 服务器是一种永远在线的侦听模式。 一旦它侦听来自任何客户端的 TCP 连接,SMTP 进程就会通过端口 25 启动连接。成功建立 TCP 连接后,客户端进程会立即发送邮件。
理解SMTP协议
SMTP 协议背后的主要思想是在服务器之间建立通信指南。 服务器识别自己并宣布正在进行的通信类型。 服务器还处理错误,例如不正确的电子邮件地址。 例如,如果收件人地址不正确,则收件人服务器会以错误消息进行响应。
SMTP是发送电子邮件的协议。它使用的是TCP的25号端口。SMTP建立一个TCP连接以后,在这个连接上进行控制和应答以及数据的发送。客户端以文本的形式发出请求,服务端返回一个3位数字的应答。每个指令和应答的最后都必须追加换行指令。
SMTP通信模型
SMTP基于客户/服务端模式,需要TCP提供可靠的数据流。SMTP服务器默认监听TCP 25端口,规范SMTP协议的最新RFC文档RFC 5321,它淘汰了RFC 2821。
SMTP是一个相对简单的基于文本的协议。MIME规范使得二进制文件能够通过SMTP来传输。目前大多数SMTP软件实现都支持8位MIME扩展,从而使二进制文件的传输变得几乎和纯文本一样简单。
当SMTP客户端有邮件要传送时,与SMTP服务器建立一个双向的传输通道。SMTP客户端负责邮件信息传送到一个或多个SMTP服务器,如果失败则给出报告。
SMTP服务器可能最终目的地,也可能是中间的中继或者网关。SMTP命令由SMTP客户端产生,发送到SMTP服务器。SMTP响应由SMTP服务器发送给SMTP客户端,对命令做出回应。
也就是说,邮件传输者可以出现在起始SMTP发送方与最终的SMTP接收方之间建立的连接上,或者出现在通过中间系统的一系列跃点上。一旦传输通道建立和初始握手完成,SMTP客户端正常初始化邮件事务。这样的事务包括一系列命令,以定义邮件的发送方和目的地,以邮件内容本身的传递。
发送者发送 MAIL 命令来指定发送者的邮件,如果接受者接收这个邮件,就回复 OK ,接着发送者发送 RCPT命令来指定接收者的邮箱,如果被接收同样回复OK,如果不接受则拒绝(不会终止整个通话)。接收者邮箱确定后,发送者用DATA命令指示要发送数据,并用一个 . 结束发送。如果数据被接收,会收到OK ,然后用QUIT结束会话。
SMTP命令
EHLO命令:
参数为SMTP客户端全称域名 。SMTP客户端问候SMTP服务器,提供自己的名称或地址,以向服务器标识自己的身份。客户端应当通过EHLO命令来发起SMTP服务,如果服务器支持SMTP服务扩展,将给出成功、失败或者错误回应;
如果不支持SMTP扩展,服务器将产生一个错误响应。
MAIL命令:
- MAIL < SP > FROM:< reverse-path > < CRLF >
MAIL命令,包含发送者邮箱( 是空格,是回车换行)
反向路径是MAIL命令的参数。该路径便于服务返回错误信息,不仅包括邮箱,而且包括主机和源邮件的反向路由,其中的第1个主机就是发送此命令的主机。
参数为发件人邮件地址。用来发起邮件事务,让邮件数据传送到SMTP服务器,SMTP服务器依次将邮件数据投递到一个或者多个邮箱,或者传送到另一个系统。
RCPT命令:
- RCPT < SP > TO:< forward-path > < CRLF >
转发路径是RCPT命令的参数。该路径不仅包括邮件,而且包括主机和目的邮箱的路由表,在其中的第1个主机就是接收命令的主机。
参数为收件人邮件地址。用来标识邮件数据的收件人,可以指定多个收件人。
DATA命令:
- DATA < CRLF >
参数为邮件主机(正文)。将该命令之后的数据作为要发送的数据。数据加入到缓存区中,以单独一行是< CRLF >.< CRLF >的行结束数据。结束行对于接收方同时意味立即开始缓冲区的数据传送,传送结束后清空缓冲区。如果传送被接收,服务器回复OK。
RSET命令:
指定当前邮件事务终止。所存储的收件人、发件人和待发送的数据都必须清除,接收方必须回复OK。
VRFY命令:
参数为收件人名称。用于验证指定的用户或邮箱是否存在。
EXPN命令:
参数为邮递清单。验证给定的邮递清单是否存在,如果存在则返回其成员。
HELP命令:
- HELP [SP String] < CRLF >
参数命令名。提供给定命令的帮助信息。
QUIT命令:
- QUIT < CRLF >
指定接收方回复OK,关闭传输通道。
SMTP响应
SMTP命令的响应用于确保邮件传输过程中的请求与操作的同步,让SMTP客户端总是知道SMTP服务器的状态。每个命令必须正好产生一个响应。
与FTP响应类似,SMTP响应也由三个数字组成,后面跟着一些文本。数字用来自动判断当前的状态,文本内容提供给用户。
/* The following were copied from RFC 2821 */
static const value_string response_codes_vs[] = {{ 211, "System status, or system help reply" },{ 214, "Help message" },{ 220, "<domain> Service ready" },{ 221, "<domain> Service closing transmission channel" },{ 235, "Authentication successful" },{ 250, "Requested mail action okay, completed" },{ 251, "User not local; will forward to <forward-path>" },{ 252, "Cannot VRFY user, but will accept message and attempt delivery" },{ 334, "AUTH input" },{ 354, "Start mail input; end with <CRLF>.<CRLF>" },{ 421, "<domain> Service not available, closing transmission channel" },{ 432, "A password transition is needed" },{ 450, "Requested mail action not taken: mailbox unavailable" },{ 451, "Requested action aborted: local error in processing" },{ 452, "Requested action not taken: insufficient system storage" },{ 454, "Temporary authentication failed" },{ 500, "Syntax error, command unrecognized" },{ 501, "Syntax error in parameters or arguments" },{ 502, "Command not implemented" },{ 503, "Bad sequence of commands" },{ 504, "Command parameter not implemented" },{ 530, "Authentication required" },{ 534, "Authentication mechanism is too weak" },{ 535, "Authentication credentials invalid" },{ 538, "Encryption required for requested authentication mechanism" },{ 550, "Requested action not taken: mailbox unavailable" },{ 551, "User not local; please try <forward-path>" },{ 552, "Requested mail action aborted: exceeded storage allocation" },{ 553, "Requested action not taken: mailbox name not allowed" },{ 554, "Transaction failed" },{ 0, NULL }
};
SMTP通信过程
SMTP 消息传输可以描述为客户端和服务器之间的对话。必须在它们之间交换一些命令,以便将消息从发送者传递给接收者。电子邮件传输的典型过程如下所示。
完整的SMTP通信过程包括连接建立、邮件传送、连接释放3个阶段,每个阶段都涉及一组命令和响应。
SMTP解析解析代码实现
int main(int argc, char* argv[])
{char errbuf[1024];pcap_t *desc = 0;char *filename = argv[1];if (argc != 2){printf("usage: ./dissect_smtp [pcap file]\n");return -1;}printf("ProcessFile: process file: %s\n", filename);if ((desc = pcap_open_offline(filename, errbuf)) == NULL){ printf("pcap_open_offline: %s error!\n", filename);return -1; } pcap_loop(desc, pkt_number, (pcap_handler)ace_pcap_hand, NULL);pcap_close(desc);return 0;
}
编译运行:
使用SMTP的好处
以下是 SMTP 协议的一些优点。
- 1、SMTP 通过电子邮件在特定网络中的多台计算机之间提供最简单的通信形式。
- 2、SMTP 由一个简单的平台组成,可以轻松快速地发送电子邮件。
- 3、SMTP 为外发电子邮件提供可靠性,因此如果邮件未成功发送,则 SMTP服务器会尝试重新发送相同的邮件,直到邮件成功发送为止。
- 4、SMTP 有助于拥有一个承诺的服务器来管理组织中的外发电子邮件。
- 5、连接到 SMTP 非常简单。 此外,它提供了一个简单的安装。
- 6、SMTP 连接没有限制,可用于连接到任何系统。我们所要做的就是合并 SMTP 信息。
- 7、它不包括我们最终的任何发展。
总结
电子邮件正在成为当今互联网上最有价值的服务之一。 大多数 Internet 系统使用 SMTP 作为一种将邮件从一个用户传输到另一个用户的方法。 SMTP 是一种推送协议,用于发送邮件,而 POP(邮局协议)或 IMAP(互联网消息访问协议)用于在接收方检索这些电子邮件。
欢迎关注微信公众号【程序猿编码】,需要SMTP 完整源码的添加本人微信号(c17865354792)
参考:RFC 5321
SMTP协议解析及C/C++代码实现相关推荐
- suricata smtp协议解析源码注释一
这一篇仅对smtp协议解析的思路做整体描述,所有内容均是按照自己理解所写,肯定有理解不正确的地方,请指出,谢谢. 一.Suricata解析smtp协议整体思路 Smtp协议解析模块根据客户端与邮件服务 ...
- TFTP协议解析及C/C++代码实现
TFTP 用于以非常简单的方式传输文件.与其他文件传输协议(如:FTP 或 HTTP)相比,TFTP 更简单,代码量也更小,因此更易于实现. 通常,TFTP 使用 UDP 作为其传输协议.众所周知的 ...
- MongoDB数据库协议解析及C/C++代码实现
MongoDB 是由 MongoDB Inc 开发的 NoSQL 数据库,它是无模式的.它是使用 c++ 和 javascript 设计和创建的,允许更高的连接性. MongoDB 是一个 NoSQL ...
- Oracle(TNS)协议解析及C/C++代码解析
Oracle客户端和服务器使用TNS作为其数据交换协议. 它提供了一种对用户透明的层, 为不同的工业标准协议提供统一, 通用的接口. 基本上是TNS以这样的方式指定了端口1521上的会话是" ...
- python pop3_Python使用POP3和SMTP协议收发邮件的示例代码
先来了解一下收/发邮件有哪些协议: SMTP协议 SMTP(Simple Mail Transfer Protocol),即简单邮件传输协议.相当于中转站,将邮件发送到客户端. POP3协议 POP3 ...
- UDT协议解析及C/C++代码实现
基于 UDP 的协议 (UDT) 是一种高性能数据传输协议.用于广域高速网络上的分布式数据密集型应用程序. UDT 使用 UDP 传输具有自己的可靠性控制和拥塞控制机制的批量数据. 新协议可以以比 T ...
- 服务器smtp协议,SMTP协议解析
http://home.eeworld.com.cn/my/space-uid-361439-blogid-360809.html 2016在写这篇帖子之前发表过一篇讨论SMTP实现的帖子,大伙的反馈 ...
- MySQL协议解析及C/C++代码实现
MySQL 常用于许多知名网站,包括 Facebook.Google.Twitter 和 YouTube等等.它于 1995 年首次发布.MySQL 是用 C 和 C++ 编写的. MySQL 适用于 ...
- 英雄远征Erlang源码分析(5)-协议解析与玩家登录处理
现在,客户端与服务器的连接算是正式建立了,此时用户需要做的第一件事就是登陆.不过在登录之前,我们要先研究下前后端通信的协议. 客户端与服务端建立连接后,通过提前制定好的协议进行交互.具体的协议文档在d ...
最新文章
- mysql数据库语句q_mysql数据库命令大全,mysql基本命令大全
- 《幸福就在你身边》第八课、幸福比成功更重要【哈佛大学幸福课精华】
- ECharts问题--柱状图和折线图中xAxis.data为空时报错问题解决
- 2020-12-11 python查看pytorch版本
- python中进制chr_python中的chr() 如何返回字符?
- 01_GIT基础、安装
- 滑动窗口最大值--单调队列
- sonar java_修复Sonar中常见的Java安全代码冲突
- 基于spring-redis发布订阅模式的实现
- spring boot(十五)spring boot+thymeleaf+jpa增删改查示例
- R语言伴随矩阵的计算
- 基于大数据的资金流量分析:思路与应用前景设想
- 关于反转的总结(C/C++)
- linux ip_conntrack_max,解?Linux NAT ip_conntrack: table full的方法
- Grid ++ MIME 类型配置 载入报表数据,检查此URL及其数据,错误提示 网络服务器响应不成功
- android 调用短信,android中可以通过两种方式调用接口发送短信
- linux运维要经常加班吗,请好好善待你身边的Linux运维工程师,因为他们…
- Tomcat配置完成后打不开localhost网页解决方法
- HAL库教程3:引脚输入检测
- 如何做一个优雅的Pod