Day 32 的 smtp server 連線問題

因為大家可能都會遇到,所以先貼出來我的解決方法,免得大家浪費時間除錯、測試。

我是使用 google gmail ,所以使用其它 smtp server 的人可能會不一樣,這僅供參考。

老師是使用 TLS 連線加密,程式如下:

to_email = "someone@gmail.com" # 要確定能收
my_email = "myemail@gmail.com" # 你要登入使用的 email account
password = "p@ssw0rd"  # 正確的密碼
connection = smtplib.SMTP("smtp.gmail.com")  # 連上我的 email smtp server
connection.starttls()  # 使用 TLS 加密
connection.login(user=my_email, password=password)
connection.sendmail(from_addr=my_email, to_addrs=to_email, msg="Hello!")
connection.close()

結果連線出現問題,依照老師的步驟檢查:

  1. 我的 email、password、.smtp server(我用 smtp.gmail.com),都正確。
  2. gmail account 設定,開啟低安全性應用程式存取、手機登入帳戶[關閉]、兩步驟驗證[關閉]

開啟低安全性應用程式存取步驟如下:
image4

image3

結果還是出現錯誤: 遇到大概有下列幾個錯誤訊息:

不支援 TLS

connection.starttls()
smtplib.SMTPNotSupportedError: STARTTLS extension not supported by server.


這個錯誤是我的 avst 防毒造成的,暫停10分鐘就 pass 了。

connection = smtplib.SMTP_SSL(“smtp.gmail.com”)
ConnectionResetError: [WinError 10054] 遠端主機已強制關閉一個現存的連線。


也可能是 avst 防毒的關係

server.login(my_email, password)
smtplib.SMTPNotSupportedError: SMTP AUTH extension not supported by server.


開了高安全性或 .sendmail() 中的資料錯誤

connection.sendmail(from_addr=my_email, to_addrs=my_email, msg=“Hello!”)
smtplib.SMTPSenderRefused: (550, b’No SMTP server defined. Use real server address instead of 127.0.0.1 in your account.’, …)


所以程式改用了 SSL 連線加密,開啟低安全性應用程式存取,關閉防毒,就 OK了。

import smtplib

to_email = "someone@gmail.com"     # 正確的 email
my_email = "me@gmail.com"   # 正確的 email
password = "P@ssw0rd"   # 正確的 password
connection = smtplib.SMTP_SSL("smtp.gmail.com")  # 改用 SSL
connection.login(user=my_email, password=password)
connection.sendmail(from_addr=my_email, to_addrs=to_email, msg="Hello!")
connection.close()

所以總結是 : 目前 gmail 不能用 TLS,請改用 SSL

如有錯誤,還請大家指正。

4 Likes

我運氣比較好,用老師的程式沒遇到問題。
你最上方的程式好像沒有 connection.login?中段的 login 用的又是 server 物件而不是 connection 物件,無法看出原始 starttls 失敗的程式全貌,不確定是誤植還是甚麼問題。

很感謝您耐心看完,
在這麼小的編輯視窗打那多字實在很不容易(修正了2次還是有錯)。
為了讓程式清爽,刪掉了程式中的多餘註解及改掉個資,
那個 connection.login(),就這樣不小心被刪了(已修正)

在測試時,我開了3個檔分別測 TLS、SSL及不加密。connection 用了不同的名稱,
切來切去才不會混亂,作筆記就直接 copy/paste了。

如果是像這樣寫: 也太突兀了

connection.starttls()
server.login(user=my_email, password=password)

pycharm 右上角的紅色錯誤就會出現,硬跑 錯誤訊息也不一樣了。


我的環境是 win10,裝了 avast。

不知道您的有不一樣嗎?

如果可以,想看看您的程式和我有何差異。讓我再跑一次。

我的程式如下,基本上就是老師的程式:

import smtplib

MY_EMAIL = "from@gmail.com"
MY_PASSWORD = "pwdoffrom"

connection = smtplib.SMTP("smtp.gmail.com")
connection.starttls()
# 文件提到要加 connection.ehlo(),但我沒加也沒問題
connection.login(user=MY_EMAIL, password=MY_PASSWORD)
connection.sendmail(
    from_addr=MY_EMAIL,
    to_addrs='to@gmail.com',
    msg="test"
)
connection.close()

Windows 10, Microsoft Defender Only…
Python 3.8.2

綜合前述幾個錯誤訊息:
smtplib.SMTPNotSupportedError: STARTTLS extension not supported by server.
ConnectionResetError: [WinError 10054] 遠端主機已強制關閉一個現存的連線。
smtplib.SMTPNotSupportedError: SMTP AUTH extension not supported by server.
smtplib.SMTPSenderRefused: (550, b’No SMTP server defined. Use real server address instead of 127.0.0.1 in your account.’, …)

感覺是網路(ex. proxy)問題,否則應該不至於把 smtp server 指到 127.0.0.1,
的確也有可能是防毒軟體郵件防護功能造成的問題。

我單純只是要表達應該不是程式本身的問題,而很可能是電腦環境的問題。
bug 就是這樣,我模擬不出來,也只能瞎猜就是了 :stuck_out_tongue:

1 Like

和您的程式沒有差異,

我又再試了一次,防毒是開的。

用 Day-32-287 的測 TLS、Day-32-290 的測 SSL

使用 TSL,出現不支援錯誤

smtplib.SMTPNotSupportedError: STARTTLS extension not supported by server.

使用 SSL

ConnectionResetError: [WinError 10054] 遠端主機已強制關閉一個現存的連線。

關了防毒: 全過了! :cold_face: :see_no_evil:

真的無語了!

現在回想一下,可能在第一次出現 STARTTLS extension not supported by server 時,

有參考了 Check Gmail through other email platforms - Gmail Help

其中 Step 2: Outgoing Mail (SMTP) Server : Requires TLS: Yes (if available) 有這樣的一句。

就覺得可能 Gmail 現在不支援 TLS 了
(因為 if available 就有可能 not available)

所以改用 SSL。

其後有再同時測 TLS 也沒有成功,是什麼原因,實在找不出來了。

上面的第一篇發文,我就不改了。讓大家看看這個討論的過程,要細心求證才是,千萬別像我 :rofl:

非常感謝騎士大人 :+1:

1 Like

本週進度終於到 Day 32了。非常感謝 rabrus & LancelotLiu,為了不打擾兩位,我就不 tag了。

我覺得這樣的討論才是最珍貴的,感謝 rabrus 的大器,留下原始文讓我們知道原委。同時也學會 SSL 的連線處理方式。

再次感謝! :heart: