利用Python 發送郵件


概要

  我們都知道SMTP(簡單郵件傳輸協議),是一組用於從原地址到目的地址傳輸郵件的規范,通過它來控制郵件的中轉方式。SMTP規定電子郵件應該如何格式化、如何加密,以及如何在郵件服務器之間傳遞。SMTP服務器就是通過遵循SMTP協議的發送郵件服務器。

  如果你使用過郵件客戶端,比如Foxmail,outlook等,那么你應該了解SMTP服務器和端口號,除了服務器和端口,我們還需要進行其他配置,默認情況下郵件服務提供商是不允許我們使用程序進行郵件發送的,如果想要使用程序發送電子郵件,就需要我們手動開啟SMTP服務,並獲取一個專用的授權碼(用於登陸)。   -- 需要自行去了解所用郵箱的授權碼獲取方式

使用smtplib和email模塊發送郵件

  得到郵箱的授權碼就可以使用Python代碼發送電子郵件了。Python標准庫有多個與郵件相關的模塊,其中smtplib負責發送郵件,email模塊用來構造郵件和解析郵件內容。

smtplib模塊

  stmplib發送郵件大概分為以下幾個步驟:

  1. 連接到SMTP服務器
  2. 發送SMTP的“Hello”消息
  3. 登陸到SMTP服務器
  4. 發送電子郵件
  5. 關閉SMTP服務器的連接

  對於簡單的郵件,smtplib的使用是非常簡單的,下面是實例

# 導入smtplib模塊
import smtplib

# 創建SMTP對象,括號內為SMTP服務器地址及端口號
smtp = smtplib.SMTP('smtp.qq.com',25)

# 向SMTP服務器打一個招呼,查看連接狀態
smtp.ehlo()
(250, b'smtp.qq.com\nPIPELINING\nSIZE 73400320\nSTARTTLS\nAUTH LOGIN PLAIN\nAUTH=LOGIN\nMAILCOMPRESS\n8BITMIME')

# 連接使用TLS加密(然后就可以傳遞敏感信息了),否則無法使用login方法登陸會提示SMTPServerDisconnected 異常
smtp.starttls()
(220, b'Ready to start TLS')

# 登陸郵箱,傳遞的是用戶名密碼
smtp.login('287990400@qq.com','oiifptyw......')    # 授權碼
(235, b'Authentication successful')

# 發送郵件
smtp.sendmail('287990400@qq.com','932911203@qq.com','Subject:this is title\n this is content')
{}

# 郵件發送完畢后關閉鏈接
smtp.quit()
(221, b'Bye')

  PS:sendmail的參數為發件人,收件人,郵件內容

  注意:可以在創建加密鏈接之前使用smtp.set_debuglevel(1),來顯示與SMTP服務器交互的相關信息

  查看發送的郵件會發送,有兩個問題,一是收件人欄為空,二是郵件內容缺失,這是因為郵件主題、如何顯示發件人、收件人等信息並不是通過SMTP協議發給MTA,而是包含在發給MTA的文本中的,所以,我們必須把FromToSubject添加到email模塊中的MIMEText中,才是一封完整的郵件。(MTA可以理解為郵件代理服務器)。

smtplib模塊結合email模塊

  使用email模塊構建一個郵件對象(Message),email模塊中支持很多郵件對象

  • MIMEText:表示一個純文本的郵件     * 常用
  • MIMEImage:表示一個作為附件的圖片
  • MIMEMultipart:用於把多個對象組合起來

  其中還有諸如其他的類:MIMEBase、MIMEAudio等。

MIMEText對象的主要參數是:MIMEText(_text, _subtype='plain', _charset=None),其中:

  • _text:表示郵件內容
  • _subtype:表示郵件內容的類型,默認為plain(純文本),還可以設置為html,表示正文是html文件(會渲染HTML標簽)
  • _charset:表示郵件編碼,默認情況下使用ascii編碼

  下面是一個發送純文本郵件的例子:

#!/usr/bin/env python3

import smtplib
from email.mime.text import MIMEText

SMTP_SERVER = 'smtp.qq.com'
SMTP_PORT = 25

