如何使用 Python 的 Flask 框架接收電子郵件
已發表: 2020-04-30雖然 Internet 上有很多關於發送電子郵件的教程,但關於如何配置應用程序來接收和處理它們的教程卻很少。 如果您嘗試自己設置所有內容,這是一項非常困難的任務,但使用 Twilio SendGrid 的入站解析功能時,它就像接收 Web 請求一樣簡單。
在這個簡短的教程中,您將學習如何使用 Python 和 Flask Web 框架讓 Twilio SendGrid 將您的電子郵件直接轉發到您的 Web 應用程序。
要求
這些是完成本教程的要求:
- Python 3:如果您的操作系統不提供 Python 3 解釋器,您可以前往python.org下載安裝程序。
- Twilio SendGrid 帳戶:如果您是 Twilio SendGrid 的新手,您可以創建一個免費帳戶,它允許您每天永遠發送 100 封電子郵件。
- 您將在其上接收電子郵件的域:在本文中,我將使用yourdomainhere.com 。 您需要將其替換為您自己的域名。
- ngrok :我們將使用這個方便的實用程序將您計算機上本地運行的 Flask 應用程序連接到 SendGrid 可以向其發送請求的公共 URL。 這對於應用程序的開發版本是必要的,因為您的計算機可能位於路由器或防火牆後面,因此無法直接在 Internet 上訪問。 如果您沒有安裝 ngrok,您可以下載適用於 Windows、MacOS 或 Linux 的副本。
域認證
在 Twilio SendGrid 可以接受您域上的電子郵件之前,您必須對其進行身份驗證,以便 Twilio SendGrid 知道該域在您的控制之下。
啟動域認證
要驗證您的域,請登錄您的 SendGrid 帳戶,然後在左側導航欄中打開“設置”,然後選擇發件人驗證。
在發件人身份驗證頁面中,單擊“域身份驗證”部分中的“開始”按鈕。
系統將要求您選擇 DNS 提供商,在大多數情況下,該提供商與您購買域的公司相同。 如果您的 DNS 提供商未出現在列表中,或者您不知道他們是誰,只需選擇“我不確定”。
然後,系統會詢問您是否為外發電子郵件中出現的鏈接添加品牌。 這不是我們目前關心的話題,所以選擇“否”。 如果您想使用它,您可以在以後啟用此選項。
單擊“下一步”按鈕繼續到下一頁。
在接下來的頁面中,您將被要求提供您的域名。 我輸入了yourdomainhere.com ,您需要輸入您打算使用的域。 您無需更改“高級設置”部分中的任何內容。
單擊“下一步”按鈕繼續。
該頁面現在將顯示 3 個您需要添加到域配置中的新 DNS 記錄,每個記錄都有一個類型、一個主機名和一個值。 為方便起見,主機和值都可以復製到剪貼板。 您可以在下面看到我給出的設置。 您的將是相似的,但其中包含您自己的域名:
將 DNS 條目添加到您的域
下一步將根據您的 DNS 提供商而有所不同。 訪問您的域的配置頁面並找到編輯 DNS 設置的位置。
下面的屏幕截圖適用於Google Domains 。 您可以在下圖中看到我如何添加三個 DNS 記錄中的第一個。 請注意,名稱為@、 ftp和www記錄的 3 條記錄與本教程無關,並且已在我的域中設置。
請注意輸入 DNS 記錄名稱的方式。 雖然一些提供商希望您的 DNS 記錄有一個完全限定的名稱,如 SendGrid 所示,但其他提供商只希望域名之前的部分。 例如,SendGrid 顯示為em3329.yourdomainhere.com的記錄必須在 Google Domains 上輸入為em3329 。 檢查您的其他 DNS 記錄,並在輸入這些新記錄時保持一致。
以下是我輸入 3 條新 DNS 記錄後的樣子:
域驗證
現在返回到 SendGrid發件人身份驗證頁面,您的域將顯示為待處理。 單擊它以繼續進行身份驗證過程。
在下一個屏幕中,您將看到 3 條 DNS 記錄。 單擊頁面右上角的“驗證”按鈕,讓 SendGrid 提取您的 DNS 記錄並確認您已添加請求的條目。
如果 SendGrid 能夠驗證您的域,您將獲得“成功!” 頁:
另一方面,如果 SendGrid 無法驗證您的 DNS 條目,您將需要稍後再試。 每次進行 DNS 更改時,更改在 DNS 服務器之間傳播都需要一些時間。 編輯 DNS 條目後立即失敗僅意味著您需要再給它一點時間,然後再點擊“驗證”按鈕。 請注意,DNS 完全傳播最多可能需要 48 小時,但通常需要的時間要少得多。
一旦你得到“它成功了!” 頁面,您正在順利將電子郵件發佈到您的 Flask Web 應用程序。
Flask 電子郵件應用程序
現在我們準備編寫一個簡單的 Flask Web 應用程序,SendGrid 可以在其中轉發我們的電子郵件。
創建 Python 虛擬環境
遵循 Python 最佳實踐,我們將為我們的項目創建一個單獨的目錄,並在其中創建一個虛擬環境。 然後我們將在其上安裝 Flask 框架。
如果您使用的是 Unix 或 Mac OS 系統,請打開終端並輸入以下命令來執行上述任務:
如果您在 Windows 上遵循本教程,請在命令提示符窗口中輸入以下命令:
傳入電子郵件路由
現在讓我們編寫一個接收傳入電子郵件的 Flask 應用程序。 完整應用程序的代碼如下所示。 將此代碼放在名為app.py的文件中。
該應用程序只有一個連接到/email URL 的 Web 路由。 我們將讓 SendGrid 調用此路由以將傳入的電子郵件傳遞給我們。 他們發送的請求將包含與作為標準 HTTP 表單帖子發送的電子郵件相關的所有詳細信息。 這意味著我們可以從 Flask 輕鬆地從 `request.form` 字典中訪問所有這些詳細信息。
以下表單變量特別有趣:
- `request.form['from']`:電子郵件的發件人
- `request.form['to']`:電子郵件的收件人
- `request.form['subject']`:電子郵件主題
- `request.form['text']` 純文本格式的電子郵件正文
- `request.form['html']` HTML 格式的電子郵件正文
請注意,這些不是 SendGrid 提交的唯一字段。 查看SendGrid 文檔中的完整電子郵件參數列表。
由於處理電子郵件很大程度上依賴於每個應用程序,對於示例 Flask 應用程序,我們所做的就是將電子郵件字段打印到控制台。
保存app.py後,您可以按如下方式啟動 Flask 應用程序:
該應用程序現在正在運行並偵聽傳入的請求,但只能從您自己的計算機訪問。 暫時讓應用程序在您的終端窗口上運行。 在下一節中,我們將把它公開給 Internet。
SendGrid 入站解析 webhook
本教程的最後一部分是配置 SendGrid 以將您域中的傳入電子郵件轉發到 Flask 應用程序。
開始 ngrok
ngrok 工具創建一個公開可用的 URL 並將其映射到本地運行的應用程序。 這是用於在 Internet 上公開服務以進行開發和測試的常用技術。 一旦您的 Flask 應用程序完成,您將在適當的服務器上部署它以進行生產,這將不再需要。
如果您還沒有,請在您的系統上安裝ngrok 。 保持 Flask 應用程序運行並打開第二個終端窗口以啟動 ngrok,如下所示:
這告訴 ngrok 創建一個從公共 Internet 到我們本地機器的端口 5000 的“隧道”,Flask 應用程序正在那裡等待 Web 請求。 ngrok 的輸出將如下所示:
注意 ngrok 屏幕中以“Forwarding”開頭的行。 這些顯示了一個隨機生成的公共 URL,ngrok 使用該 URL 將請求重定向到我們的服務。 我們將使用https:// URL,因為它使用加密。
使用 SendGrid 註冊 webhook URL
返回到SendGrid 儀表板,在 Settings 下選擇Inbound Parse ,然後單擊“Add Host & URL”。
在下一頁中,輸入您將在其上接收電子郵件的子域。 這可以是您的域上尚未使用的任何子域,或者如果您希望直接在頂級域上接收電子郵件,則可以將其留空。 在下圖中,我使用了子域parse ,這意味著 SendGrid 接受的電子郵件將具有格式 < any>@parse.yourdomainhere.com 。 將子域字段留空將允許 SendGrid 接受<anything>@yourdomainhere.com的電子郵件,這在某些情況下可能更可取。
接下來您必須選擇您的域名。 這是一個下拉列表,顯示您已使用 SendGrid 驗證的所有域。 如果您是第一次這樣做,您將只會看到您之前驗證過的域。
以下字段用於您的 webhook的目標 URL 。 這是由 ngrok 生成的 URL,附加了 Flask URL /email 。 就我而言,這是https://bbf1b72b.ngrok.io/email 。 您將有一個類似的 URL,但 ngrok 主機名的第一部分將有所不同。
單擊“添加”以配置您的 webhook。
現在,您將在 Inbound Parse 主頁面中看到您的 webhook 的條目:
注意:每次 ngrok 停止和重新啟動時,ngrok URL 都會更改,因此在開發過程中,您需要編輯 webhook 以在每次重新啟動 ngrok 時更新 URL。 當您部署 webhook 以供生產使用時,您將直接將其託管在公共 URL 上,因此不會使用 ngrok。
註冊解析子域
您在上一節中選擇接收電子郵件的子域需要在您的域的 DNS 配置中使用“MX”記錄進行定義。 此記錄的值對於所有 SendGrid 客戶都是相同的:`mx.sendgrid.net.`(注意“net”後面的尾隨點)。
在我的 Google Domains DNS 配置中,我將解析子域定義如下:
回想一下,根據您使用的域提供商,您可能需要輸入此 DNS 記錄的完整主機名,因此在這種情況下,它將是parse.yourdomainhere.com 。
如果您決定在上一節中不定義子域,那麼您的主機名將是yourdomainhere.com ,對於某些 DNS 提供商,它必須以“ @”形式給出。
請記住,此 DNS 更改也需要傳播,因此您可能無法立即接收電子郵件。
發送測試電子郵件
當您的 Flask 應用程序和 ngrok 都在運行時,打開您的電子郵件客戶端並發送一封測試電子郵件。 在“收件人:”字段中,您可以輸入您想要的任何用戶名,因為 SendGrid 會捕獲所有用戶名。 @ 之後的內容必須是您完整的電子郵件接收域。
在下面的示例中,我向[email protected]發送了一封電子郵件:
等待一兩分鐘讓 SendGrid 接收電子郵件並將其轉發到 ngrok webhook URL,然後將其傳遞到 Flask 的/email端點。 正如您在上面看到的,我在 Flask 應用程序中編寫的簡單端點將收到的電子郵件數據打印到控制台:
就是這樣,我們現在在 Flask 應用程序中以 Web 請求的形式接收電子郵件!
生產部署
在本節中,我想指出在開發期間部署的 webhook 和那些用於生產的 webhook 之間的幾個重要區別。
沒有 ngrok 的部署
如上所述,ngrok 不是生產工具,永遠不應該在生產部署中使用。 相反,您將在直接連接到 Internet 的服務器上部署 Flask 應用程序。 Flask 文檔中討論了幾個部署選項。
Webhook 安全性
考慮到您的電子郵件接收端點在 Internet 上公開可用,因此知道 URL 的任何人都可以向它發送請求,這可能會使您的應用程序暴露於偽裝成 SendGrid 請求的惡意用戶發送的虛假調用。
防止此類攻擊的一個好方法是在 Flask 端點上實現基本身份驗證。 Flask-HTTPAuth擴展有助於實現這種類型的安全性。
如果向端點添加身份驗證,則需要在提供給 SendGrid 的 webhook URL 中包含用戶名和密碼。 我上面使用的 webhook 必須以https://username:[email protected]/email 的形式給出。
結論
儘管設置所有內容以接收電子郵件涉及很多步驟,但這是實現它的最簡單方法之一。 有關入站解析的更多信息,請查看我們的文檔頁面。
我們迫不及待地想看看您使用 Inbound Parse 構建的內容!