您當前的位置:首頁 > 詩詞

Python郵件傳送,看這篇就夠

作者:由 Cracker 發表于 詩詞時間:2019-02-20

本文為譯文,原文連結 Sending Emails With Python

本人部落格: 程式設計禪師

你可能因為想使用Python傳送電子郵件而找到了本教程。 也許你希望寫程式碼來接收郵件提醒,在使用者建立帳戶時向用戶傳送確認郵件,或向組織成員傳送郵件以提醒他們支付會費。 傳送郵件是一項耗時且容易出錯的任務,但是使用Python可以輕鬆實現自動化。

在本教程中,你將瞭解如何:

使用

SMTP_SSL()

。starttls()

設定安全連線

使用Python的內建

smtplib

庫傳送基本電子郵件

使用

email

包傳送包含HTML內容和附件的電子郵件

傳送多份包含聯絡人資料的CSV檔案的個性化電子郵件

使用

Yagmail

包只需幾行程式碼即可透過Gmail帳戶傳送電子郵件

你將在本教程結束時找到一些事務性的電子郵件服務,當你想要傳送大量電子郵件時,這些服務會很有用。

準備開始

Python內建了 smtplib 模組,用於使用簡單郵件傳輸協議(SMTP)傳送電子郵件。

smtplib

在SMTP中使用 RFC 821協議。 本教程中的示例將使用Gmail SMTP伺服器傳送電子郵件,但相同的原則適用於其他電子郵件服務。 雖然大多數電子郵件提供商使用與本教程中相同的連線埠,但你可以使用Google搜尋來快速確認。

要開始本教程,請先建立用於開發的Gmail帳戶,或者建立一個SMTP除錯伺服器,郵件將不會發送而是將其列印到控制檯中。 下面列出了這兩個選項。 本地SMTP除錯伺服器可用於修復電子郵件功能的任何問題,並確保在傳送任何電子郵件之前你的電子郵件功能沒有錯誤。

選項一: 建立用於開發的Gmail賬戶

如果你決定使用Gmail帳戶傳送電子郵件,我強烈建議你為開發程式碼設定一次性帳戶。 這是因為你必須調整Gmail帳戶的安全設定來允許從你的Python程式碼訪問,而且你也可能會意外地洩露你的登入詳細資訊。 此外,我發現我的測試帳戶的收件箱很快就填滿了測試電子郵件,這也足以讓你設定一個新的Gmail帳戶進行開發。

Gmail的一個不錯的功能是,你可以使用

+

號在@符號前面的電子郵件地址中新增任何修飾符。 例如,傳送到

my+person1@gmail。com

my+person2@gmail。com

的郵件都將傳送到

my@gmail。com

。 在測試電子郵件功能時,你可以使用此功能模擬所有指向同一收件箱的多個地址。

要建立用於測試程式碼的Gmail地址,請執行以下操作:

建立一個新的Google帳戶

將允許不夠安全的應用設定為啟用。請注意,這樣可以讓其他人更輕鬆地訪問你的帳戶。

如果你不想降低Gmail帳戶的安全設定,請檢視Google的文件,瞭解如何使用Python指令碼進行OAuth2授權來獲取訪問憑據。

選項二:建立一個本地SMTP伺服器

你可以使用Python預先安裝的

smptd

模組執行一個本地SMTP除錯伺服器來測試電子郵件功能。 它不會將電子郵件傳送到指定的地址,而是丟棄它們並將其內容列印到控制檯。 執行本地除錯伺服器意味著無需處理訊息加密或使用憑據登入電子郵件伺服器。

你可以透過在命令提示符下輸入以下內容來啟動本地SMTP除錯伺服器:

python -m smtpd -c DebuggingServer -n localhost:1025

在Linux上,在相同的命令之前加上

sudo

透過此伺服器傳送的任何電子郵件都將被丟棄,並在終端視窗中每行顯示一個

bytes

物件:

—————— MESSAGE FOLLOWS ——————

b‘X-Peer: ::1’

b‘’

b‘From: my@address。com’

b‘To: your@address。com’

