最近在学习python 时,用到了发送邮件的操作,通过整理总结如下:

  

     一、相关模块介绍

      发送邮件主要用到了smtplib和email两个模块,这里首先就两个模块进行一下简单的介绍:
      smtplib模块

        smtplib.SMTP([host[, port[, local_hostname[, timeout]]]])

     SMTP类构造函数,表示与SMTP服务器之间的连接,通过这个连接可以向smtp服务器发送指令,执行相关操作(如:登陆、发送邮件)。所有参数都是可选的。

       host:smtp服务器主机名

       port:smtp服务的端口,默认是25;如果在创建SMTP对象的时候提供了这两个参数,在初始化的时候会自动调用connect方法去连接服务器。

     smtplib模块还提供了SMTP_SSL类和LMTP类,对它们的操作与SMTP基本一致。

 

   smtplib.SMTP提供的方法:

       SMTP.set_debuglevel(level):设置是否为调试模式。默认为False,即非调试模式,表示不输出任何调试信息。

       SMTP.connect([host[, port]]):连接到指定的smtp服务器。参数分别表示smpt主机和端口。注意: 也可以在host参数中指定端口号(如:smpt.yeah.net:25),这样就没必要给出port参数。

       SMTP.docmd(cmd[, argstring]):向smtp服务器发送指令。可选参数argstring表示指令的参数。

       SMTP.helo([hostname]) :使用"helo"指令向服务器确认身份。相当于告诉smtp服务器“我是谁”。

       SMTP.has_extn(name):判断指定名称在服务器邮件列表中是否存在。出于安全考虑,smtp服务器往往屏蔽了该指令。

       SMTP.verify(address) :判断指定邮件地址是否在服务器中存在。出于安全考虑,smtp服务器往往屏蔽了该指令。

       SMTP.login(user, password) :登陆到smtp服务器。现在几乎所有的smtp服务器,都必须在验证用户信息合法之后才允许发送邮件。

       SMTP.sendmail(from_addr, to_addrs, msg[, mail_options, rcpt_options]) :发送邮件。这里要注意一下第三个参数,msg是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,

   附件等构成,发送邮件的时候,要注意msg的格式。这个格式就是smtp协议中定义的格式。

       SMTP.quit() :断开与smtp服务器的连接,相当于发送"quit"指令。(很多程序中都用到了smtp.close(),具体与quit的区别google了一下,也没找到答案。)

       email模块

       emial模块用来处理邮件消息,包括MIME和其他基于RFC 2822 的消息文档。使用这些模块来定义邮件的内容,是非常简单的。其包括的类有(更加详细的介绍可见:http://docs.python.org/library/email.mime.html):

      class email.mime.base.MIMEBase(_maintype, _subtype, **_params):这是MIME的一个基类。一般不需要在使用时创建实例。其中_maintype是内容类型,如text或者image。

   _subtype是内容的minor type 类型,如plain或者gif。 **_params是一个字典,直接传递给Message.add_header()。

      class email.mime.multipart.MIMEMultipart([_subtype[, boundary[, _subparts[, _params]]]]:MIMEBase的一个子类,多个MIME对象的集合,_subtype默认值为mixed。boundary是MIMEMultipart的边界,默认边界是可数的。

      class email.mime.application.MIMEApplication(_data[, _subtype[, _encoder[, **_params]]]):MIMEMultipart的一个子类。

      class email.mime.audio. MIMEAudio(_audiodata[, _subtype[, _encoder[, **_params]]]): MIME音频对象

      class email.mime.image.MIMEImage(_imagedata[, _subtype[, _encoder[, **_params]]]):MIME二进制文件对象。

 

  二、普通文本邮件

  普通文本邮件发送的实现,关键是要将MIMEText中_subtype设置为plain,首先导入smtplib和mimetext,创建smtplib.smtp实例,connect邮件smtp服务器,login后发送,具体代码如下:(python2.7下实现)

具体代码如下:

  python SendMail 发送邮件

 



  二、html邮件的发送

    与text邮件不同之处就是将将MIMEText中_subtype设置为html。具体代码如下:(python2.7下实现)

  

 

    三、发送带附件的邮件

    发送带附件的邮件,首先要创建MIMEMultipart()实例,然后构造附件,如果有多个附件,可依次构造,最后利用smtplib.smtp发送。

  

python SendMail 发送邮件python SendMail 发送邮件
    def SendMailAttach(self, mail_tolist, mail_subject, mail_body, fileList, mail_cclist):
        '''
        发送带附件的邮件
        :param mail_tolist: 接收者邮件列表,如:['[email protected]','[email protected]']
        :param mail_subject: 邮件主题
        :param mail_body: 邮件体主题内容
        :param fileList: 附件列表,就文件名列表(包含路径)
        :param mail_cclist: 抄送邮件列表,如:['[email protected]','[email protected]'],默认不传
        :param mail_bcclist: 密送邮件列表,如:['[email protected]','[email protected]'],默认不传
        :return:
        '''
        msg = MIMEMultipart()
        message = MIMEText(mail_body, _subtype='plain', _charset='utf-8')
        msg.attach(message)

        # 构造附件
        for f in fileList:
            if os.path.isfile(f):
                att = MIMEText(open(f, 'rb').read(), 'base64', 'utf-8')
                att["Content-Type"] = 'application/octet-stream'
                att["Content-Disposition"] = 'attachment;filename=' + os.path.basename(f)
                msg.attach(att)

        msg['Subject'] = mail_subject
        msg['From'] = self.mail_sender
        msg['To'] = ",".join(mail_tolist)
        if len(mail_cclist) > 0:
            msg['Cc'] = ",".join(mail_cclist)
            mail_tolist.extend(mail_cclist)
        # if len(mail_bcclist) > 0:
        #     msg['Bcc'] = ",".join(mail_bcclist)
        #     mail_tolist.extend(mail_bcclist)

        message = ''
        try:
            server = smtplib.SMTP()
            server.connect(self.mail_host)
            server.login(self.mail_user, self.mail_pass)
            server.sendmail(self.mail_sender, mail_tolist, msg.as_string())
            server.close()
            result = '邮件发送成功'

        except smtplib.SMTPException as e:
            # print "Error: 无法发送邮件", e
            message = 'Error: 无法发送邮件:'
        return message
View Code

 

  四、完整的代码如

  

python SendMail 发送邮件python SendMail 发送邮件
# -*- coding: UTF-8 -*-
import os
import smtplib
import time
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
import mail_setting

class Mail:
    '''
    self.mail_host = "smtp.sina.com"  # 设置服务器
    self.mail_user = "xiaowang"  # 用户名
    self.mail_pass = "XXXXX"  # 口令
    self.mail_sender = '[email protected]'  # 发送者
    '''

    def __init__(self, mail_host="210.77.136.200", mail_user="user", mail_pass="pass",
                 mail_sender="da山<[email protected]>", port=465):
        # 第三方 SMTP 服务
        self.mail_host = mail_host
        self.mail_user = mail_user
        self.mail_pass = mail_pass
        self.mail_sender = mail_sender
        self.port = port


    def SendHtmlMail(self, mail_tolist, mail_subject, mail_body, fileList, mail_cclist, mail_bcclist):
        '''
        发送Html邮件
        :param mail_tolist: 接收者邮件列表,如:['[email protected]','[email protected]']
        :param mail_subject: 邮件主题
        :param mail_body: 邮件体主题内容
        :param fileList: 附件列表,就文件名列表(包含路径)
        :param mail_cclist: 抄送邮件列表,如:['[email protected]','[email protected]'],默认不传
        :param mail_bcclist: 密送邮件列表,如:['[email protected]','[email protected]'],默认不传
        :return:
        '''
        message = MIMEText(mail_body, _subtype='html', _charset='gb2312')
        message['Subject'] = mail_subject
        message['From'] = self.mail_sender
        if len(mail_cclist) > 0:
            message['Cc'] = ",".join(mail_cclist)
            mail_tolist.extend(mail_cclist)
        if len(mail_bcclist) > 0:
            message['Bcc'] = ",".join(mail_bcclist)
            mail_tolist.extend(mail_bcclist)

        try:
            smtpObj = smtplib.SMTP(self.mail_host, self.port)
            # smtpObj.connect(self.mail_host, 25)  # 25 为 SMTP 端口号
            # smtpObj.login(self.mail_user, self.mail_pass)
            smtpObj.sendmail(self.mail_sender, mail_tolist, message.as_string())
            smtpObj.close()
            print("邮件发送成功")
        except smtplib.SMTPException as e:
            print("Error: 无法发送邮件")

    def SendMailAttach(self, mail_tolist, mail_subject, mail_body, fileList, mail_cclist):
        '''
        发送带附件的邮件
        :param mail_tolist: 接收者邮件列表,如:['[email protected]','[email protected]']
        :param mail_subject: 邮件主题
        :param mail_body: 邮件体主题内容
        :param fileList: 附件列表,就文件名列表(包含路径)
        :param mail_cclist: 抄送邮件列表,如:['[email protected]','[email protected]'],默认不传
        :param mail_bcclist: 密送邮件列表,如:['[email protected]','[email protected]'],默认不传
        :return:
        '''
        msg = MIMEMultipart()
        message = MIMEText(mail_body, _subtype='plain', _charset='utf-8')
        msg.attach(message)

        # 构造附件
        for f in fileList:
            if os.path.isfile(f):
                att = MIMEText(open(f, 'rb').read(), 'base64', 'utf-8')
                att["Content-Type"] = 'application/octet-stream'
                att["Content-Disposition"] = 'attachment;filename=' + os.path.basename(f)
                msg.attach(att)

        msg['Subject'] = mail_subject
        msg['From'] = self.mail_sender
        msg['To'] = ",".join(mail_tolist)
        if len(mail_cclist) > 0:
            msg['Cc'] = ",".join(mail_cclist)
            mail_tolist.extend(mail_cclist)
        # if len(mail_bcclist) > 0:
        #     msg['Bcc'] = ",".join(mail_bcclist)
        #     mail_tolist.extend(mail_bcclist)

        message = ''
        try:
            server = smtplib.SMTP()
            server.connect(self.mail_host)
            server.login(self.mail_user, self.mail_pass)
            server.sendmail(self.mail_sender, mail_tolist, msg.as_string())
            server.close()
            result = '邮件发送成功'

        except smtplib.SMTPException as e:
            # print "Error: 无法发送邮件", e
            message = 'Error: 无法发送邮件:'
        return message

    def SendMail(self, mail_subject, mail_body, mail_tolist,mail_cclist):
        '''
        发送普通邮件
        :param mail_tolist: 接收者邮件列表,如:['[email protected]','[email protected]']
        :param mail_subject: 邮件主题
        :param mail_body: 邮件体主题内容
        :param fileList: 附件列表,就文件名列表(包含路径)
        :param mail_cclist: 抄送邮件列表,如:['[email protected]','[email protected]'],默认不传
        :param mail_bcclist: 密送邮件列表,如:['[email protected]','[email protected]'],默认不传
        :return:
        '''
        message = MIMEText(mail_body, _subtype='plain', _charset='utf-8')
        message['Subject'] = mail_subject
        message['From'] = self.mail_sender
        if mail_tolist:
            message['To'] = ",".join(mail_tolist)
        if len(mail_cclist) > 0:
            message['Cc'] = ",".join(mail_cclist)
            mail_tolist.extend(mail_cclist)

        result = ''
        try:
            server = smtplib.SMTP()
            server.connect(self.mail_host)
            server.login(self.mail_user,self.mail_pass)
            server.sendmail(self.mail_sender, mail_tolist, message.as_string())
            server.close()
            result = '邮件发送成功'
            # print "邮件发送成功"
        except smtplib.SMTPException as e:
            result = 'Error: 无法发送邮件'
        return result

    def test(self,mail_body,mail_subject,mail_sendto_user,fileName):

        fileList = []
        fileList.append(fileName)

        mail_tolist = []
        mail_tolist.append(mail_sendto_user)

        # 多个人,中间用逗号分隔
        # cc_tolist = ['xx<[email protected]>','dd<[email protected]>']
        cc_tolist =[]
        mail_bcclist = []

        # result = self.SendMail( mail_subject, mail_body, mail_tolist,cc_tolist)
        result = self.SendMailAttach(mail_tolist,mail_subject, mail_body,fileList, cc_tolist)
        return result


setobj = mail_setting.mail_setting()
m = Mail(setobj.mail_host,setobj.mail_user,setobj.mail_pass,setobj.mail_send_user,setobj.port)
# result = m.test('信息1',u'小测试测试',setobj.mail_receive_user)
fileName="D:\\work\\python36_crawl\\src\\2018-07-02-14-01-55.csv"
result = m.test('信息1',u'小测试测试',setobj.mail_receive_user,fileName)
print (result)
View Code
python SendMail 发送邮件python SendMail 发送邮件
# -*- coding: utf-8 -*-
# 配置文件类

class mail_setting:
    def __init__(self):
       

        #由于机器端口控制,目前只能用公司邮箱
        # 邮件端口
        # self.port = 465
        self.port = 465

        # 邮件服务器地址
        self.mail_host = '210.77.136.200'

        # 接收人邮件地址(需要修改)改成你自己的,发送人和接收人可以用一个地址
        self.mail_receive_user = '[email protected]'

        # self.mail_receive_user = '[email protected]'

        # 发送人邮件地址(需要修改)改成你自己的,
        self.mail_send_user='[email protected]'

        #邮件登录用户名 (需要修改)
        self.mail_user = 'user'

        # 登录用密码(需要修改)
        self.mail_pass = "password"
View Code

 

   另一例子

python SendMail 发送邮件python SendMail 发送邮件
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import parseaddr,formataddr
import smtplib
import os
# 最终结果通过Email发送
def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name,'utf-8').encode(),addr))

