1. 程式人生 > 實用技巧 >python測試開發django(28)--傳送附件EmailMessage

python測試開發django(28)--傳送附件EmailMessage

前言

Django的send_mail()和send_mass_mail()函式事實上是對EmailMessage類使用方式的一個輕度封裝。send_mail()和相關的其他封裝函式並沒有充分使用EmailMessage類的所有特性。

要想使用更多特性,比如暗送(BCC),加入附件,或是多用途格式(multi-part)郵件,都要直接建立EmailMessage例項。

有些資料用的EmailMultiAlternatives類,有些用的EmailMessage類,這2個其實有關聯,EmailMultiAlternatives類繼承了EmailMessage類

EmailMessage

EmailMessage類使用下列引數初始化(除非使用位置引數,否則預設順序如下)。所有引數均可選,均可在呼叫send()方法之前的任何時間對其賦值。

  • subject:郵件的標題行
  • body:郵件的主體內容文字,須是純文字資訊。
  • from_email:傳送者的地址。[email protected] 或 Fred[email protected]格式都是合法的。如果忽略該引數,Django就會使用 DEFAULT_FROM_EMAIL 配置項。
  • to:收件人地址列表或元組。
  • bcc:傳送郵件時用於“Bcc”頭資訊的一組列表或元組,也就是暗送的收件人。
  • connection:一個郵件後端例項。用同一個連結傳送多封郵件就要用到該引數。忽略該引數時,會在呼叫send()時自動建立一個新連結。
  • attachments:置於郵件報文內的附件列表。列表元素可以是email.MIMEBase.MIMEBase 例項,也可以是(filename, content, mimetype) 三部分構成的元組。
  • headers:置於郵件報文內的其他頭資訊(header)的字典。字典的key是頭資訊的名稱,字典的value是頭資訊的值。這樣做能確保頭資訊的名稱和對應值會以正確的格式保存於郵件報文中。
  • cc:傳送郵件時放與"Cc"頭資訊的一系列列表或元組。
  • reply_to:傳送電子郵件時"回覆"標題中使用的收件人地址列表或元組。
class EmailMessage:
    """A container for email information."""
    content_subtype = 'plain'
    mixed_subtype = 'mixed'
    encoding = None     # None => use settings default

    def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
                 connection=None, attachments=None, headers=None, cc=None,
                 reply_to=None):
        ...省略

    def send(self,fail_silently=False) :
         """
         傳送郵件報文。如果在構造郵件時如果指定了某個連結(connection),就會使用該連結發郵件。 否則,就會使用預設後端的例項發郵件。
          如果關鍵字引數 fail_silently 為 True ,就會忽略郵件傳送時丟擲的異常。
         """
    def recipients(self):
        """
         返回郵件中所有收件人的列表,不管收件人是在 to 還是 bcc 屬性中。
         這是另一個經常被繼承覆寫的方法, 因為SMTP伺服器在傳送郵件報文時,要接收完整的收件人列表。
         即使你自己的類使用其他方式來指定收件人,也仍然需要使用該方法返回收件人列表。
        """

    def message(self) :
         """
         構造了一個 django.core.mail.SafeMIMEText 物件 (Python的 email.MIMEText.MIMEText 類的子類) 或是 django.core.mail.SafeMIMEMultipart 物件(該物件儲存即將傳送出去郵件報文)。
         如需擴充套件 EmailMessage類,一般情況下要覆寫該方法,將你所需的內容新增到MIME物件中。
         """

   def attach(self, filename=None, content=None, mimetype=None):
        """
         傳遞一個單獨的 email.MIMEBase.MIMEBase 例項做為引數。該例項會直接新增到最終的郵件報文中。

         或者,給 attach() 傳遞三個引數: filename, content 和 mimetype. filename 是出現在郵件中的附件檔案的名稱, content 是附件的內容,而 mimetype 是附件所使用的MIME型別。 
         如果忽略 mimetype, Django會自動根據附件檔名來推測MIME內容型別。
         例如:
                 message.attach('design.png', img_data, 'image/png')
        """
    

     def attach_file(self, path, mimetype=None):
         """
         使用當前檔案系統下的某個檔案做為附件。呼叫時,傳入某個檔案的完整路徑,以及該附件的MIME型別(可選的)。
         忽略MIME型別的話,Django會自動根據附件檔名來推測MIME型別。
         最簡單的用法如下:
         message.attach_file('/images/weather_map.png')
        """

attach_file方法傳檔案

使用當前檔案系統下的某個檔案作為附件。呼叫時,傳入某個檔案的完整路徑,這種方法是最簡單的,上傳本地的某個檔案。

如在templates目錄下有一個a.png的圖片(圖片和其它檔案都一樣,如xx.doc,只是字尾不一樣)

views.py檔案實現程式碼

#coding:utf-8

from django.http import HttpResponse
from django.core.mail import EmailMessage
import os

