亚洲有码Av一区二区三区_国产高清啪啪免费视频_69色视频国产_国产成人人人爆出白浆_国产精品自在线拍国_一本久久伊人热热精品无码_午夜性刺激在线看免费带字幕_助力高品质欧美狂喷水_亚洲精品日韩无码_精品无码一区二区三区蜜臀_麻豆高清国产AV_熟妇人素无码中文字幕_亚洲a级片在线观看_国产欧美日韩三区_99国产成人高清在线观看

ARTICLE DETAIL

資訊詳情

深耕商務(wù)建站與企業(yè)官網(wǎng)運(yùn)營的一線實(shí)戰(zhàn)洞察。

基于Qt的跨平臺(tái)SMTP郵件發(fā)送工具封裝實(shí)戰(zhàn)

基于Qt的跨平臺(tái)SMTP郵件發(fā)送工具封裝實(shí)戰(zhàn) 簡介基于Qt與C開發(fā)的郵件發(fā)送工具面向需要跨平臺(tái)實(shí)現(xiàn)SMTP郵件收發(fā)功能的開發(fā)者尤其適合在Windows與Linux環(huán)境下構(gòu)建帶附件的郵件客戶端。資源包共59個(gè)文件包含25個(gè)cpp源文件、15個(gè)頭文件以及dll動(dòng)態(tài)庫、UI設(shè)計(jì)文件、工程配置與資源圖片等完整覆蓋從界面構(gòu)建到SMTP通信的各個(gè)環(huán)節(jié)整體約16.32MB。代碼通過socket編程與郵件服務(wù)器交互利用QMimeData及MIME標(biāo)準(zhǔn)處理附件封裝實(shí)現(xiàn)身份驗(yàn)證、主題設(shè)置、正文發(fā)送等功能工程包含Qt Creator項(xiàng)目文件、ui界面及qrc資源可直接編譯運(yùn)行便于二次開發(fā)。目前已有312人學(xué)習(xí)下載適合具備C基礎(chǔ)、希望掌握Qt網(wǎng)絡(luò)編程與郵件協(xié)議細(xì)節(jié)的開發(fā)者參考。1. 為什么我要自己用 Qt 封裝一個(gè)跨平臺(tái)的郵件發(fā)送工具做桌面客戶端的人遲早會(huì)撞上一個(gè)需求把設(shè)備狀態(tài)、統(tǒng)計(jì)報(bào)表或錯(cuò)誤日志自動(dòng)發(fā)到指定郵箱。我在一個(gè)跨平臺(tái)數(shù)據(jù)采集項(xiàng)目里就被安排了這個(gè)活目標(biāo)平臺(tái)既有 Linux 工控機(jī)又有 Windows 上位機(jī)。當(dāng)時(shí)第一反應(yīng)是找現(xiàn)成庫試了一圈發(fā)現(xiàn)要么只支持單平臺(tái)要么對 SMTP 的 TLS 處理得像黑匣子出了問題根本沒法查。最后決定基于 Qt 的 QAbstractSocket 和 QSslSocket 自己實(shí)現(xiàn)一個(gè)輕量 SMTP 客戶端代碼量不大但把協(xié)議狀態(tài)機(jī)、認(rèn)證流程、MIME 編碼這些細(xì)節(jié)吃透了。這篇筆記就把這個(gè)工具的實(shí)現(xiàn)思路、關(guān)鍵代碼和我在 Linux/Windows 雙平臺(tái)踩過的坑完整拆出來適合需要在 Qt 項(xiàng)目里快速集成郵件通知功能的開發(fā)者參考。2. SMTP 協(xié)議邊界Qt 里 TCP、SSL 與認(rèn)證方式這么選2.1 SMTP 是個(gè)純文本協(xié)議先搞懂命令-應(yīng)答模型SMTP 和 HTTP 一樣是請求-響應(yīng)模型但它的文本協(xié)議特性更純粹客戶端發(fā)一條命令服務(wù)器回一個(gè)三數(shù)字狀態(tài)碼加一段說明文本。發(fā)郵件整個(gè)過程就是一組命令的有序序列從 EHLO 開始經(jīng)過 MAIL FROM、RCPT TO、DATA最后以 QUIT 結(jié)束。這個(gè)有序性決定了 Qt 側(cè)必須有一個(gè)狀態(tài)機(jī)來驅(qū)動(dòng)不能像普通 socket 編程那樣收到什么就處理什么。我第一版實(shí)現(xiàn)就是沒有狀態(tài)機(jī)收到服務(wù)器響應(yīng)后直接調(diào)用下一步發(fā)送函數(shù)結(jié)果在慢網(wǎng)絡(luò)下偶發(fā)錯(cuò)亂——服務(wù)器回 250 還在路上客戶端就把下一步命令丟出去了。后來改成顯式的狀態(tài)枚舉每次應(yīng)答回來先校驗(yàn)狀態(tài)碼與當(dāng)前狀態(tài)的匹配關(guān)系再推進(jìn)到下一個(gè)狀態(tài)問題才徹底消失。狀態(tài)碼分幾類2xx 表示成功、3xx 表示需要更多輸入、4xx 是臨時(shí)錯(cuò)誤、5xx 是永久錯(cuò)誤。郵件發(fā)送里最常見的幾個(gè)220 是服務(wù)器就緒250 是命令執(zhí)行成功334 是服務(wù)器要求提供認(rèn)證數(shù)據(jù)354 是告訴客戶端 DATA 階段開始、可以輸入郵件內(nèi)容了。Qt 側(cè)處理的關(guān)鍵是不要把狀態(tài)碼當(dāng)普通數(shù)字解析要做成枚舉和識(shí)別函數(shù)代碼維護(hù)性會(huì)好很多。2.2 端口與加密選型25、465、587 區(qū)別在哪里端口選型直接決定底層 socket 類的選擇。25 端口是傳統(tǒng) SMTP明文傳輸公網(wǎng)環(huán)境基本被運(yùn)營商封鎖只適合內(nèi)網(wǎng)自己搭的郵件中繼。465 端口是 SMTPSsocket 建立后立即進(jìn)入 SSL/TLS 加密對應(yīng) Qt 的 QSslSocket。587 端口是 submission先建立明文會(huì)話再通過 STARTTLS 命令升級(jí)為加密通道對應(yīng)先 QAbstractSocket 后切換 QSslSocket 的模式。我在這個(gè)工具里對三種端口都做了支持因?yàn)椴煌]件服務(wù)商偏好不一樣。實(shí)現(xiàn)上的差異集中在連接階段465 直接用 QSslSocket 連接connectToHostEncrypted 一發(fā)就完事587 需要先普通連接EHLO 之后發(fā) STARTTLS成功后再重新 EHLO 并走認(rèn)證流程。這里有個(gè)常見翻車點(diǎn)587 端口升級(jí)加密后服務(wù)器要求重新發(fā)送 EHLO很多人在 TLS 握手后直接發(fā) AUTH 命令服務(wù)器會(huì)回 503 錯(cuò)誤這是免費(fèi)教學(xué)資源里反復(fù)出現(xiàn)的經(jīng)典坑。2.3 認(rèn)證機(jī)制LOGIN 和 PLAIN 是最通用的組合SMTP 認(rèn)證常見的有 PLAIN、LOGIN、CRAM-MD5 三種。PLAIN 是把用戶名密碼用客戶端和服務(wù)器的共同憑據(jù)一次性發(fā)給服務(wù)器LOGIN 是分成兩步服務(wù)器先問用戶名再問密碼。CRAM-MD5 是挑戰(zhàn)-響應(yīng)機(jī)制服務(wù)器先發(fā)一個(gè)隨機(jī)挑戰(zhàn)字符串客戶端用密碼和挑戰(zhàn)做 MD5 摘要后返回密碼不直接暴露在網(wǎng)絡(luò)上。從 Qt 實(shí)現(xiàn)角度LOGIN 和 PLAIN 處理起來最直接。LOGIN 的交互邏輯比較自然客戶端發(fā) AUTH LOGIN服務(wù)器回 334 加提示字符串客戶端把用戶名做 Base64 編碼發(fā)過去服務(wù)器再回 334客戶端再發(fā)密碼的 Base64最后收到 235 表示認(rèn)證成功。PLAIN 就一條命令A(yù)UTH PLAIN 后面直接跟一個(gè) Base64 編碼的字符串這個(gè)字符串的格式是 \0username\0password即空字符包夾用戶名和密碼??紤]到兼容性我默認(rèn)先發(fā) EHLO 看服務(wù)器通告的 AUTH 能力列表優(yōu)先嘗試 CRAM-MD5如果服務(wù)器沒通告就退到 LOGIN。實(shí)際測試中發(fā)現(xiàn)部分內(nèi)網(wǎng)郵件服務(wù)器只實(shí)現(xiàn)了 LOGIN所以我在工具里把 LOGIN 作為默認(rèn)、PLAIN 作為備選遇到服務(wù)器通告里兩種都不支持時(shí)才報(bào)錯(cuò)。// 根據(jù) EHLO 響應(yīng)解析服務(wù)器支持的認(rèn)證方式 QStringList AuthMechs; foreach (const QString line, ehloReply) { if (line.startsWith(AUTH)) { AuthMechs line.mid(5).split( , Qt::SkipEmptyParts); break; } } // 常見輸出示例: AUTH LOGIN PLAIN CRAM-MD5這段邏輯值得注意的細(xì)節(jié)是服務(wù)器返回多行擴(kuò)展?fàn)顟B(tài)碼時(shí)AUTH 能力的行可能不是第一行。SMTP 的 EHLO 響應(yīng)是多行的每行前面有狀態(tài)碼只有最后一行帶空格前綴表示續(xù)行。Qt 里如果一次性 readAll 讀取要把響應(yīng)按行拆分后逐行檢查而不是直接 startsWith(AUTH)否則遇到前面有多行狀態(tài)碼時(shí)會(huì)漏掉。2.4 QSslSocket 的同步與異步邊界要拎清Qt 的 QSslSocket 是異步接口connectToHostEncrypted 觸發(fā)連接后程序不會(huì)阻塞等待結(jié)果而是通過信號(hào)通知調(diào)用方。在郵件發(fā)送這種邏輯里同步改異步是天然的——發(fā)郵件本身就應(yīng)該放到后臺(tái)線程不阻塞主界面。但要注意 QSslSocket 的信號(hào)連接時(shí)機(jī)我在第一版里犯過錯(cuò)誤在 connectToHostEncrypted 之后才連接 encrypted 信號(hào)結(jié)果握手極快的情況下信號(hào)丟失程序卡死在等待狀態(tài)。正確做法是先連接所有需要的信號(hào)再觸發(fā)連接動(dòng)作。sslErrors 信號(hào)尤其重要默認(rèn)情況下 QSslSocket 遇到自簽名證書或證書過期會(huì)直接中止連接必須手動(dòng)調(diào)用 ignoreSslErrors 或彈出確認(rèn)對話框。在工具內(nèi)部我實(shí)現(xiàn)了一個(gè)策略配置接口讓調(diào)用方?jīng)Q定是忽略還是中止默認(rèn)對自簽名證書直接給出告警日志后忽略因?yàn)閮?nèi)網(wǎng)郵件服務(wù)器用自簽證書太常見了。3. 核心實(shí)現(xiàn)SMTP 客戶端類的四個(gè)模塊與關(guān)鍵代碼3.1 類設(shè)計(jì)與接口定義讓調(diào)用方只看一個(gè) send 函數(shù)整個(gè)工具對外只暴露一個(gè)簡潔的接口調(diào)用方不需要關(guān)心 SMTP 細(xì)節(jié)。設(shè)計(jì)上分為四層Socket 封裝層、命令層、認(rèn)證層、MIME 構(gòu)造層。Socket 封裝層負(fù)責(zé) TCP/SSL 連接生命周期管理命令層實(shí)現(xiàn) SMTP 狀態(tài)機(jī)和命令發(fā)送認(rèn)證層處理 LOGIN/PLAIN/CRAM-MD5 交互MIME 構(gòu)造層生成符合 RFC 5322 的郵件數(shù)據(jù)。類的核心接口設(shè)計(jì)如下class SmtpClient : public QObject { Q_OBJECT public: enum AuthMethod { AuthNone, AuthLogin, AuthPlain, AuthCramMd5 }; SmtpClient(const QString host, quint16 port, QObject *parent nullptr); void setAuth(const QString username, const QString password, AuthMethod method AuthLogin); void setSslMode(SslMode mode); // SslMode::Tls / SslMode::StartTls / SslMode::None public slots: void sendMail(const MailMessage msg); signals: void mailSent(); void mailFailed(const QString errorMessage); void statusChanged(const QString status); private: QAbstractSocket *m_socket; // ... };這個(gè)接口設(shè)計(jì)的核心思路是同步語義封進(jìn)異步信號(hào)調(diào)用方調(diào)用 sendMail 后通過 mailSent 和 mailFailed 拿到結(jié)果statusChanged 實(shí)時(shí)回傳當(dāng)前階段方便界面顯示發(fā)送進(jìn)度。端口和加密模式在構(gòu)造時(shí)確定認(rèn)證方式通過 setAuth 配置。關(guān)于參數(shù)SslMode 枚舉是很多實(shí)現(xiàn)里容易混淆的地方Tls 對應(yīng) 465 端口直連加密StartTls 對應(yīng) 587 端口先明文后升級(jí)。3.2 連接與狀態(tài)機(jī)基于 QStateMachine 不如手寫枚舉網(wǎng)上很多 Qt 郵件示例用 QStateMachine 框架來實(shí)現(xiàn)連接狀態(tài)轉(zhuǎn)換但我在實(shí)際項(xiàng)目里發(fā)現(xiàn)這個(gè)框架用在 SMTP 這種有極少狀態(tài)、嚴(yán)格線性的流程上顯得笨重——狀態(tài)轉(zhuǎn)換的觸發(fā)條件本來就是一個(gè) socket 信號(hào)的 lambda直接手寫枚舉加 switch 反而更清晰可控。enum SmtpState { StateIdle, StateConnecting, StateEhlo, StateStartTls, StateEhloAfterTls, StateAuth, StateAuthUsername, StateAuthPassword, StateMailFrom, StateRcptTo, StateData, StateDataContent, StateQuit };每個(gè)狀態(tài)對應(yīng)一個(gè)待發(fā)送的命令收到服務(wù)器響應(yīng)后根據(jù)當(dāng)前狀態(tài)決定推進(jìn)方向。比如收到 220 就緒響應(yīng)后如果配置了 StartTls 就發(fā) STARTTLS否則直接發(fā) EHLO。收到 250 響應(yīng)后如果處于 StateEhlo 且還沒認(rèn)證就發(fā)起 AUTH順序不能亂。我選了手寫枚舉的核心原因是這套流程邏輯雖然線性但有分支端口類型影響連接方式、認(rèn)證方式影響交互步驟、發(fā)送內(nèi)容決定是否有 DATA 過程。手寫狀態(tài)機(jī)可以清晰表達(dá)這些分支條件后續(xù)調(diào)試時(shí)把當(dāng)前狀態(tài)直接輸出到日志看狀態(tài)序列就能定位問題比 QStateMachine 調(diào)試起來直觀得多。void SmtpClient::handleReply(const QString reply) { int code reply.left(3).toInt(); switch (m_state) { case StateEhlo: if (code 250) { m_state StateAuth; sendAuth(); } else { emit mailFailed(QStringLiteral(EHLO failed: %1).arg(reply)); } break; case StateAuth: if (code 334) { m_state StateAuthUsername; sendBase64(m_username); } else { emit mailFailed(QStringLiteral(AUTH failed: %1).arg(reply)); } break; // ... } }邏輯說明handleReply 是 socket 的 readyRead 信號(hào)觸發(fā)后對緩沖數(shù)據(jù)的統(tǒng)一解析入口。每次解析出完整響應(yīng)行才交付給狀態(tài)機(jī)然后是逐個(gè)狀態(tài)的分支處理。參數(shù)說明code 只取前三位數(shù)字response 的剩余部分僅在日志中使用不做流程控制依據(jù)。3.3 base64 認(rèn)證細(xì)節(jié)Qt 的 Base64 編碼默認(rèn)不帶換行SASL 認(rèn)證里用戶名密碼都要做 Base64。這里有個(gè) Qt 特有的坑QByteArray::toBase64() 默認(rèn)每 76 個(gè)字符插入一個(gè)換行符這符合 MIME 的規(guī)范但 SMTP AUTH 里不允許出現(xiàn)換行服務(wù)器解析會(huì)出錯(cuò)。解決方案是用 QByteArray::fromBase64 的反向函數(shù)編碼時(shí)指定 Base64Encoding | Base64UrlEncoding 標(biāo)志組合起來可以關(guān)閉換行插入。實(shí)際測試中大部分 Linux 郵件服務(wù)器對換行寬容但 Windows 自帶的 SMTP 服務(wù)對格式要求嚴(yán)格一個(gè) \r\n 混進(jìn) Base64 就整個(gè)包解析失敗。QByteArray SmtpClient::encodeAuth(const QString text) const { QByteArray raw text.toUtf8(); return raw.toBase64(QByteArray::Base64Encoding | QByteArray::OmitTrailingEquals); }OmitTrailingEquals 會(huì)去掉 Base64 末尾的 填充字符部分服務(wù)器對缺失 也能接受但為了兼容性我保留了 只用 Base64Encoding 純編碼去掉默認(rèn)換行就夠。參數(shù)說明這里有個(gè)細(xì)節(jié)如果調(diào)用方傳給 setAuth 的用戶名密碼含非 ASCII 字符必須轉(zhuǎn) UTF-8 再做 Base64用 QString::toLatin1 會(huì)導(dǎo)致中文郵箱用戶名全部亂碼。3.4 超時(shí)與重傳QTimer 單次觸發(fā)做看門狗網(wǎng)絡(luò)環(huán)境不穩(wěn)定時(shí)SMTP 會(huì)話可能卡在某個(gè)中間態(tài)服務(wù)器連上了但遲遲不回 250認(rèn)證發(fā)出去沒有響應(yīng)DATA 階段服務(wù)器也斷了連接。如果沒有超時(shí)機(jī)制線程會(huì)一直掛著內(nèi)存和連接資源越積越多。我實(shí)現(xiàn)了一個(gè)統(tǒng)一的超時(shí)看門狗每次發(fā)送命令前啟動(dòng)一個(gè) QTimer::singleShot超時(shí)時(shí)間按階段區(qū)分——連接階段 30 秒認(rèn)證階段 10 秒DATA 階段 60 秒。超時(shí)后強(qiáng)制斷開 socket 并發(fā)出 mailFailed 信號(hào)。void SmtpClient::startWatchdog(int timeoutMs) { if (m_watchdogId ! -1) killTimer(m_watchdogId); m_watchdogId startTimer(timeoutMs); } void SmtpClient::timerEvent(QTimerEvent *event) { if (event-timerId() m_watchdogId) { killTimer(m_watchdogId); m_watchdogId -1; abort(); emit mailFailed(QStringLiteral(SMTP timeout)); } }這段代碼的邏輯是每次發(fā)出命令的時(shí)候重設(shè)看門狗任何一次服務(wù)器響應(yīng)到達(dá)都先 killTimer 再 startTimer相當(dāng)于重新計(jì)時(shí)。參數(shù)設(shè)置上我推薦連接階段寬松、命令階段緊湊的方式原因是通過 EHLO 響應(yīng)可以確認(rèn)服務(wù)器活著后續(xù)每步響應(yīng)都應(yīng)該很快如果超過 10 秒基本是網(wǎng)絡(luò)問題或服務(wù)器死鎖再等也沒意義。4. MIME 構(gòu)造文本、HTML、內(nèi)嵌圖片與多附件的編碼細(xì)節(jié)4.1 普通文本郵件也要設(shè)置字符集和編碼很多人以為發(fā)純文本郵件只要拼好字符串 socket 寫出去就行實(shí)際上郵件傳輸是 7-bit 干凈的通道非 ASCII 字符必須編碼。最簡單的策略是 UTF-8 加 Base64 編碼整個(gè)郵件體作為一個(gè) Base64 塊嵌進(jìn) Content-Transfer-Encoding 頭里。QByteArray MailMessage::buildTextBody(const QString text) { QByteArray out; out Content-Type: text/plain; charsetutf-8\r\n; out Content-Transfer-Encoding: base64\r\n; out \r\n; out text.toUtf8().toBase64(QByteArray::Base64Encoding); return out; }邏輯說明QByteArray::Base64Encoding 這個(gè)標(biāo)志位會(huì)自動(dòng)處理 76 字符換行這對 MIME 的 Base64 段是符合規(guī)范的——解碼端會(huì)忽略換行符。但這里有個(gè)細(xì)節(jié)Base64 編碼后的數(shù)據(jù)行與行之間以 \r\n 分隔而不是 \n網(wǎng)絡(luò)傳輸協(xié)議里標(biāo)準(zhǔn)明確要求用 CRLF。參數(shù)說明如果調(diào)用方傳入的 text 本身包含 \r\n編碼后的 Base64 塊里這些換行已經(jīng)被編碼成數(shù)據(jù)不會(huì)干擾郵件結(jié)構(gòu)可以放心。4.2 Quoted-Printable 與 Base64 的應(yīng)用場景邊界Base64 適合編碼整體就是二進(jìn)制或大量非 ASCII 字符的內(nèi)容Quoted-Printable 適合以 ASCII 為主體、偶爾有少量非 ASCII 字符的內(nèi)容。Q-P 編碼把非 ASCII 字節(jié)寫成 XX 形式可讀性好體積膨脹小。在郵件場景里 Base64 用于附件和純文本郵件體QP 用于 HTML 郵件體中穿插少量中文標(biāo)題或關(guān)鍵詞的場景。兩者可以混合出現(xiàn)在同一個(gè) MIME 多部分消息的不同部分里互不沖突。QByteArray MailMessage::encodeQuotedPrintable(const QString text) { QByteArray utf8 text.toUtf8(); QByteArray out; for (char c : utf8) { unsigned char uc static_castunsigned char(c); if (uc \n) { out \r\n; } else if (uc || uc 127 || uc 32 || uc ?) { out ; out QByteArray::number(uc, 16).rightJustified(2, 0).toUpper(); } else { out c; } } return out; }邏輯說明手動(dòng)實(shí)現(xiàn) Q-P 編碼比用庫函數(shù)更可控因?yàn)樾枰_處理軟換行和硬換行邏輯。注意代碼里的細(xì)節(jié)等號(hào)、非 ASCII 字符、控制字符都要轉(zhuǎn)義而空格在 Q-P 編碼里可以保持原樣但在行尾必須編碼成 20否則解碼端會(huì)吃掉它。4.3 multipart/mixed 與 multipart/related 的嵌套結(jié)構(gòu)一封帶附件的郵件頂層必須是 multipart/mixed里面第一個(gè)子部分是郵件正文后面是附件。如果正文里要嵌圖片正文本身要轉(zhuǎn)成 multipart/related內(nèi)嵌圖片用 CID 引用。QByteArray MailMessage::buildMultipart(const QByteArray body, const QListAttachment attachments) { QByteArray boundary ----_Part_ QByteArray::number(QRandomGenerator::global()-generate()); QByteArray out; out Content-Type: multipart/mixed; boundary\ boundary \\r\n; out \r\n; out -- boundary \r\n; out body; for (const Attachment att : attachments) { out \r\n-- boundary \r\n; out att.buildPart(); } out \r\n-- boundary --\r\n; return out; }邊界字符串用隨機(jī)數(shù)生成避免出現(xiàn)在郵件內(nèi)容里造成解析歧義。隨機(jī)數(shù)的來源我選 QRandomGenerator::global()它線程安全跨平臺(tái)表現(xiàn)一致。邊界字符串的格式要求是開頭不能是空格或換行長度不超過 70 字符這里隨機(jī)數(shù)生成的長格式完全符合規(guī)范。4.4 附件的 Content-Disposition 與文件名編碼附件的文件名如果是中文必須做 RFC 2231 編碼也就是 filename*UTF-8%E4%B8%AD%E6%96%87.txt 這種格式。不加這個(gè)頭的話多數(shù)客戶端顯示附件名為亂碼或直接丟失擴(kuò)展名。QByteArray Attachment::buildPart() const { QByteArray out; QString encodedName QUrl::toPercentEncoding(m_fileName); out Content-Type: application/octet-stream; name*UTF-8 encodedName.toUtf8() \r\n; out Content-Transfer-Encoding: base64\r\n; out Content-Disposition: attachment; filename*UTF-8 encodedName.toUtf8() \r\n; out \r\n; out m_data.toBase64(QByteArray::Base64Encoding); return out; }邏輯說明RFC 2231 的格式是對文件名做 percent-encoding 后追加到 filename* 字段注意不要用 QUrl::toPercentEncoding 的默認(rèn)參數(shù)它會(huì)編碼空格和標(biāo)點(diǎn)需要確認(rèn)不把斜杠也編碼掉。參數(shù)說明里有個(gè)細(xì)節(jié)m_data 是從文件讀取的原始字節(jié)不要在讀取時(shí)做任何轉(zhuǎn)換直接 Base64否則大文件會(huì)有雙重轉(zhuǎn)換的性能開銷和內(nèi)存膨脹。4.5 CRLF 與點(diǎn)填充DATA 階段的兩個(gè)硬性規(guī)范DATA 階段是 SMTP 協(xié)議里唯一的多行數(shù)據(jù)階段客戶端發(fā) DATA 命令收到 354 響應(yīng)后逐行發(fā)送郵件內(nèi)容以單獨(dú)一行英文句點(diǎn) . 結(jié)束。這個(gè)過程中有兩個(gè)規(guī)范必須遵守所有行必須以 CRLF 結(jié)尾內(nèi)容中凡是以 . 開頭的行都必須額外在行首增加一個(gè)點(diǎn)即發(fā)送 .. 服務(wù)器端會(huì)還原為單點(diǎn)。如果不在客戶端處理孤立行點(diǎn)郵件正文里某個(gè)以 . 開頭的段落會(huì)導(dǎo)致服務(wù)器提前結(jié)束 DATA 階段后續(xù)內(nèi)容全部丟失。我專門實(shí)現(xiàn)了一個(gè) dotUnstuffing 函數(shù)在發(fā)送前對郵件體按行處理QByteArray MailMessage::dotUnstuff(const QByteArray content) const { QByteArray out; QListQByteArray lines content.split(\n); for (int i 0; i lines.size(); i) { QByteArray line lines.at(i); if (line.endsWith(\r)) line.chop(1); if (line.startsWith(.)) out .; out line; if (i lines.size() - 1) out \r\n; } return out; }邏輯說明這里手動(dòng)處理行尾是因?yàn)椴煌到y(tǒng)上傳入的文本可能混有 \n、\r\n 或 \r統(tǒng)一在函數(shù)入口轉(zhuǎn)成規(guī)范格式再處理。注意這個(gè)函數(shù)只處理行首點(diǎn)轉(zhuǎn)義不負(fù)責(zé)把 \n 替換成 \r\n——這個(gè)邏輯應(yīng)該在構(gòu)建消息體時(shí)已經(jīng)完成在 dotUnstuff 中重復(fù)處理反而會(huì)破壞已編碼的 Base64 塊。5. 六個(gè)避坑狀態(tài)機(jī)、Base64 換行與 Windows 證書鏈5.1 現(xiàn)象465 端口連接后立即收到 220但 AUTH 后一無所獲這是我在某公司內(nèi)網(wǎng)郵件服務(wù)器上遇到的第一個(gè)玄學(xué)問題。連接正常EHLO 正常AUTH LOGIN 發(fā)出后服務(wù)器不回任何響應(yīng)直到超時(shí)。原因排查后發(fā)現(xiàn)服務(wù)器的 SMTP 服務(wù)的 TLS 層握手使用了 465 端口特有的立即加密模式而 QSslSocket 連接時(shí)默認(rèn)的 sslMode 配置成了 SslMode::None導(dǎo)致明文 AUTH 被服務(wù)器丟棄或視為協(xié)議錯(cuò)誤。解決方案是為每種端口指定獨(dú)立的默認(rèn) SslMode端口 465 默認(rèn) Tls端口 587 默認(rèn) StartTls端口 25 默認(rèn) None。同時(shí)保留 setSslMode 接口供調(diào)用方覆蓋。從那以后凡是端口和加密模式不一致的報(bào)錯(cuò)我第一件事先查配置組合。5.2 現(xiàn)象驗(yàn)證碼郵件發(fā)送成功后收件人看不到正文開發(fā)階段自己測試一切正常但收件人收到的郵件正文是空的只有附件。這是典型的 Windows 換行符混入導(dǎo)致的解析歧義。Windows 上 QFile 讀取文本或 QString 拼接時(shí)默認(rèn)保留 \r\n而 Linux 下默認(rèn)只有 \n。郵件體里部分行以 \n 結(jié)尾、部分行以 \r\n 結(jié)尾部分客戶端解析 MIME 邊界時(shí)按 \r\n 逐行找 boundary 字符串遇到裸 \n 就誤判后續(xù)結(jié)構(gòu)全亂。解決方案是在構(gòu)建郵件體的入口強(qiáng)制做換行規(guī)范化MIME 頭、正文、附件部分的每一行都以 \r\n 結(jié)尾不做例外處理。這個(gè)函數(shù)我放在 MailMessage 構(gòu)造函數(shù)里在 fill 階段統(tǒng)一處理。5.3 現(xiàn)象附件大小超過 10MB 后發(fā)送失敗日志顯示 socket 寫入明顯變慢偶爾還報(bào) connection reset by peer。原因有兩個(gè)一是我用 QByteArray 一次性持有整個(gè) Base64 編碼后的內(nèi)容大文件時(shí)內(nèi)存翻倍二是 socket 寫入緩沖區(qū)滿后Qt 的 write 函數(shù)返回 -1或只寫入部分字節(jié)我沒有處理partial write 情況。解決方案附件讀取改用分塊讀取Base64 編碼按 3KB 原始數(shù)據(jù)一塊編碼后立即寫入 socket寫入邏輯改為檢查 write 返回值如果只寫入部分則緩存剩余數(shù)據(jù)等 bytesWritten 信號(hào)繼續(xù)寫。這個(gè)改動(dòng)后內(nèi)存占用降低發(fā)送穩(wěn)定性明顯提升。5.4 現(xiàn)象Windows 上發(fā)給某大型郵箱服務(wù)商的郵件被判定為垃圾郵件Linux 上發(fā)送同樣的郵件沒問題Windows 上卻進(jìn)了垃圾箱。深入排查后發(fā)現(xiàn)是 Windows 的 QSslSocket 默認(rèn)不帶系統(tǒng)的 CA 證書鏈路徑導(dǎo)致 TLS 握手的證書鏈驗(yàn)證結(jié)果與 Linux 不同。某些郵件服務(wù)商看到 TLS 握手異常會(huì)提高垃圾郵件評(píng)分。解決方案是在 Windows 上顯式加載系統(tǒng)證書QSslConfiguration::setCaCertificates 從系統(tǒng)證書存儲(chǔ)讀取或者調(diào)用 setDefaultConfiguration 把 Windows 根證書庫的證書 load 進(jìn) QSslSocket。注意這個(gè)操作要在連接之前完成不是 connectToHostEncrypted 之后。5.5 現(xiàn)象定時(shí)發(fā)送任務(wù)在 Linux 服務(wù)器后臺(tái)運(yùn)行時(shí)偶發(fā)段錯(cuò)誤用 QTimer 定時(shí)觸發(fā) sendMail運(yùn)行幾天后出現(xiàn) crash。排查發(fā)現(xiàn)是對象生命周期問題sendMail 是異步的SMTP 狀態(tài)機(jī)跨多個(gè)網(wǎng)絡(luò)交互如果調(diào)用方在定時(shí)觸發(fā)后立刻銷毀了 SmtpClient 對象socket 信號(hào)觸發(fā)時(shí)訪問已釋放的內(nèi)存。解決方案是引入 QSharedPointer 或 QPointer 管理客戶端對象生命周期在 mailSent/mailFailed 信號(hào)發(fā)出前不釋放?;蛘咴?SmtpClient 內(nèi)部增加一個(gè) m_isDeleting 標(biāo)志告訴調(diào)用方當(dāng)前不能銷毀。一般我推薦前者用 shared 指針包裹客戶端放在調(diào)用方的容器里發(fā)送完成信號(hào)后再 reset。5.6 現(xiàn)象服務(wù)器返回 550 5.7.1 authentication required連接、認(rèn)證都顯示成功但發(fā)送時(shí)被拒日志里出現(xiàn) 550 錯(cuò)誤。這個(gè)坑的根因很隱蔽EHLO 響應(yīng)里 AUTH 能力列表只有 PLAIN服務(wù)器要求必須用 PLAIN 認(rèn)證但客戶端配置了 LOGIN認(rèn)證時(shí)服務(wù)器認(rèn)為沒有完成有效認(rèn)證發(fā)送階段才暴露。解決方案是把認(rèn)證方式選擇做成自動(dòng)協(xié)商解析服務(wù)器通告的 auth list按 CRAM-MD5 LOGIN PLAIN 優(yōu)先級(jí)選擇而不是固定調(diào)用方指定。事后我在配置接口里保留了 overrideAuthMethod 方法但默認(rèn)自動(dòng)協(xié)商保證內(nèi)網(wǎng)環(huán)境零配置可用。6. 從可用到可靠命令追蹤、自測與超時(shí)重傳的三個(gè)習(xí)慣項(xiàng)目做到能發(fā)郵件只是第一步真正考驗(yàn)人的是讓這套東西在各種異常環(huán)境下不崩、不丟、不發(fā)重復(fù)郵件。所以我在工具正式集成進(jìn)業(yè)務(wù)系統(tǒng)之前養(yǎng)成了三個(gè)習(xí)慣。第一個(gè)習(xí)慣是給每次會(huì)話做一個(gè)命令追蹤文件。SMTP 會(huì)話的每一條發(fā)出命令和接收到的響應(yīng)都帶時(shí)間戳追加到日志緩沖區(qū)并提供 dumpSessionLog 方法供外部調(diào)用。排查問題時(shí)直接看這個(gè)文件就能定位到對話的哪一步出錯(cuò)——是 TLS 握手沒完成還是認(rèn)證交互卡在某個(gè) 334 響應(yīng)一目了然。第二個(gè)習(xí)慣是用 openssl 命令手工模擬一次 SMTP 會(huì)話作為對照。通過 openssl s_client -connect host:port -starttls smtp 進(jìn)入交互模式手工輸 EHLO、AUTH、MAIL、RCPT、DATA能確認(rèn)服務(wù)器行為正常排除工具本身的問題。這個(gè)習(xí)慣幫我排查過一個(gè)非常隱蔽的坑某內(nèi)網(wǎng)服務(wù)器要求 HELO 而不是 EHLO只有手工模擬時(shí)才會(huì)注意到這個(gè)細(xì)節(jié)代碼里直接跑了六輪 EHLO 全部失敗。第三個(gè)習(xí)慣是給超時(shí)重傳加冪等控制。簡單場景下網(wǎng)絡(luò)超時(shí)后直接重發(fā)整封郵件可能造成收件人收到兩封相同的信。我在 MailMessage 結(jié)構(gòu)里加了一個(gè) messageId 字段每次重傳使用相同的 Message-ID 頭并對同一邏輯郵件的重傳次數(shù)做上限控制默認(rèn)最多 3 次間隔 30 秒退避。以重傳擴(kuò)展為例for (int attempt 1; attempt maxRetries; attempt) { connect(m_job, SmtpJob::mailSent, this, [this]() { notifySuccess(); }); connect(m_job, SmtpJob::mailFailed, this, [this, attempt]() { if (attempt maxRetries) { QTimer::singleShot(30000 * attempt, this, [this]() { sendMail(m_msg); }); } else { notifyFailure(); } }); }邏輯說明重傳間隔按嘗試次數(shù)線性退避30 秒、60 秒、90 秒給服務(wù)器恢復(fù)留時(shí)間而不是無腦重試。參數(shù)說明maxRetries 和 baseInterval 通過構(gòu)造函數(shù)注入方便宿主環(huán)境按業(yè)務(wù)場景調(diào)整——實(shí)時(shí)告警可以縮短間隔日終報(bào)表可以放大到 5 分鐘。從那以后我每次接入新郵件服務(wù)都要強(qiáng)制走一遍手工 SMTP 會(huì)話、日志回放、重傳冪等這三項(xiàng)檢查確實(shí)省下不少半夜被叫起來解決問題的麻煩希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取
返回列表
PREV
查看更多資訊
NEXT
返回資訊列表
嗯嗯啊啊啊好舒服| 99久久综合| 狠日欧美| 沈阳熟女高潮对白视频| 亚洲精品九九九| 欧美|91色综合| 偷拍五区| 乱伦av麻豆| 亚 欧 美 综合| 超清中文乱码字幕| 美女人妻色网站| 超碰吊日色| 久久老子无码午夜伦不卡| 内射卯月麻衣| 国产精品久久久啊| 激情五月丁香五月| 亚州九九九精品视频| 欧美色就是色| 夜夜一区二区| 国产精品九九九| 精品福利视频| 久久久麻豆精品| 操b网站亚洲无码| 亚洲天堂2020| 伊人99热| 男人午夜天堂| 极品丝袜无码| 国产精品永久免费10000| 天天肏美女| 国产在线观看91精品一区| 丝袜天堂网| 欧美第一页| 91亚洲不卡一区| 久久久9999| 亚洲日韩肥臀视频在线观看| 亚洲无码一二三区| 亚洲a色| 97电影院超碰| 日本一区二区三区免费观看| 美女91av| 丝袜制服字幕在线| 婷婷在线视频| 日本精品不卡一二三区| 精品人妻中文字幕高清| 熟妇人妻丰满久久久久久久无码| 久久极品一区二区| 岛国黄片网站| 欧美性爱日韩高清| 人妻素股| 国产第二页| 91超级碰碰碰| 久久国产热视频97电影| 五月天我淫我色av| 亚洲影院成人| 后入人妻无码| 午夜操一视频一区| 九九九九精品视频| 伊人久久大香线蕉亚洲五月天,青草青草欧美日本一区二区,欧美日产欧美日产国产 | 午夜国产成人福利视频| 国产美女在线精品免费看| 欧美爆操91| 午夜欧美女人操逼| 久久精品人人做人人看| 色网色网色网色网色网色| 性性久久| 久久精品电影| 欧美日韩黄色片一区二区三区四区人与兽做爱| 亚洲精品色| 色综合色色| 97精品久久| 欧美A片中文字幕| 91天天综合网| 校园春色中文字幕AV| 91在线色| 99九九久久| 91久久久老司机| 久草电影网| 国产精品另类一区大香蕉| 亚洲中文字幕久久无码精品| 五月丁香激情四射| 亚洲乱妇p22| 欧美 亚洲 在线| 人妻天天爽天天爽三区| 久久九七| 国产高清成人传媒影视| 国产高清免费不卡av| 午夜丁香婷婷| 日本亚洲vr欧美不卡高清专区| 人妻少妇精品一区二区三区| 亚洲情色一区三区| 青女偷拍网| 综合亚洲欧美| 色网色网色网色网色网色| 一级片在线观看高清无码| 黄片com.| 加勒比综合九九99视频在线播放| 青青欧洲黑| 欧美精品,四区。五区| 狠狠夜色午夜久久综合在线| 99精品无码| 亚洲欧美国产中文视频| 日本护士高潮| 九区国产| 搡老女人老91二区| 亚洲熟女乱色一区二区三区| 色情乱伦AV| 久久人人爽人人爽人人片Ⅴ| 91成人国产综合久久精品蜜月| 啊啊啊啊啊啊在线| 超碰在线看| 西西美女视频网| 亚洲在钱| 亚洲成人福利电影免费| 一本道综合色图| 97精品视频免费| 婷婷婷婷婷婷久久久久| 91人妻素女| 久久精品国产亚洲AV高级北京| 丝袜喷水在线| 免费看黄视频亚洲网站| 色久综合| 一本色道久久综合精品婷婷| 中文字幕黄片在线| wwe 天天干.com| 日韩大香蕉| 在现视频女上位好爽| 亚洲熟女av中文字幕| 精品人妻av在线播放| 性久久久| 久9久| 日本黄 R色 成 人网站| 欧美韩国你懂得在线| 蜜臀一区二区三区在线| 四虎影视在线| 亚洲色人| 香一区二区三区| 亚洲精品97久久| 加勒比大香蕉视频在线| 青青在线视频免费| 欧美色图偷拍另类| 日逼视频日本| 亚洲综合性感在线| 奇米狠999| 欧美大色交| 永久免费发布性爱网| 视频二区熟女人妻| 久热这里| 黑人美精品 A片| 色眯眯av| 亚洲人妻AV| 男人天堂资源| 久久国产对白激情浪潮| 国产精品视频白浆免费| 97视频在线播放| 六月婷婷激情| 久久亚州精品成人Av无| 一二区在线观看视频| 久久婷婷精品| 欧美性爱综合,免费| 久草精品国产蜜臀| 99色天堂| 欧美日韩性爱电影在线| 久草综合网| 一起草av| 欧美日韩免费性爱| 男人的天堂VA| 久久久专区| 老熟妇一区二区三区…| 麻豆视频一区二区| 久久內射| 五月丁香激情综合网| 思思热一热婷婷热一热| 久操网视频| 成人日本片久久久蜜桃| 日韩欧亚太美不卡| 丁香六月综合激情| 操逼天美3区| 超碰久久.com| 超碰人妻中文在线| 亚洲人在线| 91在线无码精品秘 软件| 亚洲一区二区三区婷婷| 激情四射婷婷六月天| 天天干天天干天天干| 国产乱色国产精品免费视| 后入综合久久| 99只有精品| 97天天摸天天碰| 国产理论视频在线播放| 波多野42部激情无码喷潮| 日本 情色 1区2区3区| 亚洲s在线观看| 精品一区二区成人| 素人一区二区三区日韩| 欧美肥臀在线| 亚洲丰满很很操| 日本午夜福利视频| 一级黄色影片| 欧美日韩操逼嗦吊| 思思在线免费视频| 亚欧免费观看视频| 激情小说在线视频| 麻豆成人影音在线| 久操免费电影| 91n.欧美| A一级色女| 亚洲情色在线| 国产精品乱码久久久久久久久久久久| 99超碰色| 色女99一级片在线观看| 国产精品白虎| 97最新在线播放视频| 精品无码不卡视频| 日韩综合成人免费视频| 国产精品一区二区校花| 久久av一级av少妇av高潮| 午夜啪| 午夜爽爽爽| 久热精品色情| 日本精品性生活久久久| 99操| 久久久久久久久久久999| 青青草密桃在线播放| 亚洲丝袜二区| 国产亚卅97| 99.色网| 91扒丝袜综合在线| 久久视网78| 玖玖综合色| 中文字幕精品乱码| 天天夜夜久久| 超碰97在线色男人??| 校园春色亚洲无码| 天海翼久久| 尤物视频偷拍免费| 欧美91久久久久| 亚洲Av噜噜一区二区三区妖精| 丁香五月天久久精品视频一区二区三区| 97露脸精品丝袜| 大香蕉十区| 国产偷人妻精品一区二区在线| 97这里只精品| 性欧美| 天天干夜夜鈤| 91小视频| 97操97色| 中文字幕在线2| 91精品丝袜久久久久久| 日韩熟女无码| 欧美亚洲色图另类国产| 亚洲欧洲综合视频在线| 毛片视频白嫩| 欧美黑人日韩少妇色情| 啊啊啊啊好爽好舒服一区二区易域| aa片毛片| 五月天激情影院| 久久色激情一区二区三区| 夜夜操2028| 欧洲亚洲人妻无码中字久久三区四区| 欧洲一区二区| 亚洲āv网址在线观看| 久久亚洲欧美中文字幕国语| 人人干人人搞人人摸| av大香蕉| 青草影院内射高潮| 中文久久久| 女性喷水高潮在线观看| 精品国产乱码久久久久久口爆网站| 久久社区一区二区三区| 欧美日不卡| 亚洲天堂日本| 亚洲欧美第一页| 日本性爰一道本| 91美女丝袜诱惑视频| 亚洲永久AV无码精品秋霞| aV中文麻| 日韩性爱免费视频在线网站| 欧美黑人猛交春色影视大全| 久久精品无码熟妇一区二区三区视频导航| 日韩欧美操逼xxx| 久久香蕉国产传媒一区剧情天美| 99RE在线视频精品,这里只有精品| 夫妻AV网站| 亚洲国产精品无码AV久久久| 亚洲男人天堂Av| 男人天堂网手机版婷婷| 这里只有精品视频在线观看麻豆| 激情五月天色色| 成人久久久精品| 大香蕉乱级| 久久五月份| 黄站在线免费观看| 日韩欧美国产高清视频| 啊嗯嗯啊好大好爽| 亚洲九月丁香| 亚洲日精品| 中国东北熟女老太婆内谢| 4141514逼喷水三级片| 九九精品网| www.色操逼| 欧洲亚洲人人爽爽视频| 午夜啪啪片| 加勒比综合九九99视频在线播放| 久久性生大片免费观看性| 色丁香久久| 欧美性少妇| 全球成人中文在线| 日韩99999| 国内三级自拍小视频在线观看 | 九色 人妻 大香蕉| 国产精品乱码久久久| 爱我干综合| 亚洲欲| 日本操逼二区| 欧美高潮| 强奸乱伦AV网站| 天堂伊人久久| 久操操AV电影| 亚洲蜜臀精品视频久久| 日本一级黄色电影| 91丨人妻丨国产丨丝袜| 五月天婷婷综合| 99热在线播放| 91精品人妻一区二区-全集完整版免费正片国语-B02AV | 色999人与兽| 亚洲成人帖图| 天堂九九九九九九九九九| 97精品久久| 性色高清在线| 色狠狠综合| 野狼福利社区| 婷婷色网| 激情网色| 天天影视之亚洲综合网| 亚洲无套久久嗯嗯| 国产人伦a片信息免费片| 色眯眯av| 囯产精品一区二区三区线|亚洲人成无码网WWW动漫|国产精品免费一级... | 天天操天天日天天干| 亚洲成a人在线观看久| 91国产丝袜美女| 亚洲经典啪啪| 无码操逼视频一下| 亚洲另类色综合网站| 熟女啪啪视频| 国模无码一区二区三区在线| 凹凸精品熟女在线观看| 日韩精品怡红院| 国产成人精品亚洲日本| 无码不卡八戒| 青青草大香蕉视频| 学生妹天天看| 久热大香蕉| 免费观看网黄| 上床啊啊啊| 日韩美女高潮喷水视频| 好淫网一二三视区| **一级毛片国产| 精品一区二区国产日韩| 骚货操死你| 欧美视频激情久久久久久| 人妻一区视频| AV乱伦国产| 国产精品肉丝自拍| 欧美黄色片AAAAA| 日韩欧洲操屄视频| 欧美色性情| 超碰无码五月97| 麻豆影音天美视频| 亚洲av淫乱| 青娱乐91| 日韩成人小视频| 欧美日韩婷婷中文| 啊啊啊 在线观看| 久久东京国产精品视频| 国产AV久久野战精品| 成人精品在线免费视频| 97视频免费播放| 一本色道久久综合狠狠操| A啊啊在线观看| 亚洲有薄码区日本系列中文字幕| 国产一区二区三区影片| 精品区国产区一区二区三区| 亚欧成人综合影院| 亚洲小电影免费涩涩成人在线高清| 超碰97国产欧美| 天天舔九色婷婷| 日本免费不卡二区| sss视频华人在线| 久久久久久午夜男人的天堂| 国产免费永久精品无码| 国产精品视频白浆免费| 91精品人妻电影| 欧美日韩国产高清在线一二三区 | 日韩性爱啪啪视频| av网站国产主播在线| 超碰在线一区二区| 欧美色就是色| 不卡在线观看视频| 人妻另类 专区 欧美 制服| 精品熟女呻吟久久91| 午夜精品久久久久久久久久久久久| 就去色综合| 美女十八禁| 变态综合色| 久久9久| 日比av无码| 超碰色图| 久久粉色| 国产在线综合网| 操国产逼| 97久久超碰| 欧洲性爱无码区| 五月天久久综合网| 日本欧美亚洲高清在线看| 日韩 欧美 另类 人妻| 自拍大香蕉乱插| 亚洲日本韩国在线| 日韩一999精品| 欧美 牲| 精品人妻一区二区蜜桃视频| 国产久久日| 超碰97人人乐| 乱欲视频| 国产欧美岛国精品一区| 超碰人人色| 97人人中文网| 久久久久96| 久久国产精品m码| 日本熟女不卡视频| 色网在线视频观看免费| 99日韩| 嗯啊不要啊啊在线观看视频| 97bbn| 亚州高清AV| 97精品| 天天色天天干天天射| 大香蕉婷婷| 久久男人网| 淫色网综合| 97超碰欧美手机在线| 欧美色图20p| av在线不卡一区二区三区| 亚洲最大无码中文字幕网站 | 青青草视频导航官网| 风月影院男女十八禁| 亚欧美综合网| 乱伦日本中文自拍| 丁香五月婷婷基地| 蜜桃视频一区二区三区| 少妇久久久久久| 免费A V在线播放| 后入 亚洲 美女 射| 国模不卡一本二本三电影| 少妇精品| 在线精品福利免费播放| 精品人妻二区三区| 欧洲精品二区| 国产情侣自拍在线播放| 一区二区三区无卡视频在线观看| 精品九九| 日韩啪啪啪啪啪| 女上位精品在线| 性爱网站一区二区| 一区中文字幕二区日韩| 999精品女人| 日本欧美亚洲高清在线看| 欧美色九九九| 国产强奸无码乱伦| 乱色视频中文字幕| 99蜜月精品久久| 欧美1区二区三区公司| 久久97| 男人天堂最新手机版在线青青草| 欧美人妻精品一区二区| 综合欧美日韩在线| 超碰无码加勒比| 亚洲成人一二三区| w w w.久久精品| 在线无码操| 粘花网06av视频| 日本成人在线不卡一区二区三区| 日本韩国一本产品小视频日本韩国一本产品久久久产品小视频日本韩国一本产品久 | 大香蕉在线SuP| 国产成人亚洲精品无码最新在线| 亚洲城人男人的天堂| 葡萄牙性视频一二区| 色九月婷婷| 欧美偷| 婷婷丁香久久| 九九九九九九免费视频| 久久黄片国产一区二区| 啊啊啊 在线观看| 亚洲天堂男人| 麻豆黄四叶草网站| 中国AV美女| 四季AV综合网址| 综合伊人激情| 国产乱青青草久久| 日本在线视频导航| 精品久久97观看在线视频| 五月天综合在线| 中文字幕一区二区无码成人| 日韩另类色图| 欧美性爱第一页久久| 99青青草国产视频| 免费伦费视频在线观看| 青女在线| 国产精品青草综合久久| 亚洲日韩美女丝袜美腿人妻视频| 青娱乐导航AV| 天天射日日干| 91逼逼女人91| 日韩成人高清一区二区| 中文字幕人乱码中文字的预防方法 | 日本久久天堂| 欧美精品精品一区二区| 99re在线精品78| 91狠狠综合久久久| 日韩成人性日韩成人性爱视频在线免费观看 | 超碰在线日韩一区| 艾草av| 欧美日韩国内不卡| 国产激情视频一区区三区| 精品999日本| 亚洲高清无码免费观看视频| 国产肏逼网站| 国产区性爱在线视频秋霞豆| 五月色综合| 9999九九九久久久| 国产九九久久久精品| 欧美综合第一| 中文久久爆乳| 人人操人人摸avav| 舔人妻中文免费视频| 蜜臀久久99精品久久综合| 久久伊人亚洲AV无码网站| 高潮9999外国| 久久久久久久久久久久黄色 | 欧美97在线观看| 免费一级特黄特色大片在线观看看 | 亚洲老司机123专区| 亚洲丝袜色| 国产成人一级av88| 人人操人人爽人人操人人| 正宗无毛一线天嫩逼| 神马久久久久久久久久久久| 婷婷六月色| 欧美日韩不卡a片| 欧美色就是色| 色97欧美| 婷婷五月天无码 | 欧美很很操视频| 亚洲精品国产熟女久久久| av在线人气| 香蕉综合网| ,成人免费啪啪视频| 亚洲图片91| SS久久| 91丝袜美女国产| 亚洲精品三| 亚洲日韩国产欧美综合v| 性色av大全| 操国产逼| 日韩操p| 天天看天天日| 天天操天天舔| 极品肉射| 亚洲精品人体| 日本一区二区三区四区五区六区七区八区九区 | 青青操97| 精品无码久久久| 调教熟妇 久久久久久| 婷婷五月天伊人| 亚一综合久久久久久久久久| 色黄污美女啪啪啪免费网站| 中文字幕第9页萱萱影音先锋| 视频不卡中文字幕| 97亚洲欧美| 夜夜黄| 好涩综合| 日本999精品| 97精品国产精品免费观看| 蜜桃色院一区久久| 国产女人9999| 欧美日韩人妻精品一区二区三区| 在线情色电影 91大 | 久久91| 亚洲无线观看久久| 狠狠爱大香蕉| 日日操夜夜操天天操免费观看麻豆| 国产精品网址| 久久双插| 无码高清专| 91久久久久久| 91青视频| 国产一区二区三区不卡手机在线| 亚洲在高跟鞋自慰久久在色线| 天美欧美国产| 2019亚洲男人天堂| 九热中文字幕| 欧洲亚洲国产综合在线| 国产九九九九九九九九| 成人AV素股で擦久久| 欧美乱妇狂野欧美在线视频| 天天操熟妇| 热思思免费视频| 亚洲高清国产理伦片| 色久桃花影院在线观看| 欧美成97爱| 久艾草在线精品视频在线观看| 操B在线观看| 五月丁香网站| 亚洲熟久久| 9丨久久九九九| 日本人妻中文字幕 | 97高清啪啪| 中文一区二区| 亚洲中文字幕在现观看| 中国乱伦一区二区| 亚洲欧美性生活| 亚洲欧洲日韩中文字幕一区| 国产精品黄色三级av| 屌逼麻豆| 国产精品伦理| 国产黄色 A 片免费看| 九色97| 亚洲第一页综合在线| 中文乱码字字幕在线第5页| 在线国产福利网址导航| 亚洲 综合 欧美| 青青伊人加勒比海| 精品99999| 国模精品一区二区三区苹果色戒 | 色九九九九| 日韩精品啪啪啪| 日韩欧美午夜视频在线| 欧美久久草熟女| 暴力av在线| 国产精品无套内谢| 久久亚洲不卡一区二区三区| 特色a在线上| 女人被添高潮免费视频| 97精品久久久久中文字幕| 九九九热| 大香蕉碰碰| 蜜臀99久久精品| 手机在线中文字幕国产| 九九99久久| 夜夜嗨免费视频| 无码av永久免费专区网站| av操操不卡| 日日超碰亚洲| 懂色AV中文| 亚洲性爱成人| 欧美日韩免费专区在线| 欧美色涩| 国产精品 午夜福利| 中文操逼字幕| 精品视频专区| 青娱乐欧美激情一区二区| 顶级少妇BT天堂| 亚洲色综合| 久久久com| 91少妇| 色呦呦、国产精品| 深夜福利黄片| 男人的天堂成人的社区| 99999亚洲另类| 欧美刺激色黄片免费看| 亚洲综合一| 另类 日韩 熟女| 久久风骚城市| 中文字幕永久在线| 2017天天操| 日韩一区二区熟女| 久久国产逼| 97超碰免费人人性爱| 国产一区自拍欧美日韩| 久久久久久久六六| 99久久久无码精品国产人| 1024手机看片欧美日韩| 91天堂色男人的天堂| 玖玖无码超碰| 极品五月天噜噜| 综合伊人网12色| 日韩天天本| 这里都是精品在线观看| 五月婷亚洲精品天堂| 成人老鸭窝人人在线视频| 亚洲国产精品9999在线观看| 欧美黑人91| 激情久久久| 欧美色网| 果冻传媒一区二区三区| 在线 制服丝袜中出 人妻| 欧美后入| 中文字幕在线2| 99无码视频| 国产精品人妻无码久久久老鸭窝| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 国产乱码久久| 性爱视频无打码在线观看| 自拍第一页| 99re6久热只有精品6在线直播| 国产精品人人爽人人做可爱福利| 九九超碰综合网| 97天天搞在线| 日本色色色视频| 久久日本熟妇熟色一区| 天天天天天天天天综合| 国产女上位好爽在线| 在线国产福利网址导航| 亚洲97在线观看| 一区二区亚州激情久婷婷欧美| 婷婷日韩一区二区三区中文字幕在线| 免费?级毛片无码?∨蜜芽试看| 桑老女人九区| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 五月香婷婷| 色色色日本| 综合欧美色图| 久日综合网| 欧美人妻精品| 久久久久国产精品片区无码直播| 日本孕妇一区二区视频操逼免费看 | 六月天婷婷| 亚洲蜜乳av| 亚洲麻豆av一区二区| 欧美人妖内射| 久9综合在线| 日韩欧美天天爽爽爽天天爽爽 | 韩日色费| 性色av大全| 人妻夜夜爽天天爽三区麻豆AV网站| 亚洲清纯唯美| 欧美草草| 亚洲综合骚逼| 中文字幕女同在线| 91亚州欧美| www.操| 99热超碰| 国产丝袜视频| 超碰99在线观看| 日本精品第一视频在'| 国产亚洲中文不卡二区| 另类TS人妖一区二区三区| 日产操逼| 亚洲欧美成人网站AAA| 91精品丝袜久久久久久| 综合少妇网| 久久久久久中文| 中文字幕午夜精品久久久| 丰满欧美放荡少妇在线| 吊色| 免看60秒涩涩视频| 亚洲做性| 久9爱精品| 成人无码欧美一级A片狼牙直播| 在线观看午夜婷婷久久久久清性观看| 欧美 日韩 婷婷 五月| 乱理日韩中文| wwe 天天干.com| 骚逼一区二区| 九九九九九九九九九五码| 亚洲s色图| 本道在线| 亚洲少妇综合| 97日韩| 好爽免费视频| 国产精品视频91久久| 日韩在线性爱免费视频| jizz啪啪| 综合伊人激情| 天天躁日日躁xxxxx| 操逼操逼逼操操逼91| 精品在线观看视频在线| 色婷婷激情| 91精品电影18| 国产老熟女| 性爱AV天堂| 亚州五月| 中文乱码字字幕在线第5页| 国产AAAAAABBBBB| 美女写真| 九九久久首页| 人妻无码一区二区三区久久99| 欧美后入式| 欧美男人天堂| 韩国黄片aaaa| 久久久一区二区三区四曲免费听| 99999精品成人| 蜜臀一二三| 国产精品久久久久婷婷二区次| 精品无码欧美三级| 无码操逼网| 日本高清电影欧美色图| 99re这里| 日韩小电影| 日本不卡高清视频| 韩国久久97| 精品人妻无码一区二区三区不卡-精品人妻无码一区二区...|精品少妇一区二区三 | 国产精品欧美激在线| 99精品久久久久久| 97超碰人人操人人操| 国产色精品午夜大片| 五月丁香婷婷综合| 国产熟女少妇一区| 五月天加勒比啪| 国产福利合集| 欧美日韩在线国产在线| 野狼激情网| 亚洲极品| 日韩性爱视频在线免费观看| 97人人草| 超碰在线1234区| 草草草视频在线免费看| 亚欧性爱在线无码| 啊啊啊不要啊啊受不了了视频在线| 国产农村妇女毛片精品久久| 一级特黄aaa大片在线观看成人一级片在线观看| 亚洲中文字幕三级在线| 天天拍天| 国产特级毛片AAAAAA高潮流水| 射 色综合| 亚洲九九视频| 亚洲AV无码国产成人| 日本男人插女人的逼黄色| 久久久97| 久久综合婷婷| 日1区2区3区2020| 黄在线| 97色97好| 欧美激情1区| 人人天天干干| 99re69| 国产一区二区二区按摩精品啪视频| 人妻熟女av国产网站| 久久久久大香青草精品综合| av网站国产主播在线| 欧美少妇熟女| 中文乱码字幕观看视频| 激情专区综合| 少妇九九九九| 国产树林里野战在线看| 大香蕉青青9| 精品国产一区二区三区香蕉欧美| 有码免费观看| 亚洲无992tv| 国产少妇与亚洲av| 国产精品一区二区三区四区五区| 超碰九色| 青青青在线高清视频在线一二三四区| 激情五月天丁香社区| 中文字幕精品亚洲熟女| www色日本| 蜜桃传媒视频第一区入口在线看| 日韩乱插| 色噜噜人妻av中文字幕| 婷婷色综合| 亚洲欧美黄| 色噜噜人妻av 中文字幕| 网友自拍第一页| 亚洲熟妇乱女区二区三区| 亚洲欧美日韩制服另类| 久久精品免视看国产成人﹣蜜臀av一区. 久久精品免视看国产成人,蜜臀av一区 | 天天操狠狠日夜夜干超碰撸com视频在线观看 | 日韩一级二级三级| 熟妇在线视频一区二区| 麻豆av一区二区| 中文字幕一区 二 区 三 四 五 区日 日 骚 | 中国熟女91| 探花激情视频| 亚洲在线综合| 亚洲精品视频在线播放| 男人精品区| 成人影 天天操 亚洲| 欧美一区二区一级岛国大片| 精品无码久久久久| 国模吧 一区二区三区| 欧美成人性活片| 青青草黑寡妇男人天堂| 口爆吞精在线观看| 超碰色97| 99热在线不卡| 手机看片1024你懂的国产| 久久久精精精| 天美传媒国产原创中文字幕亚洲欧美另类 | 婷婷五月天影院| 天天综合中文字幕 91| 青青色综合| 热99这里只有精品| 欧美97爱| 人妻黑丝袜电影| 97色色视频| 蜜乳成人AV| 超碰97综合网| 国产玖玖| 乱伦熟女论坛| 素人伊尹大香蕉免费下载视频| 日韩亚洲美州欧洲综三区一品在线| 黄色av网站在线播放| 国产白丝网站| 久久久性爱视频| 国产福利精品最新在线| 日韩av性爱在线播放| 欧美日韩系列| 成人日本精品九区| 99婷婷| 欧美性爱日韩高清| 综合九九| 影音综合网| 久久婷婷伊人| 精品国产一区二区三区香蕉欧美| 91色夜| 射丝袜大香蕉| 91大神电影天堂| 欧美一区二区三区日韩| 日韩美女啪啪一区| 97香蕉网| 欧美九九九| 美女干逼2| 婷婷国产精品九区| www.人人cao| 亚洲国产精品9999在线观看| 欧美加勒比| 日韩97超碰| 国产AV天美传媒一区二区三区 | 福利社区午夜一区二区| 超清中文乱码字幕| 91精品久久久久| 四虎在线免费视频| 欧美日韩电影一区二区| 操人妻少妇中文 | 亚洲图片欧美91N| 五月天婷婷综合网| 久综合网| 日本激情免费大片| 久久日本熟妇熟色一区| 性感美女91影视| 色99久草| 五月天AV资源| 国模91| 中文字幕诱惑制服人妻丝袜美丝袜美| 91成人在线| 久久99国产综合精品女同| 操久久久久久| 亚洲精品aa久久伊人| 人妻系列无码专区中文有码| 亚洲 欧美 制服 另类 自拍| 伊人网免费视频| 成人青青草原伊人| 欧中美三级一区二区三区| 人妻喷水| 一本久久久精品| 亚洲欧洲日韩中文字幕一区| 欧美色图99| 天天久久久久久| 78精品在线| 天天综合网合集91| 97干天天| 久久人妻无码毛片A片麻豆| 久久日本熟女精品一区| 一区二区三区色综合| 天天插夜夜爽| 99re在线视频国产| 熟女熟妇伦久久影院毛片一区二区| 亚洲高清在线se| 欧美色图人妻| 久夜操| 欧美 亚洲 第一页 | 91人妻素女| AAA久久| 极品五月天噜噜| 欧美内射少妇| 精品无码久久久久| 乱操9999| 欧美天天弄| 国产精品蜜臀久久久久无码AV| 天天综合欧美| 国产999精品久久久| 亚洲天堂欧美| 久久久久久久九九九九九九| 国产精品一级片在线看| 午夜精品探花| 日韩久久三区| 欧美日本天堂| 熟妇高潮二区三区| 青青草好吊色| 国产丝袜欧美在线视频| 久久精品国产亚洲AV嘿嘿| 九九无码视频| 久久国产三区| 日影院久久婷婷夜夜网| 亚州黄站| 黄色片A级一区二区三区| 亚洲日韩国产欧美综合v| 老鸭窝亚洲毛片| 九一性生活免费视频| 男人的天堂三级| 国产精品久久久久久久久久久久| 久久riav中文精品| 啊灬啊灬啊灬好深灬快高潮了动漫-国产字幕国产在线观看-B049AV | 蜜臀久久99精品久久久| 色图综合网| 欧美性爱伊人| www.高清无码诱惑一区.com| 91精品导航| 最新日韩黄片| 欧美72网页| 亚洲丝袜诱惑| 99久久婷婷国产综合精品草原| 国产精品网站www| 成人性交午夜免费片| 丰满岳乱妇一区二区三区| 六月色婷婷| 色偷综合| 麻豆国产精品午夜视频| 九九香蕉网| 精品少妇一区二区三区免费观看| 四虎在线观看网站| 亚洲一区二区三区春色| 日韩成人网址| 亚洲综合夜色| 性饥渴少妇av无码毛片| 亚洲高清无码在线桃色| 狠狠搞 亚洲91| 亚洲色91| 任你艹| 91亚.色| 国产一区二区精品久久99| 国产日韩精品一区二区三区| 国产精品乱码久久久、久久| 国内精品久久人妻性色av| 国产超碰国产97| 上床啊啊啊| 婷婷五月天色色| 夜夜狠狠躁日日躁色视频| 人妻夜夜爽天天爽三区麻豆AV网站| av凤凰久久久| 欧美第二页午夜| 欧美天天干| www.高清无码诱惑一区.com | 精品人妻伦一区二区三区久久| 手机在线播放国产福利| 极品后入免费视频| 亚洲乱色熟女一区| 天天综合有色网| 91精品人妻偷情| 97人人中文网| 加勒比中文av| 久久黄黄| 国产精品操| 国产又色又爽又舒服的三级视频| 少妇人妻激情四射| 首页中文字幕中文字幕免费| 性性久久| 黑丝自慰喷水网站| 四虎在线免费视频| 亚洲图片日本AⅤ欧美在线| 日韩二三区| 国产一区二区在线播放量| 97这里都是精品| 五十路六十路素人熟女| 国语人妻精彩刺激| 操国产高清| 99re3这里只有精品| 女生91网站| 五月婷婷激情| 欧美日韩在线视频网站| 日韩一级二级在线| 交换娇妻呻吟声不停中文字幕| 区一二区日韩亚洲乱码av电影| 国产女同视频在线播放| 校园春色综合香蕉| 色欲日韩欧美在线一区| 久久久涩| 欧美大香蕉卡久久| 欧美在线天堂| 91伊人影视综合| 色伊人91| 男人的天堂视频精品乱在线| 亚洲精品视频在线| 9色国产精品一区粉嫩| 色拍偷亚洲| 青青草原人妻| 乱伦系列一区二区| 男女啪啪啪18禁网站| 亚洲se电影| 欧美亚洲一区二区久久久婷精品大包诱| AA特级绝黄| 精品免费视频国产一区| 青青草好吊| 丝袜综合| 91 刺激在线| 韩国成人精品久久久免费看| 人妻丝袜日本| 超碰是碰在线观看| 91骚妇| 国产剧情一区在线观看| 国产精品激情久久久久久久| 欧美在线播放| 亚洲少妇视频| 超碰一区二区| 91总综合网| 性感女人网页在线观看视频| www…国产操逼| 蜜乳Av成人片网站| 亚洲婷婷丁香在线| 久久精品国产亚洲粉嫩| 呦女网站| 亚洲自拍一区夜夜操| 99热综合在线| 天天干,天天日| 色青青久久影视| 欧美成人四级在线播放| 操b在线观看| 欧美日韩1234| 大香久久| 97色欧洲| 亚洲不卡一| 色香欲天天天天综合色| 欧美一区二区成人一卡| 大香蕉免| 翘臀vidoes| 91美女丝袜诱惑视频| 国产免费永久精品无码| 国产精品久久久久久片| 欧美精品99久久久**| 日本1区2区不卡视频| 国产综合色精品在线观看| 亚洲天堂男人网| 凌辱美少妇久久aV| 精品1区2区3区| 欧美亚洲中文字幕| 欧美色图99| 久久久久女教师免费一区| av天堂加勒比| 女人香蕉久久毛毛片精品| 亚洲色图欧美色图在线播放| 久久久久久免费电影| 国产97综合| 天天综合~91| 怡红院成人视频| 五月天亚洲色图| 操国产高清| 欧美福利视频啊啊啊啊| 国产精品高清2021在线| 欧美人人曰人人操人人射射| 久热在线精品免费观看| 亚洲 欧美综合| 免费看日本操逼视频| 天天色播| 国产欧美日韩在线观看麻豆传媒公司| 99热这里| 91在线视频免费中出| 大奶尤物鲍汁淫荡欧美视频粉嫩夜夜骚| 超碰97最新人妻| 国产精品九九| 天天夜夜rb|