python3發送郵件(有附件)


python3發送郵件(有附件)

代碼一:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.utils import formatdate
import os

#設置登錄及服務器信息
mail_host = 'smtp.vcredit.com'
mail_user = 'h***@vcredit.com'
mail_pass = 'h****'
sender = 'h***@vcredit.com'
receivers = ['p****@vcredit.com']

#設置eamil信息
#添加一個MIMEmultipart類,處理正文及附件
message = MIMEMultipart()
message['From'] = sender
message['To'] = receivers[0]
message['Subject'] = '測試'
message['Date'] = formatdate( )
#推薦使用html格式的正文內容,這樣比較靈活,可以附加圖片地址,調整格式等
with open('abc.html','r') as f:
content = f.read()
#設置html格式參數
part1 = MIMEText(content,'html','utf-8')

basename = os.path.basename("report.txt")
#添加一個txt文本附件
with open('report.txt','r')as h:
content2 = h.read()
#設置txt參數
part2 = MIMEText(content2,'plain','utf-8')

#附件設置內容類型,方便起見,設置為二進制流
part2['Content-Type'] = 'application/octet-stream'
#設置附件頭,添加文件名
part2['Content-Disposition'] = 'attachment;filename=%s' % basename

#解決中文附件名亂碼問題
# part2.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', basename))

#添加照片附件
with open('1.png','rb')as fp:
picture = MIMEImage(fp.read())
#與txt文件設置相似
picture['Content-Type'] = 'application/octet-stream'
picture['Content-Disposition'] = 'attachment;filename="1.png"'
#將內容附加到郵件主體中
message.attach(part1)
message.attach(part2)
message.attach(picture)

#登錄並發送
try:
# smtpObj = smtplib.SMTP()
# smtpObj.connect(mail_host,25)
#需要SSL認證
smtpObj = smtplib.SMTP_SSL(mail_host)

smtpObj.login(mail_user,mail_pass)
smtpObj.sendmail(sender,receivers,message.as_string())
print('success')
smtpObj.quit()
except smtplib.SMTPException as e:
print('error',e)

參考鏈接:http://mp.weixin.qq.com/s/X8i4b2HlU7HAlZLeGVnl0A

經驗證使用代碼一從公司的Outlook郵箱發送到Outlook郵箱是沒有問題的,但是當附件的名稱為中文的時候,收到的郵件的附件名稱為

研究了很長時間,不知道怎么解決。。。

 

用代碼一從公司的Outlook郵箱發送到QQ郵箱,QQ郵箱收不到郵件(原因未知),不過可以使用代碼二發送到QQ郵箱,並且不存在未命名附件和亂碼的問題;但是發送到公司的Outlook郵箱不管是否為中文名稱的附件都存在未命名附件的問題。

解決方法:針對代碼二可以使用Foxmail收取Outlook的郵件,這樣不會出現未命名附件和亂碼的問題

代碼二:

'''發送帶附件的郵件'''
from email import encoders
from email.mime.text import MIMEText
from email.utils import formatdate
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.header import Header
import smtplib
import os.path

From = "p****@vcredit.com"

#多個收件人用逗號隔開
To = "9*****@qq.com, aa@aa.com"

acc = 'dd@dd.com, eeg@ee.com'
file_name = "測試.png"

server = smtplib.SMTP("smtp.vcredit.com")
server.login("p****@vcredit.com","p*****") #僅smtp服務器需要驗證時

# 構造MIMEMultipart對象做為根容器
main_msg = MIMEMultipart()

# 構造MIMEText對象做為郵件顯示內容並附加到根容器
text_msg = MIMEText("this is a test text to text mime")
main_msg.attach(text_msg)

# 構造MIMEBase對象做為文件附件內容並附加到根容器
contype = 'application/octet-stream'
maintype, subtype = contype.split('/', 1)

# 讀入文件內容並格式化
data = open(file_name, 'rb')
file_msg = MIMEBase(maintype, subtype)
file_msg.set_payload(data.read( ))
data.close( )
encoders.encode_base64(file_msg)