def file_mail(request):
    '''傳送附件'''
    email = EmailMessage(
        'Hello',
        'Body goes here',
        '[email protected]',   # 發件人
        ['[email protected]'],   # 收件人
        ['[email protected]'],                      # cc抄送
        reply_to=['[email protected]'],  # “回覆”標題中使用的收件人地址列表或元組
        headers={'Message-ID': 'foo'},
    )
    cur = os.path.dirname(os.path.realpath(__file__))
    # templates目錄下有個a.png的圖片
    filepath = os.path.join(cur, "templates", "ab.png")

    email.attach_file(filepath, mimetype=None)
    email.send()
    return HttpResponse('郵件傳送成功,收不到就去垃圾箱找找吧!')

郵件收到效果如下

attach方法

attach() 傳遞三個引數:filename,content和mimetype。filename是出現在郵件中的附件檔案的名稱,content是附件的內容,而mimetype是附件所使用的MIME型別。

參考格式如:message.attach('a.png',img_data,'image/png')

#coding:utf-8


from django.http import HttpResponse
from django.core.mail import EmailMessage
import os

def file_mail(request):
    '''傳送附件'''
    email = EmailMessage(
        'Hello',
        'Body goes here',
        '[email protected]',   # 發件人
        ['[email protected]'],   # 收件人
        ['[email protected]'],                      # cc抄送
        reply_to=['[email protected]'],  # “回覆”標題中使用的收件人地址列表或元組
        headers={'Message-ID': 'foo'},
    )
    cur = os.path.dirname(os.path.realpath(__file__))
    # templates目錄下有個a.png的圖片
    filepath = os.path.join(cur, "templates", "ab.png")
    #方法1 attach_file
    email.attach_file(filepath, mimetype=None)

    #方法2 attach
    filepath1=os.path.join(cur,"templates","c.png")
    img_datas=open(filepath1,"rb")
    email.attach('c.png',img_datas.read(),'image/png')
    email.send()
    return HttpResponse('郵件傳送成功,收不到就去垃圾箱找找吧!')

郵件收到效果如下

這裡雖然能新增附件了,但是如果正文想傳html的正文內容,這個類裡面沒有封裝對應方法,在EmailMultiAlternatives類裡面有個attach_alternative方法可以實現該功能,接著往下看。

EmailMultiAlternatives

attach_alternative方法封裝在EmailMultiAlternatives類裡面,EmailMultiAlternatives類繼承了EmailMessage類

class EmailMultiAlternatives(EmailMessage):
    """
    繼承EmailMessage 可以輕鬆傳送multipart / alternative訊息。 例如,包括文字的HTML和HTML版本變得更容易
    """
    alternative_subtype = 'alternative'

    def __init__(self, subject='', body='', from_email=None, to=None, bcc=None,
                 connection=None, attachments=None, headers=None, alternatives=None,
                 cc=None, reply_to=None):
        """
        Initialize a single email message (which can be sent to multiple
        recipients).
        """
        super().__init__(
            subject, body, from_email, to, bcc, connection, attachments,
            headers, cc, reply_to,
        )
        self.alternatives = alternatives or []

    def attach_alternative(self, content, mimetype):
        """Attach an alternative content representation."""
        assert content is not None
        assert mimetype is not None
        self.alternatives.append((content, mimetype))

 使用方法 

#coding:utf-8

from django.http import HttpResponse
from django.core.mail import send_mail
from django.core.mail import send_mass_mail
from django.core.mail import EmailMessage
from django.core.mail import EmailMultiAlternatives
import os


def file_mail(request):
    '''傳送附件'''
    email = EmailMultiAlternatives(
        'Hello',
        'Body goes here',
        '[email protected]',   # 發件人
        ['[email protected]'],   # 收件人
        ['[email protected]'],                      # cc抄送
        reply_to=['[email protected]'],  # “回覆”標題中使用的收件人地址列表或元組
        headers={'Message-ID': 'foo'},
    )
    cur = os.path.dirname(os.path.realpath(__file__))
    # templates目錄下有個a.png的圖片
    filepath = os.path.join(cur, "templates", "ab.png")
    #方法1 attach_file
    email.attach_file(filepath, mimetype=None)

    #方法2 attach
    filepath1=os.path.join(cur,"templates","c.png")
    img_datas=open(filepath1,"rb")
    email.attach('c.png',img_datas.read(),'image/png')

    #新增html正文
    h='''
    <!DOCTYPE HTML>
    <html>
    <head>
        <meta charset="UTF-8">
        <title>帶圖片的郵件</title>
    </head>
    <body>
    <a href="https://i.cnblogs.com/posts?cateId=1633461" target="_blank">
        <p>點圖片進入jango文章列表<br>
        <img src="https://mail.qq.com/cgi-bin/getqqicon?sid=y4qfcTC8aEOSW00S&uin=-2239048779&mode=newaddr&mailaddr=371933505%40qq.com" height="160" width="270" />
        </p></a>
    <p>
    其它圖片:<br>
    <img src="http://www.w3school.com.cn/i/eg_chinarose.jpg" height=150 width=300/></p>
    <p>請注意,插入動畫影象的語法與插入普通影象的語法沒有區別。</p>
    </body>
    </html>
    '''
    email.attach_alternative(content=h,mimetype='text/html')

    email.send()
    return HttpResponse('郵件傳送成功,收不到就去垃圾箱找找吧!')

到這裡郵件傳送相關的功能都實現了

總的來說,一般推薦用EmailMultiAlternatives類,它繼承了EmailMessage