def send_mail(user,passwd,to,subject,text):
    msg = MIMEText(text)
    msg['From'] = user            # 構建msg對象的發件人
    msg['to'] = to                # 構建msg對象的收件人
    msg['Subject'] = subject      # 構建msg對象的郵件正文

    smtp_server = smtplib.SMTP(SMTP_SERVER,SMTP_PORT)
    print('Connecting To mail Server')
    try:
        smtp_server.ehlo()
        print('Starting Encrypted Session.')
        smtp_server.starttls()
        smtp_server.ehlo()
        print('Loggin Into Mail Server.')
        smtp_server.login(user,passwd)
        print('Send mail.')
        smtp_server.sendmail(user,to,msg.as_string())   # 利用msg的as_string()方法轉換成字符串
    except Exception as err:
        print('Sending Mail Failed:{0}'.format(err))

    finally:
        smtp_server.quit()


def main():
    send_mail('287990400@qq.com','vgdw...ucafc','932911203@qq.com','Important','Text Message from dahlhin')

if __name__ == '__main__':
    main()
                                                                                                              

PS:利用msg對象,我們可以構建郵件的header,通過添加header信息,給郵件增加subject等參數,達到補全郵件信息的目的。msg的header添加方式和使用字典的方式相同。

帶附件的郵件

  前面說明了發送純文本郵件的方法,在使用郵件發送帶附件(圖片)的郵件時,需要使用MIMEMultipart對象,並把MIMEImage對象添加。

import smtplib
import os
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication

SMTP_SERVER = 'smtp.qq.com'
SMTP_PORT = 25


def send_mail(user, passwd, to, subject, text):
    msg = MIMEMultipart(text)
    msg['From'] = user  # 構建msg對象的發件人
    msg['to'] = to  # 構建msg對象的收件人
    msg['Subject'] = subject  # 構建msg對象的郵件正文
    msg.preamble = subject

    smtp_server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
    print('Connecting To mail Server')
    try:
        smtp_server.ehlo()
        print('Starting Encrypted Session.')
        smtp_server.starttls()
        smtp_server.ehlo()
        print('Loggin Into Mail Server.')
        smtp_server.login(user, passwd)


        # 添加圖片附件
        url = r'C:\Users\Are you SuperMan\Pictures\Saved Pictures'
        for img in os.listdir(url):

            jpgpart = MIMEImage(open(os.path.join(url,img),'rb').read(),'png')
            jpgpart.add_header('Content-Disposition', 'attachment', filename=img)    # 用於告知瀏覽器下載附件文件時的名稱
            msg.attach(jpgpart)


        print('Send mail.')
        smtp_server.sendmail(user, to, msg.as_string())  # 利用msg的as_string()方法進行轉換
    except Exception as err:
        print('Sending Mail Failed:{0}'.format(err))

    finally:
        smtp_server.quit()


def main():
    send_mail('287990400@qq.com', 'jwxpwixnpruwcabj', '932911203@qq.com', 'Important2', 'Text Message from dahlhin')


if __name__ == '__main__':
    main()

使用yagmail發送郵件 

  Python的標准庫smtplib和email,相對來說還是比較復雜的,因此許多開源項目提供了更加易用的接口來發送郵件。比如yagmail就是一個使用比較廣泛的開源項目,它依舊使用smtplib和email模塊,但是相對於直接使用smtplib和email模塊,它提供了更加Pythonic的接口,並具有更好的易用性。

  由於yagmail屬於第三方庫,在使用前需要先行安裝

pip3 install yagmail

  下面使用yagmail發送一封簡單的郵件

server = yagmail.SMTP(user='287990400@qq.com',password='vgdwgrziieducafc',host='smtp.qq.com',port=25,smtp_starttls=True,smtp_ssl=False)
content = ['this is my first mail','used for yagmail']
server.send('932911203@qq.com','IMPORTANT',content)          # 對方郵箱,主題,郵件內容

  如果要攜帶附件那么只需要在send后面添加即可

server = yagmail.SMTP(user='287990400@qq.com',password='vgdwgrziieducafc',host='smtp.qq.com',port=25,smtp_starttls=True,smtp_ssl=False)
content = ['this is my first mail','used for yagmail']
server.send('932911203@qq.com','Images',content,['/Users/DahlHin/Desktop/image.jpg'])

  再也沒有這么好用的第三方郵件庫了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM