天天看點

Python之smtplib發送郵件 by二卷

  • SMTP(Simple Mail Transfer Protocol)即簡單郵件傳輸協定,它是一組用于由源位址到目的位址傳送郵件的規則,由它來控制信件的中轉方式。Python内置對SMTP的支援,可以發送純文字郵件、HTML郵件以及帶附件和圖檔的郵件
  • Python對SMTP支援有smtplib和email兩個子產品,email負責構造郵件,smtplib負責發送郵件
  • python的smtplib提供了一種很友善的途徑發送電子郵件,對smtp協定進行了簡單的封裝
  • 學習網址: http://www.runoob.com/python/python-email.html ; http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832745198026a685614e7462fb57dbf733cc9f3ad000

SMTP 基礎知識

1.SMTP 的會話方式

1.郵件直接投遞

發送郵件給[email protected],直接連結163.com的郵件伺服器,把郵件給[email protected]

2.驗證過後發信

你有[email protected]郵箱,發送郵件給[email protected],要先連接配接126.com的smtp伺服器,然後認證,之後在把要發到163.com的信件投到126.com上,126.com會幫你把信投遞到163.com。

email使用文法

1.建立簡單的純文字檔案

from email.mime.text import MIMEText
msg = MIMEText('hello world!', 'plain', 'utf-8') #傳回MIMEText對象
#'hello world!'為郵件正文;'plain'是MIME的子類型;
#一定要用utf-8編碼保證多語言相容性                

注:MIME(Multipurpose Internet Mail Extensions)多用途網際網路郵件擴充類型。是設定某種擴充名的檔案用一種應用程式來打開的方式類型,當該擴充名檔案被通路的時候,浏覽器會自動使用指定應用程式來打開。例:text/plain 就是一個MIME類型,text是類型 & plain是子類型,檔案設定為純文字的形式,浏覽器在擷取到這種檔案時并不會對其進行處理。

smtplib使用文法

1.建立python的SMTP對象

import smtplib

smtpObj = smtplib.SMTP( [host [, port [,local_hostname]]] )
#host: SMTP 伺服器主機,可以指定主機的ip位址或者域名(可選)
#port: 有host 參數則要指定SMTP服務使用的端口号,一般為25
#local_hostname:SMTP在本機上,隻需指定伺服器位址為 localhost                

2.python的SMTP對象使用sendmail方法發送郵件

smtpObj.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options])
#from_addr: 郵件發送者位址
#to_addrs: 字元串清單,郵件發送位址
#msg: 發送消息,字元串,格式是smtp協定中定義的格式                

執行個體

1.primer(發送純文字)

#!/usr/bin/python
# -*- encoding:utf-8 -*-

from email.mime.text import MIMEText
import smtplib
from email.header import Header
from email.utils import parseaddr, formataddr

'''
這裡采用的是間接方式,就是上述的驗證後發信。如果你有一個163.com的郵箱,
想發送給一個126.com的郵箱,先連結163.com的郵箱伺服器,登入你的郵箱後,
再通過1163.com的郵箱伺服器發送郵件給126.com的郵箱。
注:通過第三方的郵件伺服器發送郵件比較通用,你自己的伺服器發郵件很容易被接收方判定為垃圾郵件
'''
def _format_addr(s): #定義一個不能被其他檔案import的函數,主要用于處理郵件的編碼問題
    name, addr = parseaddr(s) #如果是erjuan<erjuan.163.com>,則name就是erjuan, addr就是erjuan.163.com,注意郵箱格式要對
    #變成準确的郵件需要的編碼
    return formataddr(( \
        Header(name, 'utf-8').encode(), \
        addr.encode('utf-8') if isinstance(addr, unicode) else addr))

from_addr = raw_input('From: ') #輸入你需要登入認證郵箱的位址,就是你自己的郵箱
password = raw_input('Password: ') #你郵箱的密碼
smtp_server = raw_input('SMTP server: ')# 輸入SMTP伺服器位址,如果你用是163郵箱,那麼就是:smtp.163.com
to_addr = raw_input('To: ')# 輸入收件人位址

emailContent = MIMEText('hello world!', 'plain', 'utf-8')
#關于Header見官網https://docs.python.org/2/library/email.header.html?highlight=email.head#module-email.header
emailContent['From'] = _format_addr(u'二卷<'+from_addr+'>')
emailContent['To'] = _format_addr(u'You<'+to_addr+'>')
#emailContent['From'] = Header("二卷<[email protected]>", 'utf-8')
#emailContent['To'] =  Header("You<[email protected]", 'utf-8')#直接這樣使用,會出現亂碼問題
emailContent['Subject'] = Header('來自二卷的郵件哦', 'utf-8').encode()