# 設置附件頭
basename = os.path.basename(file_name)
#解決中文附件名亂碼問題
file_msg.add_header('Content-Disposition', 'attachment', filename=('gbk', '', basename))
main_msg.attach(file_msg)

# 設置根容器屬性
main_msg['From'] = From
main_msg['To'] = To

main_msg['Cc'] = acc 
main_msg['Subject'] = Header("郵件測試","utf-8")
main_msg['Date'] = formatdate( )

# 得到格式化后的完整文本
fullText = main_msg.as_string( )

# 用smtp發送郵件
try:

#發送給多人、同時抄送給多人,發送人和抄送人放在同一個列表中
  server.sendmail(From, To.split(',') + acc.split(','), fullText)
finally:
  server.quit()

代碼三:

Python發送圖片|文本|word|pdf格式的郵件

import os, pickle
import smtplib 
import mimetypes 
from email.mime.multipart import MIMEMultipart 
from email.mime.base import MIMEBase 
from email.mime.text import MIMEText 
from email.mime.audio import MIMEAudio 
from email.mime.image import MIMEImage 
from email.encoders import encode_base64
import email

def dumpPickle(data, saveLocation, fileName):
    os.chdir(saveLocation) #文件存放的路徑
    with open(fileName, 'wb') as f:
        pickle.dump(data, f) #導入數據data到文件f中
        print('save data: %s successful' % fileName)

def loadPickle(loadLocation, fileName):
    os.chdir(loadLocation) #文件讀取的路徑
    with open(fileName, 'rb') as f:
        return pickle.load(f) #讀取數據

def sendMail(subject, recipient, text, *attachmentFilePaths): 
    '''發送郵件函數:參數(郵件主題,郵件內容,郵件附件(可多選))''' 
    msg = MIMEMultipart()  # 發送附件時需調用 MIMEMultipart類,創建 MIMEMultipart,並添加信息頭

    '''
MIME郵件的基本信息、格式信息、編碼方式等重要內容都記錄在郵件內的各種域中,域的基本格式:{域名}:{內容},域由域名后面跟“:”再加上域的信息內容構成,一條域在郵件中占一行或者多行,
域的首行左側不能有空白字符,比如空格或者制表符,占用多行的域其后續行則必須以空白字符開頭。域的信息內容中還可以包含屬性,屬性之間以“;”分隔,屬性的格式如下:{屬性名稱}=”{屬性值}”。   
    '''
    msg['From'] = sender 
    msg['To'] = ";".join(recipient)
    msg['Subject'] = subject 
    msg.attach(MIMEText(text)) 

    for attachmentFilePath in attachmentFilePaths:  #判斷添加哪些附件
        msg.attach(getAttachment(attachmentFilePath))  #如果入參給定附件文件,使用attach 發放添加msg頭信息
    try:
        mailServer = smtplib.SMTP('smtp.qq.com',587)  # 連接騰訊郵件的服務器;SMTP(Simple Mail Transfer Protocol)即簡單郵件傳輸協議,用於由源地址到目的地址傳送郵件的規則,由它來控制信件的中轉方式
        mailServer.ehlo()  # 使用starttls 方法必須先 ehlo 判斷是否是同一個地址。。。
        mailServer.starttls()  # 以下SMTP都會加密;Put the SMTP connection in TLS (Transport Layer Security) mode. All SMTP commands that follow will be encrypted.
        mailServer.ehlo()  # You should then call ehlo() again.
        mailServer.login(sender, password)  # 登錄郵箱
        mailServer.sendmail(sender, recipient, msg.as_string())  # 發送郵件(發件人,收件人,發送內容)
        mailServer.close() # 關閉郵件發送服務
        print('Sent email to %s successfully' % recipient)
    except Exception as e:
        print('sendEmai failed %s' % e)

"""part = MIMEApplication(open('foo.mp3','rb').read())
part.add_header('Content-Disposition', 'attachment', filename="foo.mp3")
msg.attach(part) """     

