python 工资邮件群发工具开发(一个小公司的需求)

------------------------------------

该需求有两个表格,第一个表格是计算薪资的,第二个表格是员工信息,包括姓名和邮箱

这里只要把薪资表按照每个人截图放到一个文件夹中,从信息表取姓名和截图名字做对应,然后发送邮件

 1、工资表样式,名字必须和员工信息表一致

 

2、员工信息表样式注意列,我没有做行列自定义选择的功能,现在是写死的,当然也可以加个变量自定义

 

软件样式:

 

 

 

本程序是根据员工信息表的基础,来判定是否成功发送邮件,如果工资表没有这个人,那么也没有这个人的截图,那这个人就未发送。

 授权码就是qq邮箱的 第三方授权

 --------------------------------------------------

用到的包pillow 、xlwings、email、tkinter(界面UI)

-----------------------------------

这里不多废话,直接贴代码

  1 from PIL import ImageGrab
  2 import xlwings as xw
  3 import smtplib
  4 from email.mime.multipart import MIMEMultipart
  5 from email.mime.text import MIMEText
  6 from email.mime.image import MIMEImage
  7 import tkinter as tk  # 使用Tkinter前需要先导入
  8 from tkinter import filedialog
  9 import os
 10 import time
 11 
 12 class Monitor():
 13     def __init__(self):
 14         #错误信息
 15         self.error = []
 16         self.nosend = []
 17         self.dictname =[]
 18 
 19     #判断文件夹是否已经创建
 20     def is_exists(self,dir):
 21         if not os.path.exists(dir):
 22             os.makedirs(dir)
 23 
 24     # 截图函数
 25     def excel_catch_screen(self,wbs,save_floder,shot_sheetname):
 26         sheet = wbs.sheets(shot_sheetname)  # 选定sheet
 27         all = sheet.used_range  # 获取有内容的range
 28         all.api.CopyPicture()  # 复制图片区域
 29         sheet.api.Paste()  # 粘贴
 30         pic = sheet.pictures[0]  # 当前图片
 31         pic.api.Copy()  # 复制图片
 32         img = ImageGrab.grabclipboard()  # 获取剪贴板的图片数据
 33         self.is_exists(save_floder)  # 判断文件夹
 34         try:
 35             img.save(save_floder+'/'+shot_sheetname + ".png")  # 保存图片
 36             pic.delete()  # 删除sheet上的图片
 37         except:
 38             print('%s 截图失败!'%shot_sheetname)
 39 
 40 
 41     #   邮件函数
 42     #   1、查看邮件excel中的所有对应值  (name,email)
 43     def get_info(self,dicts,info):
 44         app = xw.App(visible=False, add_book=False)
 45         wb = app.books.open(info)
 46         sheet = wb.sheets[0]
 47         maxrow = sheet.used_range.last_cell.row   # 最大行
 48         for row in range(2,maxrow+1):
 49             name = sheet.range('B' + str(row)).value
 50             email = str(sheet.range('J' + str(row)).value).replace('@qq.com','')
 51             dicts[name] = email.replace('.0','')+'@qq.com'
 52         wb.close()
 53         app.quit()
 54     #2、发送邮件
 55     def send_png(self,subject,sender,name,receivers,password,png):
 56         message = MIMEMultipart('related')
 57         message['Subject'] = subject
 58         message['From'] = sender
 59         message['To'] = receivers
 60         content = MIMEText('<html><body><img src="cid:imageid" alt="imageid"></body></html>','html','utf-8')
 61         message.attach(content)
 62         file=open(png, "rb")
 63         img_data = file.read()
 64         file.close()
 65         img = MIMEImage(img_data)
 66         img.add_header('Content-ID', 'imageid')
 67         message.attach(img)
 68         try:
 69             server=smtplib.SMTP_SSL("smtp.qq.com",465)
 70             server.login(sender,password) #"填写qq邮箱的授权码"
 71             server.sendmail(sender,receivers,message.as_string())
 72             server.quit()
 73             print ("邮件发送成功")
 74         except smtplib.SMTPException as e:
 75             self.error.append(name)
 76             pass
 77 
 78     def work(self,subject,sender,password,excel_name,info_name):
 79         sheetname=[]
 80         app = xw.App(visible=False, add_book=False)
 81         wb = app.books.open(excel_name)
 82         num = len(wb.sheets)
 83         #用sheetname 接受所有员工的sheet名
 84         for i in range(1,num):
 85             sheet = wb.sheets[i]
 86             sheetname.append(sheet.name)
 87         #循环截屏并保存到自定义文件夹下
 88         save_floder = './'+subject
 89         for name in sheetname:
 90             self.excel_catch_screen(wb,save_floder,name)
 91             time.sleep(5)
 92         #存储员工信息表
 93         dicts = {}
 94         self.get_info(dicts,info_name)
 95 
 96         wb.close()  # 不保存,直接关闭
 97         app.quit()
 98         #循环发送邮件 #发送邮件 根据excel中的邮件人姓名和地址进行匹配已保存的png图片,顺序发送
 99         # 遍历字典,在文件夹中找对应图片
