一次邮件发送协议SMTP问题排查

2024-05-15 09:38

本文主要是介绍一次邮件发送协议SMTP问题排查,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

项目中需要用到smtp协议来发送邮件告警,后端的技术栈主要是Java和C++,Java项目里直接在网上找的现成的类完美实现,163邮箱,腾讯邮箱和阿里邮箱均测试通过,不幸的是C++的项目也需要使用smtp协议来发送邮件,惯例先度娘,CSDN逛了一圈,例程也不少但是每个下边留言都有这样和那样的问题,copy过来直接运行,163邮箱完美测试通过,我们用的钉钉全家桶,测试钉钉邮箱时发现不能发送邮件,认证都有问题。好吧,还是先老老实实的学习遍SMTP协议吧

 

WireShark抓取一次完整的邮件交互过程(关闭ssl):

流程如下:

第一步:发送EHLO指令,申明身份,表示自己身份需要验证,注意这部分需要通过Telnet验证一下,是user@example.com还是user,否则会出错。

第二步:发送AUTH LOGIN指令,登录邮箱,这一部分一般要用base64加密。

第三步:发送MAIL指令,这个命令用来开始传送邮件,它的后面跟随发件方邮件地址(返回邮件地址)。它也用来当邮件无法送达时,发送失败通知。为保证邮件的成功发送,发件方的地址应是被对方或中间转发方同意接受的。这个命令会清空有关的缓冲区,为新的邮件做准备。

第四步:发送RCPT指令,这个命令告诉收件方收件人的邮箱。当有多个收件人时,需要多次使用该命令RCPT TO,每次只能指明一个人。如果接收方服务器不同意转发这个地址的邮件,它必须报550错误代码通知发件方。如果服务器同意转发,它要更改邮件发送路径,把最开始的目的地(该服务器)换成下一个服务器。

第五步:发送DATA指令,收件方把该命令之后的数据作为发送的数据。数据被加入数据缓冲区中,以单独一行是”.”的行结束数据。结束行对于接收方同时意味立即开始缓冲区内的数据传送,传送结束后清空缓冲区。如果传送接受,接收方回复OK。

第六步:发送QUIT指令,SMTP要求接收放必须回答OK,然后中断传输;在收到这个命令并回答OK前,收件方不得中断连接,即使传输出现错误。发件方在发出这个命令并收到OK答复前,也不得中断连接。

 

分析:

掌握了基本的流程和抓取了数据包,只要C++也按照这种数据格式发送即可,认证不通过,首先怀疑用户名和密码传输的数据有问题,抓取C++发送的数据包,果然User数据BASE64的值不一样,Pass的值是一样的,解Base64后发现一个是user@example.com,一个是user,显然问题出在这,163邮箱要求是user,钉钉邮箱要求是user@example.com,改正后认证成功,接着发送邮件也OK,完事大吉,然而。。。一周后项目完成交给测试人员,告诉我告警邮件发不过来,怎么可能,运行工程,打脸了,只能发送一次,接着就发不出去邮件了,难道钉钉给屏蔽了,Java测试了下,没问题,好吧,继续抓包,认证是没问题的,发送过去就是收不到。

 

Java发送抓取的DATA数据部分如下:

C++发送抓取的DATA数据部分如下:

很明显差别太大了,From,To的格式不对,Content-Type也不对,但是明显差别的是少了Message-ID字段,所以重点先分析Message-ID,又抓取了多次比对后每次的Message-ID都是不同的,怀疑这给C++只能发送一次成功有关系,C++中增加了如下代码:

    email = "From: ";email += user;email += "\r\n";email += "To: ";email += targetAddr;email += "\r\n";//新增email += "Message-ID: ";email += “1”;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";

运行果然成功了,但是在运行又不成功了,把Message-ID值改为2又成功了,问题果然出在这里,大功告成,最终Message-ID改为:机器名+随机数。

总结:

        WireShark是个很好的工具,善于使用它分析网络传输协议,抓包能够说明一切,让问题一目了然。

这篇关于一次邮件发送协议SMTP问题排查的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991470

相关文章

Vue3绑定props默认值问题

《Vue3绑定props默认值问题》使用Vue3的defineProps配合TypeScript的interface定义props类型,并通过withDefaults设置默认值,使组件能安全访问传入的... 目录前言步骤步骤1:使用 defineProps 定义 Props步骤2:设置默认值总结前言使用T

HTTP 与 SpringBoot 参数提交与接收协议方式

《HTTP与SpringBoot参数提交与接收协议方式》HTTP参数提交方式包括URL查询、表单、JSON/XML、路径变量、头部、Cookie、GraphQL、WebSocket和SSE,依据... 目录HTTP 协议支持多种参数提交方式,主要取决于请求方法(Method)和内容类型(Content-Ty

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

解决升级JDK报错:module java.base does not“opens java.lang.reflect“to unnamed module问题

《解决升级JDK报错:modulejava.basedoesnot“opensjava.lang.reflect“tounnamedmodule问题》SpringBoot启动错误源于Jav... 目录问题描述原因分析解决方案总结问题描述启动sprintboot时报以下错误原因分析编程异js常是由Ja

基于Python实现自动化邮件发送系统的完整指南

《基于Python实现自动化邮件发送系统的完整指南》在现代软件开发和自动化流程中,邮件通知是一个常见且实用的功能,无论是用于发送报告、告警信息还是用户提醒,通过Python实现自动化的邮件发送功能都能... 目录一、前言:二、项目概述三、配置文件 `.env` 解析四、代码结构解析1. 导入模块2. 加载环

使用Python的requests库来发送HTTP请求的操作指南

《使用Python的requests库来发送HTTP请求的操作指南》使用Python的requests库发送HTTP请求是非常简单和直观的,requests库提供了丰富的API,可以发送各种类型的HT... 目录前言1. 安装 requests 库2. 发送 GET 请求3. 发送 POST 请求4. 发送

MySQL 表空却 ibd 文件过大的问题及解决方法

《MySQL表空却ibd文件过大的问题及解决方法》本文给大家介绍MySQL表空却ibd文件过大的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录一、问题背景:表空却 “吃满” 磁盘的怪事二、问题复现:一步步编程还原异常场景1. 准备测试源表与数据

解决Nginx启动报错Job for nginx.service failed because the control process exited with error code问题

《解决Nginx启动报错Jobfornginx.servicefailedbecausethecontrolprocessexitedwitherrorcode问题》Nginx启... 目录一、报错如下二、解决原因三、解决方式总结一、报错如下Job for nginx.service failed bec

SysMain服务可以关吗? 解决SysMain服务导致的高CPU使用率问题

《SysMain服务可以关吗?解决SysMain服务导致的高CPU使用率问题》SysMain服务是超级预读取,该服务会记录您打开应用程序的模式,并预先将它们加载到内存中以节省时间,但它可能占用大量... 在使用电脑的过程中,CPU使用率居高不下是许多用户都遇到过的问题,其中名为SysMain的服务往往是罪魁

MySQ中出现幻读问题的解决过程

《MySQ中出现幻读问题的解决过程》文章解析MySQLInnoDB通过MVCC与间隙锁机制在可重复读隔离级别下解决幻读,确保事务一致性,同时指出性能影响及乐观锁等替代方案,帮助开发者优化数据库应用... 目录一、幻读的准确定义与核心特征幻读 vs 不可重复读二、mysql隔离级别深度解析各隔离级别的实现差异