Skip to content

[Python] 使用 SMTP 模組透過 Gmail 寄信

Last Updated on 2021-04-10 by Clay

現代人的生活已經徹底脫離不了 Google 了,曾幾何時,跟指導教授寄信已經變成研究生最主要的對外聯絡手段(這非常可悲哈哈哈。)

在研究生的生涯當中,由於不斷來回切換 Linux、Windows 兩邊,所以一直苦惱於檔案備份的問題。(我其實有架 FTP 的伺服器,但由於中文編碼的問題,我的檔名一直都會怪怪的 ...... 何況由於老師的研究範圍,讓我一直脫離不了中文,我也希望檔名可以全部用英文啊!)

有次,在某個颱風天(是的,我颱風天還在處理實驗室的事情 QQ),我使用 Teamviewer 遠端連線的時候終於崩潰了!(有資料非得寄給教授不可。)

為什麼!Teamviewer 的延遲太嚴重了吧!我們老師的信件可是非常挑剔一個字都不能錯啊! 咳咳,抱歉,你什麼都沒看到。

而單純使用 Terminal ssh 進伺服器又不能寄信! (其實可以我知道,可是我不知為啥每次都被防火牆擋下來 ...... 連防火牆都要欺負我 QAQ)

最後,我終於大徹大悟,我要寫一個使用 Gmail 來寄信的程式!

於是這篇心得筆記就這樣誕生了。為了怕日後忘記,我要趕快把它紀錄在這裡。

那我們就開始吧!


SMTP

首先,如果你搜尋 "Python" 和 "Gmail",你最先看到的,一定是這個模組 SMTP

那麼,SMTP 究竟是什麼呢?

SMTP(Simple Mail Transfer Protocol),顧名思義,其實是一個『簡易郵件傳輸協定』。在 Python 中要調用這個協定、使用它來寄信,可以使用這個模組:smtplib。

這個模組是 Python 自帶的,並不需要額外透過 pip 下載。

我們首先來看該如何透過 Gmail 寄信:

# -*- coding: utf-8 -*-
import json
from email.mime.text import MIMEText
import smtplib


# Account infomation load
account = json.load(open('Account.json', 'r', encoding='utf-8'))
gmailUser = account['Account']
gmailPasswd = account['password']
to = [account['Account'], '[email protected]', '[email protected]']

# Create message
emails = [t.split(',') for t in to]
message = MIMEText('Give me a Test!', 'plain', 'utf-8')
message['Subject'] = 'Single Test'
message['From'] = gmailUser
message['To'] = ','.join(to)

# Set smtp
smtp = smtplib.SMTP("smtp.gmail.com:587")
smtp.ehlo()
smtp.starttls()
smtp.login(gmailUser, gmailPasswd)

# Send msil
smtp.sendmail(message['From'], message['To'], message.as_string())
print('Send mails OK!')


首先,我為了不透漏自己的 Gmail 地址,我使用在當前資料夾下創了 Account.json 這個檔案,裡頭分別有我的帳號密碼 XD

# Account infomation load
account = json.load(open('Account.json', 'r', encoding='utf-8'))
gmailUser = account['Account']
gmailPasswd = account['password']
to = [account['Account'], '[email protected]', '[email protected]']


所以你可以想像成 account['Account'] 是我的 Gmail 位址、 account['password'] 是我這個帳號的密碼。
to 是我所有想要寄送的對象,格式為 list。

# Create message
emails = [t.split(',') for t in to]
message = MIMEText('Give me a Test!', 'plain', 'utf-8')
message['Subject'] = 'Single Test'
message['From'] = gmailUser
message['To'] = ','.join(to)


這裡我們使用剛才 import 的 MIMEText() 輸入我們想要寄信的內容。

message['Subject']: 信件標題
message['From']: 寄件人
message['To']: 收件人

# Set smtp
smtp = smtplib.SMTP("smtp.gmail.com:587")
smtp.ehlo()
smtp.starttls()
smtp.login(gmailUser, gmailPasswd)


SMTP 就如同上面所提的,是一個簡易的郵件傳輸協定,在這裡我們使用 Gmail 的主機 ("smtp.gmail.com:587")

587 這個 Port 是 Google 自己決定的,我們也只能照用。

smtp.ehlo() 是回應傳送伺服器的指令。
smtp. starttls() 是要求加密的指令。
smtp.login() 則是登入我們的 Gmail 帳號。

# Send msil
smtp.sendmail(message['From'], message['To'], message.as_string())
print('Send mails OK!')


最後就是 sendmail() 啦。裡面只需要附上兩樣東西:寄件人和收信人。

如此一來我們就可以收到我們自己的信件了!(因為我收件人也是自己)

Send mails OK!

看到 Send mails OK! 就知道郵件已寄送了。

結果。

附帶檔案的郵件寄送

# -*- coding: utf-8 -*-
import json
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib


# Account infomation load
account = json.load(open('Account.json', 'r', encoding='utf-8'))
gmailUser = account['Account']
gmailPasswd = account['password']
to = [account['Account']]

emails = [t.split(',') for t in to]

# Create message
message = MIMEMultipart()
message['Subject'] = 'Single Test'
message['From'] = gmailUser
message['To'] = ','.join(to)

# Mail content
message.attach(MIMEText('Give me a Test!', 'plain', 'utf-8'))

# File
file = MIMEText(open('a.txt', 'r', encoding='utf-8').read(), 'base64', 'utf-8')
file['Content-Type'] = 'application/octet-stream'
file['Content-Disposition'] = 'attachment; filename=test.txt'
message.attach(file)

# Set smtp
smtp = smtplib.SMTP("smtp.gmail.com:587")
smtp.ehlo()
smtp.starttls()
smtp.login(gmailUser, gmailPasswd)

# Send mail
smtp.sendmail(message['From'], message['To'], message.as_string())
print('Send mails OK!')


最大的差別應該是這部份:

# Create message
message = MIMEMultipart()
message['Subject'] = 'Single Test'
message['From'] = gmailUser
message['To'] = ','.join(to)


我們要夾帶檔案,我們要初始化的便是 MIMEMultipart()。

然後我們在當前資料夾底下新增一個新的文件:a.txt。並在裡面寫下如下這段話:

今天天氣真好啊!
# File
file = MIMEText(open('a.txt', 'r', encoding='utf-8').read(), 'base64', 'utf-8')
file['Content-Type'] = 'application/octet-stream'
file['Content-Disposition'] = 'attachment; filename=test.txt'
message.attach(file)

# Set smtp
smtp = smtplib.SMTP("smtp.gmail.com:587")
smtp.ehlo()
smtp.starttls()
smtp.login(gmailUser, gmailPasswd)

# Send mail
smtp.sendmail(message['From'], message['To'], message.as_string())
print('Send mails OK!')


設定 smtp 以及 send mail 的流程並沒有改變,只是這次我們要夾帶檔案。

MIMEText(open('a.txt', 'r', encoding='utf-8').read(), 'base64', 'utf-8')

這部份就是把我們剛才建立好的 a.txt 放進去。

filename=test.txt

這部份的檔名可以自己取,當然你也可以就照舊取 a.txt。這影響的是你在 Gmail 當中收到的檔案名稱。

然後我們執行程式,應該會看到郵件已發送!

Tags:

Leave a Reply