def Me_email(from_addr,password,to_addr,smtp_server,title,mail_body,fileList):
    # msg = MIMEText('%s' % (result),'plain','utf-8')            # 邮件显示内容
    msg = MIMEMultipart()
    message = MIMEText(mail_body, _subtype='plain', _charset='utf-8')
    msg.attach(message)
    msg['From'] = _format_addr('ICTR <%s>' % from_addr)                # 邮件发送人
    # msg['To'] = _format_addr('管理员 <%s>' % to_addr)
    msg['To']="[email protected],[email protected]"
    msg['Cc'] = "[email protected]"
    # msg['To'] = _format_addr('[email protected]')
    msg['Subject'] = Header('%s' % (title),'utf-8').encode()        # 邮件title
    for f in fileList:
        if os.path.isfile(f):
            att = MIMEText(open(f, 'rb').read(), 'base64', 'utf-8')
            att["Content-Type"] = 'application/octet-stream'
            att["Content-Disposition"] = 'attachment;filename=' + os.path.basename(f)
            msg.attach(att)
    server = smtplib.SMTP(smtp_server,587)
    server.set_debuglevel(1)
    server.login(from_addr,password)
    # server.sendmail(from_addr,[to_addr,'[email protected]','[email protected]'],msg.as_string())
    lst ="[email protected],[email protected],[email protected]".split(',')
    server.sendmail(from_addr, lst, msg.as_string())
    server.quit()