b‘Subject: a local test mail’

b‘’

b‘Hello there, here is a test email’

—————— END MESSAGE ——————

對於本教程的其餘部分,我假設你使用的是Gmail帳戶,但如果你使用的是本地除錯伺服器,請確保使用

localhost

作為SMTP伺服器地址並使用埠為1025而不是埠465或587。 除此之外,你不需要使用

login()

或使用

SSL / TLS

加密通訊。

傳送純文字郵件

在我們深入傳送包含HTML內容和附件的電子郵件之前,你將學會使用Python傳送純文字電子郵件。 這些是你可以在簡單的文字編輯器中編寫的電子郵件。 沒有像文字格式或超連結這樣的奇特東西。 這些稍後你會了解到。

開始一個安全SMTP連線

當你透過Python傳送電子郵件時,應確保你的SMTP連線已加密,以便其他人無法輕鬆訪問你的郵件和登入憑據。 SSL(安全套接字層)和TLS(傳輸層安全性)是兩種可用於加密SMTP連線的協議。 使用本地除錯伺服器時,不必使用其中任何一個。

有兩種方法可以與你的電子郵件伺服器建立安全連線:

使用

SMTP_SSL()

建立安全的SMTP連線

使用不安全的SMTP連線,然後使用

。starttls()

加密

在這兩種情況下,Gmail都會使用TLS加密電子郵件,因為這是SSL更安全的後續版本。 根據Python的安全注意事項,強烈建議你使用 ssl 模組中的

create_default_context()

。 這將載入系統的可信CA證書,啟用主機名檢查和證書驗證,並嘗試選擇適合的安全的協議和密碼設定。

如果要檢查Gmail收件箱中電子郵件的加密資訊,請轉到更多→顯示原始內容來檢視“已接收”標題下列出的加密型別。

smtplib 是Python的內建模組,用於使用SMTP或ESMTP監聽器守護程式向任何Internet計算機發送電子郵件。

我將首先向你展示如何使用

SMTP_SSL()

,因為它從一開始就例項化一個安全的連線,並且比使用

。starttls()

替代方案略微簡潔。 請注意,如果使用

SMTP_SSL()

,則Gmail要求你連線到465埠,使用

。starttls()

時,要求連線到589埠。

選項1: 使用

SMPT_SSL()

下面的程式碼示例使用

smtplib

SMTP_SSL()

初始化TLS加密連線,以此來與Gmail的SMTP伺服器建立安全連線。

ssl

的預設上下文驗證主機名及其證書,並最佳化連線的安全性。 請務必填寫你自己的電子郵件地址而不是

my@gmail。com

import

smtplib

ssl

port

=

465

# For SSL

password

=

input

“Type your password and press enter: ”

# Create a secure SSL context

context

=

ssl

create_default_context

()

with

smtplib

SMTP_SSL

“smtp。gmail。com”

port

context

=

context

as

server

server

login

“my@gmail。com”

password

# TODO: Send email here

使用

with smtplib。SMTP_SSL() as server

確保連線在縮排程式碼塊的末尾自動關閉。 如果port為零或未指定,則

。SMTP_SSL()

將使用標準埠(埠465)。

將電子郵件密碼儲存在程式碼中並不安全,特別是如果你打算與他人共享。 相反,

使用input()

讓使用者在執行指令碼時輸入密碼,如上例所示。 如果你在輸入時不希望密碼顯示在螢幕上,則可以匯入 getpass 模組並使用

。getpass()

代替直接輸入密碼。

選項2: 使用

.starttls()

我們可以建立一個不安全的SMTP連線並使用

。starttls()

加密它,而不是使用

。SMTP_SSL()

一開始就建立是安全的連線。

為此,建立一個

smtplib。SMTP

例項,該例項封裝SMTP連線並允許你訪問其方法。 我建議你在指令碼開頭定義SMTP伺服器和埠,以便輕鬆配置它們。

下面的程式碼片段使用

server= SMTP()

,而不是使用

with SMTP() as server:

這個我們在上一個示例中使用了的格式。 為了確保在出現問題時程式碼不會崩潰,請將主程式碼放在

