码迷,mamicode.com
首页 > 编程语言 > 详细

Python发送多个附件和支持HTML及纯文本内容的 Email 实现

时间:2015-05-07 10:36:38      阅读:338      评论:0      收藏:0      [点我收藏+]

标签:python   电子邮件   smtp   附件   发送html   

由于工作中经常需要收发电子邮件,例如每日(周)的工作报告,测试报告,监控告警,定时提醒等等,大都已电子邮件的形式发送。本文将实现一个 Python 的电子邮件发送类,支持发送多个附件(目录),HTML或纯文本内容,抄送收件人,多个接收者等功能。


代码实现

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Copyright (C)  2015 By Thomas Hu.  All rights reserved.
@author : Thomas Hu
@version: 1.0
@created: 2015-05-17
'''
import base64
import httplib
import re
import os
import smtplib
from xml.etree import ElementTree
from email.utils import formatdate
from email.MIMEText import MIMEText
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
from email import Encoders

class EmailSender(object):
    def __init__(self, smtp_server, smtp_port=0, verbose=False, debug_level=1, encoding="utf-8"):
        ''' Initiate the EmailSender.
        @param smtp_server: the Email SMTP server.
        @param smtp_port:   the Email SMTP server port, if use the default port(25), you can set it to 0 or 25.
        @param verbose:     show the processing information if set to 'True', default is 'False'.
        @param debug_level: set the smtplib debug level, if it's '0', will enable debug information.
        @param encoding:    the encoding or charset for email body text or attachment file name, default is "utf-8".
        '''
        self.server = smtp_server
        self.port = int(smtp_port)
        self.verbose = verbose
        self.debug_level = int(debug_level)
        self.encoding = encoding
        self.attachments = []

        #Create smtp instance
        self.smtp = smtplib.SMTP(self.server, self.port)
        self.smtp.set_debuglevel(self.debug_level)
        self.print_verbose("Init SMTP server successfully. server=%s, port=%d."%(self.server, self.port))

    def print_verbose(self, message):
        '''Print the verbose information.
        @param message: the message to be print if the verbose is "True".
        '''
        if self.verbose:
            print(message)
            
    def login(self, user, password):
        '''Login to SMTP server.
        @param user:     the user name of the email sender.
        @param password: the passord of the user for login to SMTP server.
        '''
        self.from_addr = user + "@" + ".".join(self.server.split(".")[1:])
        try:
            self.print_verbose("Start to login into SMTP server.server=%s, port=%d."%(self.server, self.port))
            self.smtp.login(user, password)
            self.print_verbose("Login into SMTP server successfully.")
        except Exception as ex:
            print("Login into SMTP server failed! Error info: %s"%(str(ex)))

    def __add_attachment_file(self, filename, encoding, Filter):
        '''Add attachment file to the attachment list.
        @param filename:  the file name of attachment, should not be a path.
        @param encoding:  the encode of the attachment file name.
        @param Filter:    the file filter object, must implement 'accept(filename)' interface, and return True or False.
        '''
        # Check if the file is acceptable by the Filter
        if Filter is not None:
            try:
                accept = Filter.accept(filename)
            except:
                accept = False
            if accept == False:
                return
        # Add the attachment to the attachment list
        try:
            basename = os.path.basename(filename)
            attach = MIMEBase("application", "octet-stream")
            attach.set_payload(open(filename, "rb").read())
            #attach.add_header("Content-Disposition", "attachment;filename=%s"%(basename))
            attach.add_header("Content-Disposition", "attachment", filename=(encoding, "", basename))
            Encoders.encode_base64(attach)
            self.attachments.append(attach)
            self.print_verbose("Add attachment \"%s\" successfully."%(filename))
        except Exception as ex:
            print("Add attachment file \"%s\" failed. Error info: %s."%(filename, str(ex)))
                
    def add_attachment(self, path, encoding=None, Filter=None):
        '''Add attachment file to the attachment list.
        @param path:      the path of files to be added as attachment files. If is a directory, all of the files in it will be added.
        @param encoding:  the encode of the attachment file name.
        @param Filter:    the file filter object, must implement 'accept(filename)' interface, and return True or False.
        '''
        if not os.path.exists(path):
            self.print_verbose("Warning: attachment path \"%s\" is not exists."%(path))
            return
        charset = encoding if (encoding is not None) else self.encoding
        if os.path.isfile(path):
            return self.__add_attachment_file(path, charset, Filter)
        for root, dirs, files in os.walk(path):
            for f in files:
                fname = os.path.join(root, f)
                self.__add_attachment_file(fname, charset, Filter)
                
    def send_email(self, subject, to_addrs, cc_addrs, content, subtype="plain", charset=None):
        '''Send the email to the receivers.
        @param subject:    the email's subject(title).
        @param to_addrs:   the receivers' addresses, it's a list looks like ["user1@some_server.com", "user2@another_server.com"].
        @param cc_addrs:   the copy to receivers' addresses, has the same format as to_addrs.
        @param content:    the email message body, it can be plain text or HTML text, which depends on the parameter 'content_type'.
        @param subtype:    the content type, it can be "html" or "plain", default is "plain".
        @param charset:    the charset of message content, default is "None", use the same encoding as the initial function, which default is "utf-8".
        @return: if send successfully, return 'True', otherwise, return 'False'.
        '''
        charset = charset if charset is not None else self.encoding
        
        #Set the root information
        msg_root = MIMEMultipart("related")
        msg_root["Subject"] = subject
        msg_root["From"] = self.from_addr  # You can change it to any string
        msg_root["To"] = ",".join(to_addrs)
        msg_root["CC"] = ",".join(cc_addrs)
        msg_root["Date"] = formatdate(localtime=True)
        msg_root.preamble = "This is a multi-part message in MIME format."

        #Encapsulate the plain and HTML of the message body into an 'alternative' part,
        #so message agents can decide which they want to display.
        msg_alt = MIMEMultipart("alternative")

        #Set the message content
        msg_txt = MIMEText(content, subtype.lower(), charset)
        msg_alt.attach(msg_txt)

        #Add the alternative part to root part.
        msg_root.attach(msg_alt)

        #Add the attachment files
        for attach in self.attachments:
            msg_root.attach(attach)

        #Extend the copy to addresses to to_addrs
        to_addrs.extend(cc_addrs)

        #Send the email
        try:
            self.smtp.sendmail(self.from_addr, to_addrs, msg_root.as_string())
            self.print_verbose("Send email successfully.")
        except Exception as ex:
            print("Send email failed. Error info:%s"%(str(ex)))
            return False
        return True

    def close(self):
        '''Quit from the SMTP.
        '''
        self.smtp.quit()
        self.print_verbose("Logout SMTP server successfully.")
        
def test():
    smtp_server = "smtp.163.com"
    user = "yyy"
    password = "yyyxxx"
    from_addr = "yyy@163.com"
    to_addrs = ["xxxxxxxxx@qq.com"]
    cc_addrs = []
    subject = "Email sending test"
    content ='Dear Friends,<p/><a href="http://blog.csdn.net/thomashtq"> Welcome to my CSDN blog!</a> <p/>Thanks a lot!'
    attach_files=[r"D:\temp\sendemail\attach"]

    emailsender = EmailSender(smtp_server, verbose=True)
    emailsender.login(user, password)
    for attach in attach_files:
        emailsender.add_attachment(attach, "utf-8")
    emailsender.send_email(subject, to_addrs, cc_addrs, content, subtype="html", charset="utf-8")
    emailsender.close()
        
if __name__ == '__main__':
    test()


代码中都有详细的解释,请原谅我用英文注释啊,习惯了^_^。 运行时,请将 test() 函数中相关的用户名、密码、服务器、收件人、附件列表等进行修改。也就是  test()函数中开头那段代码(空行之前的),根据自己的具体情况进行修改就 OK 了。

Python发送多个附件和支持HTML及纯文本内容的 Email 实现

标签:python   电子邮件   smtp   附件   发送html   

原文地址:http://blog.csdn.net/thomashtq/article/details/45555689

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!