# for f in fileList:
#     if os.path.isfile(f):
#         att = MIMEText(open(f, 'rb').read(), 'base64', 'utf-8')
#         att["Content-Type"] = 'application/octet-stream'
#         att["Content-Disposition"] = 'attachment;filename=' + os.path.basename(f)
#         msg.attach(att)
# 输入Email地址和口令
from_addr = '[email protected]'    # 发送邮件的邮箱账号
password = '@8ddr'                # 发送邮件的邮箱密码,无需提供
to_addr = '[email protected]'        # 接收邮件的邮箱账号
smtp_server = '211.71.136.200'        # 发送邮件邮箱的STMP服务器地址
title = '金融时报和第一财经日报今天数据'
mail_body = '问好:\n\n          附件是金融时报和第一财经日报今天的采集数据\n\n          有问题,请及时联系,谢谢。'

fileList = []

fileName = "E:\\News\\2018-09-28.csv"
fileList.append(fileName)
fileName = "E:\\News\\2018-09-29.csv"
fileList.append(fileName)
Me_email(from_addr,password,to_addr,smtp_server,title,mail_body,fileList)
View Code

 

python SendMail 发送邮件python SendMail 发送邮件
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.utils import parseaddr,formataddr
import smtplib
import datetime
import os
import mail_setting

