邮件发送协议 SMTP 问题排查

本文讲述了在C++项目中使用SMTP协议发送邮件遇到的问题及解决过程,包括从WireShark抓包分析邮件交互流程,解决163邮箱与钉钉邮箱的认证差异,以及修复C++发送邮件只能成功一次的故障。关键在于理解和正确构造邮件头部信息,特别是Message-ID字段的设置。
摘要由CSDN通过智能技术生成

原文地址 微信公众号

项目中需要用到 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 是个很好的工具,善于使用它分析网络传输协议,抓包能够说明一切,让问题一目了然。  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值