python批量发送邮件--包括批量不同附件

Python014

python批量发送邮件--包括批量不同附件,第1张

小猪在公司做出纳,干的活却包括了出纳、会计、结算专员等工作,周末都要被无奈在家加班,主要还没有加班费,简直是被公司严重压榨。每个月初都要给每个工长发预付款账单邮件,月中发结算款账单。重复性机械工作。

一个及格线上的程序员,最起码的觉悟就是将重复性的机械工作自动化,于是,在我花了一个多小时,帮她给一部分工长发了一次邮箱后,默默的回来写了这个脚本。

所以,设计要点就是一个字——

恩,就酱。

经过我观察,邮件内容分为两种,这里先说第一种,“结算款”:

(1) 邮件内容(content)不变,为固定的txt文本

(2) 附件(attch)为每个工长的结算账单(excel文件.xlsx),此文件命名为总账单中自动分割出来的名字(暂时不懂怎么分割出来的=.=),格式为:

(3) 邮件主题(Subject)为附件名(不带后缀名)

(4) 邮件接收对象(工长)的名单及其邮箱地址基本不变,偶尔变动

(5)

(1) 将工长及其邮箱地址存为CSV文件的两列,python中将其读取为字典形式,存储以供后续查询邮箱地址。

(2) 遍历文件夹中的附件(.xlsx类型文件),对其进行两种操作,一方面将其名字(不带路径和后缀)提取出来,作为邮件主题(Subject),并对Subject进一步划分,得到其中的人名(工长);另一方面,将其传入MIMEbase模块中转为邮件附件对象。

(3) 由上述得到的人名(name),在字典形式的通讯录中,查找相应的地址(value),即为收件人名称和地址

(4) 利用python中的email模块和smtp模块,登录自己的邮箱账号,再对每个附件,得到的收件人名和地址,添加附件,发送邮件。done

在设计过程中有几点需要注意

(1) 有时一个邮件地址对应两个人名,此时应该在CSV文件中分为两行存储,而不是将两个人名存为同一个键;

(2)有账单.xlsx文件,通讯录里却没存储此人记录,程序应该打印提示没有通讯记录的人名,且不能直接退出,要保证员工看到此提示,此第一版程序还有解决此问题;

(3)此程序发送的邮件内容为纯文本,若要求邮件内容有不同格式(如部分加粗,部分红色),还有小部分需要每次更改的地方(如邮件内容包含当前月份),如何解决?(这就是第二种邮件内容,“预算款”);

(4)重名的,暂时还没碰到,程序中也没给出解决方案。

第一版到此,20180830,待更新

第二版更新,20180904

第三版更新,20180909

转战CSDN博客,更多博客见传送门《 xiaozhou的博客主页 》

''''' 

函数说明:Send_email_text() 函数实现发送带有附件的邮件,可以群发,附件格式包括:xlsx,pdf,txt,jpg,mp3等 

参数说明: 

    1. subject:邮件主题 

    2. content:邮件正文 

    3. filepath:附件的地址, 输入格式为["","",...] 

    4. receive_email:收件人地址, 输入格式为["","",...] 

'''  

def Send_email_text(subject,content,filepath,receive_email):  

    import smtplib  

    from email.mime.multipart import MIMEMultipart   

    from email.mime.text import MIMEText   

    from email.mime.application import MIMEApplication  

    sender = "发送方邮箱"  

    passwd = "填入发送方密码"  

    receivers = receive_email   #收件人邮箱  

      

    msgRoot = MIMEMultipart()   

    msgRoot['Subject'] = subject  

    msgRoot['From'] = sender  

      

    if len(receivers)>1:  

        msgRoot['To'] = ','.join(receivers) #群发邮件  

    else:  

        msgRoot['To'] = receivers[0]  

      

    part = MIMEText(content)   

    msgRoot.attach(part)  

      

    ##添加附件部分  

    for path in filepath:  

        if ".jpg" in path:  

            #jpg类型附件  

            jpg_name = path.split("\\")[-1]  

            part = MIMEApplication(open(path,'rb').read())   

            part.add_header('Content-Disposition', 'attachment', filename=jpg_name)  

            msgRoot.attach(part)  

          

        if ".pdf" in path:  

            #pdf类型附件  

            pdf_name = path.split("\\")[-1]  

            part = MIMEApplication(open(path,'rb').read())   

            part.add_header('Content-Disposition', 'attachment', filename=pdf_name)   

            msgRoot.attach(part)  

          

        if ".xlsx" in path:  

            #xlsx类型附件  

            xlsx_name = path.split("\\")[-1]  

            part = MIMEApplication(open(path,'rb').read())   

            part.add_header('Content-Disposition', 'attachment', filename=xlsx_name)  

            msgRoot.attach(part)  

              

        if ".txt" in path:  

            #txt类型附件  

            txt_name = path.split("\\")[-1]  

            part = MIMEApplication(open(path,'rb').read())  

            part.add_header('Content-Disposition', 'attachment', filename=txt_name)  

            msgRoot.attach(part)  

          

        if ".mp3" in path:  

            #mp3类型附件  

            mp3_name = path.split("\\")[-1]  

            part = MIMEApplication(open(path,'rb').read())   

            part.add_header('Content-Disposition', 'attachment', filename=mp3_name)   

            msgRoot.attach(part)  

              

    try:  

        s = smtplib.SMTP()  

        s.connect("smtp.mail.aliyun.com") #这里我使用的是阿里云邮箱,也可以使用163邮箱:smtp.163.com  

        s.login(sender, passwd)  

        s.sendmail(sender, receivers, msgRoot.as_string())  

        print ("邮件发送成功")  

    except smtplib.SMTPException as e:  

        print("Error, 发送失败")  

    finally:  

        s.quit()

首先了解SMTP(简单邮件传输协议),邮件传送代理程序使用SMTP协议来发送电邮到接收者的邮件服务器。SMTP协议只能用来发送邮件,不能用来接收邮件,而大多数的邮件发送服务器都是使用SMTP协议。SMTP协议的默认TCP端口号是25。

本文主要介绍利用'smtplib','email'两个模块来实现邮件的发送,可以如下查看两个模块的函数和方法:

smtplib模块简介:

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

  此为SMTP类构造函数,表示与SMTP服务器之间的连接,并根据这个连接向smtp服务器发送指令,执行相关操作(如:登陆、发送邮件),且每个参数都是可选的。

其中最重要的参数:

host:smtp服务器主机名

port:smtp服务的端口,默认是25;

如果在创建SMTP对象的时候提供了这两个参数,在初始化的时候会自动调用connect方法去连接服务器。

smtplib.SMTP还提供了如下方法:

SMTP.set_debuglevel(level):设置是否为调试模式

SMTP.connect([host[, port]]):连接到指定的smtp服务器。参数分别表示 smpt主机和端口。

SMTP.docmd(cmd[, argstring]):向smtp服务器发送指令。

SMTP.helo([hostname]) :使用"helo"指令向服务器确认身份。

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

SMTP.sendmail(from_addr,to_addrs,msg[,mail_options,rcpt_options]):发送邮件。这里要注意一下第三个参数,msg是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,附件等构成,发送邮件的时候,要注意msg的格式。这个格式就是smtp协议中定义的格式。SMTP.quit() :断开与smtp服务器的连接,相当于发送"quit"指令。(重要!)

常用的函数方法:

email模块

1.class email.message.Message

__getitem__,__setitem__实现obj[key]形式的访问。

Msg.attach(playload): 向当前Msg添加playload。

Msg.set_playload(playload):

Msg.add_header(_name, _value, **_params): 添加邮件头字段。

2.class email.mime.base.MIMEBase(_maintype, _subtype, **_params)

所有MIME类的基类,是email.message.Message类的子类。

3.class email.mime.multipart.MIMEMultipart()

在3.0版本的email模块 (Python 2.3-Python 2.5) 中,这个类位于email.MIMEMultipart.MIMEMultipart。这个类是MIMEBase的直接子类,用来生成包含多个部分的邮件体的MIME对象。

4.class email.mime.text.MIMEText(_text)

使用字符串_text来生成MIME对象的主体文本。

获得所需要使用的邮箱的host地址和port端口号,(本文使用的是163邮箱,对应的smtp服务器地址:mail.163.com,端口号25)

常用邮箱的smtp服务器地址和端口号如图:

编写程序如下:

#! /usr/bin/env python

import smtpli

from email.mime.text import MIMEText

mailto_list=['[email protected]'] #收件人(列表)

mail_host="smtp.163.com"#使用的邮箱的smtp服务器地址

mail_user="name" #用户名

mail_pass="pwd" #密码

mail_postfix="postfix" #邮箱的后缀

def send_mail(to_list,sub,content):

me="hello"+"<"+mail_user+"@"+mail_postfix+">"

msg = MIMEText(content,_subtype='plain')

msg['Subject'] = sub

msg['From'] = me

msg['To'] = "".join(to_list)#将收件人列表以‘;’分隔

try:

server = smtplib.SMTP()

server.connect(mail_host)#连接服务器

server.login(mail_user,mail_pass) #登录操作

server.sendmail(me, to_list, msg.as_string())

server.close()

return True

except Exception, e:

print str(e)

return False

for i in range(5): #发送五封,不过会被拦截的。。。

if send_mail(mailto_list,"hello","haha!"): #邮件主题和邮件内容

print "done!"

else:

print "failed!"

最后,可以运行编写的py文件,可以得到如图所是的结果,代表邮件发送成功。

这样,就能成功实现用Python发送邮件啦!