class Mail:
    def __init__(self):
        pass

    def init(self):
        setobj = mail_setting.mail_setting()
        # 邮件服务器IP
        self.mail_host = setobj.mail_host
        # 邮件服务器端口:587
        self.port = setobj.mail_port
        # 发送人
        self.mail_send = setobj.mail_send
        # 邮件发送人登录密码
        self.mail_pass = setobj.mail_pass
        # 介绍人,多个以逗号分隔
        self.mail_receive = str(setobj.mail_receive)
        # 抄送,多个以逗号分隔
        self.mail_chao = str(setobj.mail_chao)
        # 邮件主题内容
        self.mail_subject = setobj.mail_subject
        # 邮件体内容
        self.mail_body = setobj.mail_body
        # 发送的附件路径
        self.attachmentFileDir = setobj.attachmentFileDir
    # 最终结果通过Email发送

    def _format_addr(self, s):
        name, addr = parseaddr(s)
        return formataddr((Header(name, 'utf-8').encode(), addr))

    def Me_email(self, from_addr, password, to_addr, to_chao, smtp_server, title, mail_body, fileList):
        # msg = MIMEText('%s' % (result),'plain','utf-8')            # 邮件显示内容
        msg = MIMEMultipart()
        message = MIMEText(mail_body, _subtype='plain', _charset='utf-8')
        msg.attach(message)
        msg['From'] = self._format_addr('ICTR <%s>' % from_addr)  # 邮件发送人
        # msg['To'] = _format_addr('管理员 <%s>' % to_addr)
        msg['To'] = to_addr
        if to_chao:
            msg['Cc'] = to_chao
        msg['Subject'] = Header('%s' % (title), 'utf-8').encode()  # 邮件title
        for f in fileList:
            if os.path.isfile(f):
                att = MIMEText(open(f, 'rb').read(), 'base64', 'utf-8')
                att["Content-Type"] = 'application/octet-stream'
                att.add_header('Content-Disposition', 'attachment', filename=('gbk', '', os.path.basename(f)))
                msg.attach(att)
        server = smtplib.SMTP(smtp_server, 587)
        # server.set_debuglevel(1)
        server.login(from_addr, password)
        # server.sendmail(from_addr,[to_addr,'[email protected]','[email protected]'],msg.as_string())
        lst = "[email protected],[email protected],[email protected]".split(',')
        server.sendmail(from_addr, lst, msg.as_string())
        server.quit()

    def SendMail(self, mail_tolist, mail_cclist, fileList):
        ''' 发送邮件
                  :param mail_tolist: 接收者邮件列表,如:['[email protected]','[email protected]']
                  :param mail_cclist: 抄送列表,同上
                  :param fileList: 文件列表,同上
              '''
        try:
            msg = MIMEMultipart()
            message = MIMEText(self.mail_body, _subtype='plain', _charset='utf-8')
            msg.attach(message)
            msg['Subject'] = self.mail_subject
            msg['From'] = self._format_addr('ICTR <%s>' % self.mail_send)

            if mail_tolist:
                msg['To'] = ",".join(mail_tolist)
            if len(mail_cclist) > 0:
                msg['Cc'] = ",".join(mail_cclist)
                mail_tolist.extend(mail_cclist)

            if fileList:
                for f in fileList:
                    if os.path.isfile(f):
                        att = MIMEText(open(f, 'rb').read(), 'base64', 'utf-8')
                        att["Content-Type"] = 'application/octet-stream'
                        att.add_header('Content-Disposition', 'attachment', filename=('gbk', '', os.path.basename(f)))
                        msg.attach(att)

            server = smtplib.SMTP(self.mail_host, self.port)
            # 调试状态设置
            # server.set_debuglevel(1)
            server.login(self.mail_send, self.mail_pass)
            server.sendmail(self.mail_send, mail_tolist, msg.as_string())
            server.quit()
        except smtplib.SMTPException as e:
            print("Error: 无法发送邮件")

    def test(self):
        self.init()

        fileList = []
        dt = datetime.datetime.now().strftime("%Y-%m-%d")
        fileName = '金融时报_' + dt + '.csv'
        fileName = os.path.join(self.attachmentFileDir, fileName)
        if os.path.exists(fileName):
            fileList.append(fileName)

        fileName = '第一财经日报_' + dt + '.csv'
        fileName = os.path.join(self.attachmentFileDir, fileName)
        if os.path.exists(fileName):
            fileList.append(fileName)

        # 如果没有附件就不发邮件
        if fileList:
            mail_tolist = []
            if self.mail_receive.find(",") > 0:
                users = self.mail_receive.split(",")
                for user in users:
                    mail_tolist.append(user)
            else:
                mail_tolist.append(self.mail_receive)

            mail_cclist = []
            if self.mail_chao:
                if self.mail_chao.find(",") > 0:
                    users = self.mail_chao.split(",")
                    for user in users:
                        mail_cclist.append(user)
                else:
                    mail_cclist.append(self.mail_chao)

            self.SendMail(mail_tolist, mail_cclist, fileList)
View Code

 

 

 

相关文章: