一次郵件傳送協議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 += "
";
email += "To: ";
email += targetAddr;
email += "
";
//新增
email += "Message-ID: ";
email += “1”;
email += "
";
email += "Subject: ";
email += title;
email += "
";
email += "MIME-Version: 1.0";
email += "
";
email += "Content-Type: multipart/mixed;boundary=qwertyuiop";
email += "
";
email += "
";
執行果然成功了,但是在執行又不成功了,把Message-ID值改為2又成功了,問題果然出在這裡,大功告成,最終Message-ID改為:機器名+隨機數。
總結:
WireShark是個很好的工具,善於使用它分析網路傳輸協議,抓包能夠說明一切,讓問題一目瞭然。
原文釋出時間為:2018-10-19
本文作者:蝸牛
本文來自雲棲社群合作伙伴“Java架構師之路”,瞭解相關資訊可以關注“Java架構師之路”。
相關文章
- SMTP協議解讀以及如何使用SMTP協議傳送電子郵件協議
- Jmeter——SMTP Sampler傳送郵件JMeter
- Python SMTP傳送郵件Python
- 配置mail使用SMTP傳送郵件AI
- Python使用SMTP傳送郵件Python
- 利用UTL_SMTP傳送郵件
- 電子郵件協議及GO傳送QQ郵件協議Go
- 郵件開發:SMTP協議詳解協議
- 一次性解決python smtp 傳送outlook郵件,163郵件,qq郵件等等.Python
- cisco pix防火牆接管smtp的問題,Outlook express不能傳送郵件防火牆Express
- 在Python如何使用SMTP傳送郵件Python
- 傳送郵件出現問題
- python實現基於smtp傳送郵件Python
- WPForms和 WP Mail SMTP – 最好的WordPress SMTP郵件傳送外掛ORMAI
- 【python】用SMTP模組傳送帶附件的郵件Python
- ThinkPHP_phpmailer使用外部認證SMTP傳送郵件PHPAI
- 郵件傳送時的亂碼問題
- SMTP協議初探(1)----dos下telnet命令發郵件協議
- SMTP操作使用詳解並透過python進行smtp郵件傳送示例Python
- 軟體測試學習教程——Python SMTP傳送郵件Python
- Linux 上使用 Gmail SMTP 伺服器傳送郵件通知LinuxAI伺服器
- mailx 或telnet 使用指定SMTP伺服器傳送郵件AI伺服器
- 郵件傳送
- 傳送郵件
- foxmail能收郵件,但是無法傳送郵件的問題AI
- Python使用POP3和SMTP協議收發郵件Python協議
- laravel傳送啟用郵件的思路和問題Laravel
- SpringBoot整合Mail傳送郵件&傳送模板郵件Spring BootAI
- Laravel 傳送郵件Laravel
- PHP傳送郵件PHP
- Django——郵件傳送Django
- java郵件傳送Java
- Laravel傳送郵件Laravel
- gmail傳送郵件AI
- Oracle郵件傳送Oracle
- java傳送郵件Java
- Powershell郵件傳送
- thinkphp 郵件傳送PHP