server = smtplib.SMTP(smtp_server, 25)# 連接配接郵件伺服器,SMTP協定預設端口是25
#server = smtplib.SMTP('localhost') 使用這個話的時候一般需要你的機器上安裝有發送郵件的程式,例如sendmail
#server.set_debuglevel(1)#列印流程
server.login(from_addr, password)#登入你的郵箱
server.sendmail(from_addr, [to_addr], emailContent.as_string())#發送郵件
server.quit()                

結果展示

Python之smtplib發送郵件 by二卷

Bug

如果出現smtplib.SMTPDataError: (554, …… 這樣的報錯是因為你的真實的郵件位址和你在From和to中填寫的不一緻

2.primer+1(發送html)

隻需要修改primer中發送文本的

emailContent = MIMEText(……)

這個語句,把plain換成html,然後第一個參數寫上html的語句

emailContent = MIMEText('<html><body><h1>Hello world!</h1>' +
    '<a href="http://www.baidu.com" target="_blank" rel="external nofollow" >百度</a>' +
    '</body></html>', 'html', 'utf-8')                

結果展示

Python之smtplib發送郵件 by二卷

3.advance(發送附件)

發送帶附件的方法蠻多的,這裡介紹一個簡單的,需要建立MIMEMultipart()執行個體,比較簡單的是使用都用MIMEApplication來添加附件,MIMEApplication預設子類型是application/octet-stream(表示二進制檔案,根據其字尾進行處理)

#!/usr/bin/python
# -*- encoding:utf-8 -*-

from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import smtplib
from email.header import Header
from email.utils import parseaddr, formataddr


def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr(( \
        Header(name, 'utf-8').encode(), \
        addr.encode('utf-8') if isinstance(addr, unicode) else addr))

from_addr = raw_input('From: ')
password = raw_input('Password: ')
smtp_server = raw_input('SMTP server: ')
to_addr = raw_input('To: ')

#建立一個帶附件的執行個體
emailContent = MIMEMultipart()
emailContent['From'] = _format_addr(u'二卷<'+from_addr+'>')
emailContent['To'] = _format_addr(u'You<'+to_addr+'>')
emailContent['Subject'] = Header('來自二卷的郵件哦', 'utf-8').encode()

#郵件中的文本資訊
emailText = MIMEText("This email has attachment", 'plain', 'utf-8')
emailContent.attach(emailText)

#郵件中的附件資訊,一般來說會判斷一下附件的檔案類型,我們這裡是圖檔,就不判斷了
img = open('picture.png', 'rb')
attachment = MIMEImage(img.read())
img.close()
emailContent.attach(attachment)

server = smtplib.SMTP(smtp_server, 25)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], emailContent.as_string())
server.quit()                

結果展示

Python之smtplib發送郵件 by二卷

3.advance+1(在正文中顯示圖檔)

正文中的圖檔用html語言來引用附件中的,隻需要把上面的代碼稍作修改

這個方法的話附件還是存在的

#!/usr/bin/python
# -*- encoding:utf-8 -*-

from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
import smtplib
from email.header import Header
from email.utils import parseaddr, formataddr


def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr(( \
        Header(name, 'utf-8').encode(), \
        addr.encode('utf-8') if isinstance(addr, unicode) else addr))

from_addr = raw_input('From: ')
password = raw_input('Password: ')
smtp_server = raw_input('SMTP server: ')
to_addr = raw_input('To: ')

#建立一個帶附件的執行個體
emailContent = MIMEMultipart()
emailContent['From'] = _format_addr(u'二卷<'+from_addr+'>')
emailContent['To'] = _format_addr(u'You<'+to_addr+'>')
emailContent['Subject'] = Header('來自二卷的郵件哦', 'utf-8').encode()

#郵件中的文本資訊
emailText = MIMEText('<html><body><h1>Hello world!</h1>' +
    '<p>郵件文本中有圖檔</p><p><img src="cid:pp"></p>' +
    '</body></html>', 'html', 'utf-8')
emailContent.attach(emailText)

#郵件中的附件資訊,一般來說會判斷一下附件的檔案類型,我們這裡是圖檔,就不判斷了
img = open('picture.png', 'rb')
attachment = MIMEImage(img.read())
#給你的附件命名,這裡叫pp,這樣在上面的html中好引用,用cid
attachment.add_header('Content-ID', 'pp')
img.close()
emailContent.attach(attachment)

server = smtplib.SMTP(smtp_server, 25)
server.login(from_addr, password)
server.sendmail(from_addr, [to_addr], emailContent.as_string())
server.quit()                

結果展示

Python之smtplib發送郵件 by二卷

轉載于:https://www.cnblogs.com/erjuan/p/6425471.html