100         for name, receivers in dicts.items():
101             self.dictname.append(name)
102         for file in os.listdir(save_floder):
103             self.nosend.append(file.replace('.png',''))
104         for name, receivers in dicts.items():
105             if name in self.nosend:
106                 self.send_png(subject,sender,name,receivers,password,save_floder+'/'+name+'.png')
107                 print(sender,receivers,name,save_floder+'/'+name+'.png')
108             else:
109                 self.error.append(name)
110 
111     def main(self):
112         # password = 'zbtwghtciidmbaii'
113         # 界面化处理
114         window = tk.Tk()
115         window.title('邮件群发V1.0')
116         # 第3步,设定窗口的大小(长 * 宽)
117         window.geometry('400x400')  # 这里的乘是小x
118 
119         def selectPath():
120             entry_excel_name = filedialog.askopenfilename(title='选择工资计算表',
121                       initialdir='/', filetypes=[('.xlsx','*.xlsx'),('全部文件','*.*')])
122             return entry_excel_name
123         def selectPath1():
124             entry_info_name = filedialog.askopenfilename(title='选择员工信息表',
125                       initialdir='/', filetypes=[('.xlsx','*.xlsx'),('全部文件','*.*')])
126             return entry_info_name
127 
128         def exec(entry_excel_name,entry_info_name):
129             try:
130                 subject = entry_title.get()
131                 sender = entry_usr_name.get()
132                 password = entry_usr_pwd.get()
133                 excel_name = entry_excel_name
134                 info_name = entry_info_name
135 
136                 self.work(subject,sender,password,excel_name,info_name)
137                 if len(self.error) == 0:
138                     text.insert('insert','所有邮件发送成功')
139                 else:
140                     text.insert('insert','%s 邮件发送失败' % self.error)
141 
142             except Exception as e:
143                 if e == 'No such file: ':
144                     text.insert('insert','没有选择文件')
145                 else:
146                     text.insert('insert',e)
147 
148 
149         # 用户信息
150         tk.Label(window, text='邮件标题:', font=('Arial', 10)).place(x=10, y=5)
151         tk.Label(window, text='Q Q 号:', font=('Arial', 10)).place(x=10, y=35)
152         tk.Label(window, text='授权码:', font=('Arial', 10)).place(x=10, y=65)
153 
154         subject = tk.StringVar()
155         subject.set('XX年XX月薪资')
156         entry_title = tk.Entry(window, textvariable=subject, font=('Arial', 10))
157         entry_title.place(x=120, y=5)
158 
159         var_usr_name = tk.StringVar()
160         var_usr_name.set('[email protected]')
161         entry_usr_name = tk.Entry(window, textvariable=var_usr_name, font=('Arial', 10))
162         entry_usr_name.place(x=120, y=35)
163 
164         var_usr_pwd = tk.StringVar()
165         entry_usr_pwd = tk.Entry(window, textvariable=var_usr_pwd, font=('Arial', 10), show='*')
166         entry_usr_pwd.place(x=120, y=65)
167 
168         #程序运行框
169         text = tk.Text(window, show=None)
170         text.place(relx=0.01,rely=0.3,relwidth=0.98,relheight=0.7)
171 
172         # 执行按钮
173         btn_login = tk.Button(window, text='立即执行',height = 4,  width = 15 ,command= lambda : exec(selectPath(),selectPath1()))
174         btn_login.place(x=275, y=6)
175 
176         # 主窗口循环显示
177         window.mainloop()
178 
179 if __name__ == '__main__':
180     app = Monitor()
181     app.main()
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章