try

塊中,讓

except

塊將任何錯誤訊息列印到

stdout

import

smtplib

ssl

smtp_server

=

“smtp。gmail。com”

port

=

587

# For starttls

sender_email

=

“my@gmail。com”

password

=

input

“Type your password and press enter: ”

# Create a secure SSL context

context

=

ssl

create_default_context

()

# Try to log in to server and send email

try

server

=

smtplib

SMTP

smtp_server

port

server

ehlo

()

# Can be omitted

server

starttls

context

=

context

# Secure the connection

server

ehlo

()

# Can be omitted

server

login

sender_email

password

# TODO: Send email here

except

Exception

as

e

# Print any error messages to stdout

print

e

finally

server

quit

()

要通知伺服器讓它知道自己,應在建立

。SMTP()

物件後呼叫

。helo()

(SMTP)或

。ehlo()

(ESMTP),並在

。starttls()

後再呼叫。 此函式由

。starttls()

。sendmail()

隱式呼叫,因此除非你要檢查伺服器的SMTP服務擴充套件,否則不必顯式呼叫

。helo()

。ehlo()

傳送你的純文字郵件

使用上述任一方法發起一個安全SMTP連線後,你可以使用

。sendmail()

傳送電子郵件:

server

sendmail

sender_mail

receiver_email

message

我建議在

import

後在指令碼頂部定義電子郵件地址和郵件內容,以便你可以方便更改它們:

sender_email

=

“my@gmail。com”

receiver_email

=

“your@gmail。com”

message

=

“”“

\

Subject: Hi there

This message is sent from Python。”“”

# Send email here

message

字串以

“Subject:Hi there”

開頭,後跟兩個換行符(\ n)。 這樣可以確保

Hi there

為電子郵件的主題顯示,並且新的一個行後面的文字將被視為郵件正文。

下面的程式碼示例使用

SMTP_SSL()

傳送純文字電子郵件:

import

smtplib

ssl

port

=

465

# For SSL

smtp_server

=

“smtp。gmail。com”

sender_email

=

“my@gmail。com”

# Enter your address

receiver_email

=

“your@gmail。com”

# Enter receiver address

password

=

input

“Type your password and press enter: ”

message

=

“”“

\

Subject: Hi there

This message is sent from Python。”“”

context

=

ssl

create_default_context

()

with

smtplib

SMTP_SSL

smtp_server

port

context

=

context

as

server

server

login

sender_email

password

server

sendmail

sender_email

receiver_email

message

這是透過使用

。starttls()

加密SMTP連線傳送純文字電子郵件的一個程式碼示例。作為對照,

server。ehlo()

行可以省略,因為如果需要,它們將由

。starttls()

。sendmail()

隱式呼叫:

import

smtplib

ssl

port

=

587

# For starttls

smtp_server

=

“smtp。gmail。com”

sender_email

=

“my@gmail。com”

receiver_email

=

“your@gmail。com”

password

=

input

“Type your password and press enter:”

message

=

“”“

\

Subject: Hi there

This message is sent from Python。”“”

context

=

ssl

create_default_context

()

with

smtplib

SMTP

smtp_server

port

as

server

server

ehlo

()

# Can be omitted

server

starttls

context

=

context

server

ehlo

()

# Can be omitted

server

login

sender_email

password

server

sendmail

sender_email

receiver_email

message

傳送花哨的電子郵件

Python的內建

email

包允許你構建更多花哨的電子郵件,然後可以使用

smptlib