def getAttachment(attachmentFilePath):  # 獲取附件,參數:文件路徑
    contentType, encoding = mimetypes.guess_type(attachmentFilePath)  # 根據 guess_type方法判斷文件的類型和編碼方式

    if contentType is None or encoding is not None:  # 如果根據文件的名字/后綴識別不出是什么文件類型
        contentType = 'application/octet-stream'   # 使用默認類型,usable for a MIME content-type header.

    mainType, subType = contentType.split('/', 1)  # 根據contentType 判斷主類型與子類型
    file = open(attachmentFilePath, 'rb') 

    if mainType == 'text':  # 根據主類型不同,調用不同的文件讀取方法
        attachment = MIMEBase(mainType, subType)  # A subclass of MIMENonMultipart, the MIMEText class is used to create MIME objects of major type text.
        attachment.set_payload(file.read())  # Set the entire message object’s payload(負載) to payload.
        encode_base64(attachment)  # Encodes the payload into base64 form and sets the Content-Transfer-Encoding header to base64.       
    elif mainType == 'message': 
        attachment = email.message_from_file(file)  # 使用message_from_file方法,Return a message object structure tree from an open file object
    elif mainType == 'image':  # 圖片
        attachment = MIMEImage(file.read())  #A subclass of MIMENonMultipart, the MIMEImage class is used to create MIME message objects of major type image.
    #elif mainType == 'audio':  # 音頻
        #attachment = MIMEAudio(file.read(), _subType=subType)  #A subclass of MIMENonMultipart, the MIMEAudio class is used to create MIME message objects of major type audio.

    else: 
        attachment = MIMEBase(mainType, subType)  # The MIMEBase class always adds a Content-Type header (based on _maintype, _subtype, and _params), and a MIME-Version header (always set to 1.0).
        attachment.set_payload(file.read())  # Set the entire message object’s payload(負載) to payload.
        encode_base64(attachment)  # Encodes the payload into base64 form and sets the Content-Transfer-Encoding header to base64.  

    file.close() 
    """
Content-disposition 是 MIME 協議的擴展,MIME 協議指示 MIME 用戶代理如何顯示附加的文件。Content-disposition其實可以控制用戶請求所得的內容存為一個文件的時候提供一個默認的文件名,
文件直接在瀏覽器上顯示或者在訪問時彈出文件下載對話框。 content-disposition = "Content-Disposition" ":" disposition-type *( ";" disposition-parm ) 。   
    """
#     attachment.add_header('Content-Disposition', 'attachment',   filename=os.path.basename(attachmentFilePath))
    attachment.add_header('Content-Disposition', 'attachment',   filename=('gb2312', '', os.path.basename(attachmentFilePath)))  #Content-Disposition為屬性名 disposition-type是以什么方式下載,如attachment為以附件方式下載 disposition-parm為默認保存時的文件名
    return attachment 

#需要先執行dumpPickle函數生成senderInfo.txt文件
#dumpPickle("發件人郵箱?發件人郵箱密碼?['收件人郵箱']", os.path.basename('.'), "senderInfo.txt")
if __name__ == "__main__":
    #qq郵箱登錄的時候密碼需要換成授權碼
    senderInfo = loadPickle(os.path.basename('.'), "senderInfo.txt")
    sender = senderInfo.split("?")[0] #發件人郵箱
    password = senderInfo.split("?")[1] #發件人郵箱密碼
    recipient = senderInfo.split("?")[2] #收件人郵箱
    recipient = [recipient[2:-2]] #將string格式的"['收件人郵箱']"轉換成['收件人郵箱']
    sendMail('郵件主題', recipient, '發送格式:.jpg, .pdf, .docx, .txt', 'error_jpg.jpg', '律***.pdf', '函****.docx', '測試.txt')

對於Outlook郵箱還是存在上面說的問題,建議可以使用Foxmail郵箱收取相關郵件。 

參考鏈接:

http://blog.csdn.net/ck3207/article/details/51823905

http://blog.csdn.net/biboshouyu/article/details/53338277


免責聲明!

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



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