進行傳輸。 下面,你將瞭解如何使用 email` 包傳送包含HTML內容和附件的電子郵件。

包含HTML內容

如果你要格式化電子郵件中的文字(粗體,斜體等),或者如果要新增任何影象,超連結或響應式的內容,則使用HTML非常方便。 今天最常見的電子郵件型別是MIME(多用途因特網郵件擴充套件)多部分的電子郵件,它結合了HTML和純文字。 MIME訊息由Python的

email。mime

模組處理。 有關詳細說明,請檢視文件 。

由於並非所有電子郵件客戶端都預設顯示HTML內容,並且出於安全原因,有些人僅選擇接收純文字電子郵件,因此為HTML訊息新增純文字的替代非常重要。 由於電子郵件客戶端將首先渲染最後一部分的附件,因此請確保在純文字版本之後新增HTML訊息。

在下面的示例中,我們的

MIMEText()

物件將包含訊息的HTML和純文字版本,

MIMEMultipart(“alternative”)

例項將這些組合成一個帶有兩個備用渲染選項的訊息:

import

smtplib

ssl

from

email。mime。text

import

MIMEText

from

email。mime。multipart

import

MIMEMultipart

sender_email

=

“my@gmail。com”

receiver_email

=

“your@gmail。com”

password

=

input

“Type your password and press enter:”

message

=

MIMEMultipart

“alternative”

message

“Subject”

=

“multipart test”

message

“From”

=

sender_email

message

“To”

=

receiver_email

# Create the plain-text and HTML version of your message

text

=

“”“

\

Hi,

How are you?

Real Python has many great tutorials:

www。realpython。com”“”

html

=

“”“

\

Hi,

How are you?

Real Python

has many great tutorials。

”“”

# Turn these into plain/html MIMEText objects

part1

=

MIMEText

text

“plain”

part2

=

MIMEText

html

“html”

# Add HTML/plain-text parts to MIMEMultipart message

# The email client will try to render the last part first

message

attach

part1

message

attach

part2

# Create secure connection with server and send email

context

=

ssl

create_default_context

()

with

smtplib

SMTP_SSL

“smtp。gmail。com”

465

context

=

context

as

server

server

login

sender_email

password

server

sendmail

sender_email

receiver_email

message

as_string

()

在此示例中,首先將純文字和HTML訊息定義為字串文字,然後將它們儲存為

plain / html MIMEText

物件。 然後可以按順序將這些新增到

MIMEMultipart(“alternative”)

訊息中,並透過與電子郵件伺服器的安全連線傳送。 請記住在替代的純文字後新增HTML訊息,因為電子郵件客戶端將嘗試首先渲染最後一個子部分。

使用

email

新增附件

為了將二進位制檔案傳送到設計用於處理文字資料的電子郵件伺服器,需要在傳輸之前對其進行編碼。 這通常使用base64完成,它將二進位制資料編碼為可列印的ASCII字元。

下面的程式碼示例展示瞭如何在傳送電子郵件時將PDF檔案作為附件:

import

email

smtplib

ssl

from

email

import

encoders

from

email。mime。base

import

MIMEBase

from

email。mime。multipart

import

MIMEMultipart

from

email。mime。text

import

MIMEText

subject

=

“An email with attachment from Python”

body

=

“This is an email with attachment sent from Python”

sender_email

=

“my@gmail。com”

receiver_email

=

“your@gmail。com”

password

=

input

“Type your password and press enter:”

# Create a multipart message and set headers

message

=

MIMEMultipart

()

message

“From”

=

sender_email

message

“To”

=

receiver_email

message

“Subject”

=

subject

message

“Bcc”

=

receiver_email

# Recommended for mass emails

# Add body to email

message

attach

MIMEText

body

“plain”

))

filename

=

“document。pdf”

# In same directory as script

# Open PDF file in binary mode

with

open

filename

“rb”

as

attachment

# Add file as application/octet-stream

# Email client can usually download this automatically as attachment

part

=

MIMEBase

“application”

“octet-stream”

part

set_payload

attachment

read

())

# Encode file in ASCII characters to send by email

encoders

encode_base64

part

# Add header as key/value pair to attachment part

part

add_header

“Content-Disposition”

f

“attachment; filename= {filename}”

# Add attachment to message and convert message to string

message

attach

part

text

=

message

as_string

()

# Log in to server using secure context and send email

context

=

ssl

create_default_context

()

with

smtplib

SMTP_SSL

“smtp。gmail。com”

465

context

=

context

as

server

server

login

sender_email

password

server

sendmail

sender_email

receiver_email

text

MIMEultipart()

接受RFC5233樣式的鍵/值對形式的引數,這些引數儲存在字典中並傳遞給

Message

基類的

。add_header

方法。

檢視Python的

email。mime

模組的文件,瞭解有關使用MIME類的更多資訊。

傳送多封個性化電子郵件

想象一下,你希望向你組織的成員傳送電子郵件,以提醒他們支付他們的捐款費用。 或者,你可能希望向班級中的學生髮送個性化電子郵件,其中包含最近作業的成績。 這些任務在Python中輕而易舉。

使用相關個人資訊製作CSV檔案

傳送多封個性化電子郵件的簡單開始是建立包含所有必需個人資訊的CSV(逗號分隔值)檔案。 (確保在未經他們同意的情況下不共享其他人的私人資訊。)CSV檔案可以被視為一個簡單的表,其中第一行通常包含列標題。

以下是

contacts_file。csv

檔案的內容,我將其儲存在與Python程式碼相同的資料夾中。 它包含一組虛構人物的名稱,地址和成績。 我使用

my+modifier@gmail。com

構造來確保所有電子郵件最終都在我自己的收件箱中,在此示例中為

my@gmail。com

name,email,grade

Ron Obvious,my+ovious@gmail。com,B+

Killer Rabbit of Caerbannog,my+rabbit@gmail。com,A

Brian Cohen,my+brian@gmail。com,C

建立CSV檔案時,請確保使用逗號分隔你的值,而不包含任何的空格。

遍歷行傳送多個郵件

下面的程式碼示例顯示瞭如何開啟CSV檔案並迴圈其內容行(跳過標題行)。 為了確保程式碼在你向所有聯絡人傳送電子郵件之前正常執行。我已經為每個聯絡人列印了

Sending email to 。。。

,我們稍後可以用實際傳送電子郵件的功能替換它們:

import

csv

with

open

“contacts_file。csv”

as

file

reader

=

csv

reader

file

next

reader

# Skip header row

for

name

email

grade

in

reader

print

f

“Sending email to {name}”

# Send email here

在上面的示例中,使用

open(filename) as file

: 確保你的檔案在程式碼塊的末尾關閉。

csv。reader()

可以逐行讀取CSV檔案並提取其值。

next(reader)

會跳過標題行,接下的一行

for name, email, grade in reader

:使用Python中的解包操作,並將結果值儲存在當前聯絡人的名稱,電子郵件和成績中。

如果CSV檔案中的值包含任一側或兩側的空格,則可以使用

。strip()

方法刪除它們。

個性化的的內容

你可以使用

str。format()

填充大括號佔位符,將個性化內容放入訊息中。 例如,

“hi {name}, you {result} your assignment”。format(name=“John”, result=“passed”)

會給你

“hi John, you passed your assignment”

從Python 3。6開始,使用f-string可以更優雅地完成字串格式化,但這些需要在f-string本身之前定義佔位符。 為了在指令碼開頭定義電子郵件訊息,並在迴圈CSV檔案時填寫每個聯絡人的佔位符,使用較舊的

。format()

方法。

考慮到這一點,你可以設定一個通用訊息體,其中可以為個人定製佔位符。

程式碼案例

以下程式碼示例允許你向多個聯絡人傳送個性化電子郵件。 它會迴圈CSV檔案顯示每個聯絡人的姓名,電子郵件,成績的,如上例所示。

常規訊息在指令碼開頭定義,對於CSV檔案中的每個聯絡人,其

{name}

{grade}

佔位符都已填入,並且透過與Gmail伺服器的安全連線傳送個性化電子郵件,正如你之前看過的:

import

csv

smtplib

ssl

message

=

“”“Subject: Your grade

Hi {name}, your grade is {grade}”“”

from_address

=

“my@gmail。com”

password

=

input

“Type your password and press enter: ”

context

=

ssl

create_default_context

()

with

smtplib

SMTP_SSL

“smtp。gmail。com”

465

context

=

context

as

server

server

login

from_address

password

with

open

“contacts_file。csv”

as

file

reader

=

csv

reader

file

next

reader

# Skip header row

for

name

email

grade

in

reader

server

sendmail

from_address

email

message

format

name

=

name

grade

=

grade

),

Yagmail

有多個庫可以讓您更輕鬆地傳送電子郵件,例如 Envelopes,Flanker 和 Yagmail。 Yagmail旨在專門用於Gmail,它透過友好的API大大簡化了傳送電子郵件的過程,如下面的程式碼示例所示:

import

yagmail

receiver

=

“your@gmail。com”

body

=

“Hello there from Yagmail”

filename

=

“document。pdf”

yag

=

yagmail

SMTP

“my@gmail。com”

yag

send

to

=

receiver

subject

=

“Yagmail test with attachment”

contents

=

body

attachments

=

filename

此程式碼示例傳送帶有PDF附件的電子郵件,比我們使用

email

smtplib

傳送郵件的例子程式碼量大大減少 。

設定Yagmail時,你可以將Gmail驗證新增到作業系統的金鑰環中,如文件中所述。 如果你不這樣做,Yagmail會在需要時提示你輸入密碼並自動將其儲存在金鑰環中。

事務性郵件服務

如果你計劃傳送大量電子郵件,想要檢視電子郵件統計資訊,並希望確保可靠的投放,則可能需要檢視事務性電子郵件服務。 雖然以下所有服務都發送大量電子郵件的付費套餐,但他們還提供免費套餐,以便你可以試用它們。 其中一些免費計劃無限期有效,可能足以滿足你的電子郵件需求。

以下是一些主要事務性電子郵件服務的免費計劃概述。 單0封免費,接下來100封/天Sendinblue200 封/天Mailgun開始的10000封免費Mailjet200 封/天Amazon SES62,000 封/月 | 起初30天內40000封免費,接下來100封/天 | | Sendinblue | 200 封/天 | | Mailgun | 開始的10000封免費 | | Mailjet | 200 封/天 | | Amazon SES | 62,000 封/月 |

你可以執行Google搜尋以檢視最符合你需求的提供商,或者只是嘗試一些免費計劃,以檢視你最喜歡哪種API。

Sendgrid程式碼示例

這是一個使用Sendgrid傳送電子郵件的程式碼示例,為你提供如何使用Python的事務性電子郵件服務的方法:

import

os

import

sendgrid

from

sendgrid。helpers。mail

import

Content

Email

Mail

sg

=

sendgrid

SendGridAPIClient

apikey

=

os

environ

get

“SENDGRID_API_KEY”

from_email

=

Email

“my@gmail。com”

to_email

=

Email

“your@gmail。com”

subject

=

“A test email from Sendgrid”

content

=

Content

“text/plain”

“Here‘s a test email sent through Python”

mail

=

Mail

from_email

subject

to_email

content

response

=

sg

client

mail

send

post

request_body

=

mail

get

())

# The statements below can be included for debugging purposes

print

response

status_code

print

response

body

print

response

headers

要執行此程式碼,你必須先:

註冊一個(免費)Sendgrid帳戶

請求一個API金鑰用於進行使用者驗證

透過在命令提示符中鍵入

setx SENDGRID_API_KEY “YOUR_API_KEY”

(永久儲存此API金鑰)來新增API金鑰,或者設定

SENDGRID_API_KEY YOUR_API_KEY

以僅為當前客戶端會話儲存它

有關如何在Mac和Windows設定Sendgrid,可以在Github上的儲存庫README中找到更多資訊。

總結

你現在可以啟動安全的SMTP連線,並向聯絡人列表中的人員傳送多個個性化電子郵件!

你已經學會了如何使用純文字替代方式傳送HTML電子郵件,並將檔案附加到你的電子郵件中。 當你使用Gmail帳戶時,Yagmail軟體包可簡化所有這些任務。 如果你計劃傳送大量電子郵件,則值得研究事務性電子郵件服務。

享受用Python傳送電子郵件,但記住:請不要垃圾郵件!

Python郵件傳送,看這篇就夠

關注公眾號 <程式碼與藝術>,學習更多國外精品技術文章。

標簽: 電子郵件  email  SMTP  com  gmail