一.软件功能
邮件批量发送软件可以模拟手动发送过程,实现邮件的批量发送,节省工作量,提高工作效率。
二.代码实现
代码分两部分,软件界面设计及功能函数设计。
2.1 界面设计
界面用pyqt5进行设计,分为两部分:发送设置与内容设置。
2.2 功能实现
功能部分主要包括界面内容的读取与邮件发送。
界面读取包括从界面部分读取相应的用户名、授权码、发送间隔等信息。
邮件发送分为创建实例、添加邮件文字部分、添加邮件附件部分。
def send_functtion(self, receivers):
msg = MIMEMultipart() # 创建一个带附件的实例
msg["Subject"] = mail_subject
msg["From"] = mail_user
msg["To"] = ','.join([receivers])
# ---文字部分---
part = MIMEText(mail_text)
msg.attach(part)
# ---附件部分---
part = MIMEApplication(open(mail_txt_add, 'rb').read())
part.add_header('Content-Disposition', 'attachment', filename=os.path.basename(mail_txt_add))
msg.attach(part)
try:
s = smtplib.SMTP(mail_smtp, timeout=(mail_span_time*len(receiver_list)+1000)) # 连接smtp邮件服务器,端口默认是25;超时时间设置大一点
s.login(mail_user, mail_pass) # 登陆服务器
s.sendmail(mail_user, receivers, msg.as_string()) # 发送邮件
s.close()
except Exception as e:
print("error:", e)
三.软件使用及注意事项
3.1 软件使用方法
使用时,在发送设置中输入邮箱用户名、SMTP授权码、发送间隔,选择存放目标邮件地址的txt文件。
SMTP授权码获取方法可以自行百度。
内容设置中输入邮件主题、正文,选择邮件的附件。
设置完成后点击“发送”按钮,提示窗中显示发送进度具体内容,下方显示发送进度条。
3.2 软件注意事项
(1)存放目标邮件地址的txt文件中:不同邮件地址需以“,”(英文)隔开,且除了地址和逗号外不能存在其他内容,如回车等;
(2)邮件的附件只能选择一个,适用于txt、word、pdf类型的文件,其他文件不宜超过500KB,其余情况请自行测试。
附录:代码源码
界面代码
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'windows_screen.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(819, 625)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.user_label = QtWidgets.QLabel(self.centralwidget)
self.user_label.setGeometry(QtCore.QRect(40, 86, 131, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.user_label.setFont(font)
self.user_label.setObjectName("user_label")
self.user_lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.user_lineEdit.setGeometry(QtCore.QRect(170, 90, 371, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.user_lineEdit.setFont(font)
self.user_lineEdit.setAlignment(QtCore.Qt.AlignCenter)
self.user_lineEdit.setObjectName("user_lineEdit")
self.pass_lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.pass_lineEdit.setGeometry(QtCore.QRect(170, 150, 371, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.pass_lineEdit.setFont(font)
self.pass_lineEdit.setAlignment(QtCore.Qt.AlignCenter)
self.pass_lineEdit.setObjectName("pass_lineEdit")
self.pass_label = QtWidgets.QLabel(self.centralwidget)
self.pass_label.setGeometry(QtCore.QRect(40, 146, 131, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.pass_label.setFont(font)
self.pass_label.setObjectName("pass_label")
self.title_lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.title_lineEdit.setGeometry(QtCore.QRect(170, 360, 461, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.title_lineEdit.setFont(font)
self.title_lineEdit.setText("")
self.title_lineEdit.setObjectName("title_lineEdit")
self.title_label = QtWidgets.QLabel(self.centralwidget)
self.title_label.setGeometry(QtCore.QRect(40, 356, 131, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.title_label.setFont(font)
self.title_label.setObjectName("title_label")
self.addtxt_pushButton = QtWidgets.QPushButton(self.centralwidget)
self.addtxt_pushButton.setGeometry(QtCore.QRect(580, 480, 51, 41))
self.addtxt_pushButton.setObjectName("addtxt_pushButton")
self.addtxt_label = QtWidgets.QLabel(self.centralwidget)
self.addtxt_label.setGeometry(QtCore.QRect(40, 476, 121, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.addtxt_label.setFont(font)
self.addtxt_label.setObjectName("addtxt_label")
self.addtxt_lineEdit = QtWidgets.QLineEdit(self.centralwidget)
self.addtxt_lineEdit.setEnabled(True)
self.addtxt_lineEdit.setGeometry(QtCore.QRect(170, 480, 411, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.addtxt_lineEdit.setFont(font)
self.addtxt_lineEdit.setObjectName("addtxt_lineEdit")
self.send_groupBox = QtWidgets.QGroupBox(self.centralwidget)
self.send_groupBox.setGeometry(QtCore.QRect(20, 326, 631, 211))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.send_groupBox.setFont(font)
self.send_groupBox.setObjectName("send_groupBox")
self.main_lineEdit = QtWidgets.QLineEdit(self.send_groupBox)
self.main_lineEdit.setGeometry(QtCore.QRect(150, 90, 461, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.main_lineEdit.setFont(font)
self.main_lineEdit.setText("")
self.main_lineEdit.setObjectName("main_lineEdit")
self.main_label = QtWidgets.QLabel(self.send_groupBox)
self.main_label.setGeometry(QtCore.QRect(20, 86, 131, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.main_label.setFont(font)
self.main_label.setObjectName("main_label")
self.set_groupBox = QtWidgets.QGroupBox(self.centralwidget)
self.set_groupBox.setGeometry(QtCore.QRect(20, 66, 551, 251))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.set_groupBox.setFont(font)
self.set_groupBox.setObjectName("set_groupBox")
self.span_label = QtWidgets.QLabel(self.set_groupBox)
self.span_label.setGeometry(QtCore.QRect(20, 136, 131, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.span_label.setFont(font)
self.span_label.setObjectName("span_label")
self.span_lineEdit = QtWidgets.QLineEdit(self.set_groupBox)
self.span_lineEdit.setGeometry(QtCore.QRect(150, 140, 321, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.span_lineEdit.setFont(font)
self.span_lineEdit.setAlignment(QtCore.Qt.AlignCenter)
self.span_lineEdit.setObjectName("span_lineEdit")
self.oddtxt_label = QtWidgets.QLabel(self.set_groupBox)
self.oddtxt_label.setGeometry(QtCore.QRect(20, 200, 271, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.oddtxt_label.setFont(font)
self.oddtxt_label.setObjectName("oddtxt_label")
self.oddtxt_lineEdit = QtWidgets.QLineEdit(self.set_groupBox)
self.oddtxt_lineEdit.setEnabled(True)
self.oddtxt_lineEdit.setGeometry(QtCore.QRect(230, 200, 241, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.oddtxt_lineEdit.setFont(font)
self.oddtxt_lineEdit.setObjectName("oddtxt_lineEdit")
self.oddtxt_pushButton = QtWidgets.QPushButton(self.set_groupBox)
self.oddtxt_pushButton.setGeometry(QtCore.QRect(470, 200, 51, 41))
self.oddtxt_pushButton.setObjectName("oddtxt_pushButton")
self.span_unit_label = QtWidgets.QLabel(self.set_groupBox)
self.span_unit_label.setGeometry(QtCore.QRect(480, 136, 41, 51))
self.span_unit_label.setObjectName("span_unit_label")
self.labtitle_label = QtWidgets.QLabel(self.centralwidget)
self.labtitle_label.setGeometry(QtCore.QRect(260, 20, 261, 41))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.labtitle_label.setFont(font)
self.labtitle_label.setFrameShape(QtWidgets.QFrame.Box)
self.labtitle_label.setAlignment(QtCore.Qt.AlignCenter)
self.labtitle_label.setObjectName("labtitle_label")
self.sendp_label = QtWidgets.QLabel(self.centralwidget)
self.sendp_label.setGeometry(QtCore.QRect(20, 540, 131, 51))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.sendp_label.setFont(font)
self.sendp_label.setObjectName("sendp_label")
self.send_progressBar = QtWidgets.QProgressBar(self.centralwidget)
self.send_progressBar.setGeometry(QtCore.QRect(140, 550, 661, 31))
self.send_progressBar.setProperty("value", 0)
self.send_progressBar.setObjectName("send_progressBar")
self.information_groupBox = QtWidgets.QGroupBox(self.centralwidget)
self.information_groupBox.setGeometry(QtCore.QRect(580, 66, 221, 251))
self.information_groupBox.setObjectName("information_groupBox")
self.send_textBrowser = QtWidgets.QTextBrowser(self.information_groupBox)
self.send_textBrowser.setGeometry(QtCore.QRect(10, 29, 201, 211))
self.send_textBrowser.setObjectName("send_textBrowser")
self.send_pushButton = QtWidgets.QPushButton(self.centralwidget)
self.send_pushButton.setGeometry(QtCore.QRect(660, 360, 141, 161))
font = QtGui.QFont()
font.setFamily("Arial")
font.setPointSize(12)
self.send_pushButton.setFont(font)
self.send_pushButton.setObjectName("send_pushButton")
self.set_groupBox.raise_()
self.send_groupBox.raise_()
self.user_label.raise_()
self.user_lineEdit.raise_()
self.pass_lineEdit.raise_()
self.pass_label.raise_()
self.title_lineEdit.raise_()
self.title_label.raise_()
self.addtxt_pushButton.raise_()
self.addtxt_label.raise_()
self.addtxt_lineEdit.raise_()
self.labtitle_label.raise_()
self.sendp_label.raise_()
self.send_progressBar.raise_()
self.information_groupBox.raise_()
self.send_pushButton.raise_()
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 819, 30))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "邮件批量发送软件"))
self.user_label.setText(_translate("MainWindow", "用户名:"))
self.pass_label.setText(_translate("MainWindow", "授权码:"))
self.title_label.setText(_translate("MainWindow", "主题:"))
self.addtxt_pushButton.setText(_translate("MainWindow", "..."))
self.addtxt_label.setText(_translate("MainWindow", "附件:"))
self.send_groupBox.setTitle(_translate("MainWindow", "内容设置"))
self.main_label.setText(_translate("MainWindow", "正文:"))
self.set_groupBox.setTitle(_translate("MainWindow", "发送设置"))
self.span_label.setText(_translate("MainWindow", "发送间隔:"))
self.span_lineEdit.setText(_translate("MainWindow", "1"))
self.oddtxt_label.setText(_translate("MainWindow", "目标地址邮箱文件:"))
self.oddtxt_pushButton.setText(_translate("MainWindow", "..."))
self.span_unit_label.setText(_translate("MainWindow", "秒"))
self.labtitle_label.setText(_translate("MainWindow", "邮件批量发送软件"))
self.sendp_label.setText(_translate("MainWindow", "发送进度:"))
self.information_groupBox.setTitle(_translate("MainWindow", "提示窗"))
self.send_pushButton.setText(_translate("MainWindow", "发送"))
功能代码
import sys,os,time
from PyQt5.QtCore import QThread,pyqtSignal
from PyQt5.QtWidgets import QApplication,QMainWindow,QFileDialog
import smtplib # smtp协议封装库;email用来创建邮件
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.application import MIMEApplication
import windows_screen
# QT多线程:界面相应的功能函数
class mailsend_thread(QThread):
# 创建槽变量
send_a_data = pyqtSignal(int) # 弹出发送进度条数据
txt_a_data = pyqtSignal(str) # 弹出发送进度数据
def __init__(self, parent=None):
super(mailsend_thread, self).__init__(parent)
#设置工作状态与初始num数值
self.send_progressBar_data = 0
self.send_a_data.emit(self.send_progressBar_data)
# 发送邮件函数
def run(self):
i_sum = 0 # 发送邮件序号
for i in receiver_list:
self.send_functtion(i) # 调用发送函数:传入发送邮箱地址
i_sum += 1
self.send_progressBar_data = int((i_sum / len(receiver_list))*100) # 统计发送进度
self.str_data = str(i_sum) # 字符化发送序号
self.txt_a_data.emit(self.str_data) # 弹出发送进度条数据
self.send_a_data.emit(self.send_progressBar_data) # 弹出发送进度
time.sleep(mail_span_time) # 发送延时
self.send_a_data.emit(100) # 发送完成后填满进度条
# 发送函数
# mail_user为邮箱用户名,mail_pass为授权码,receivers为接收邮箱地址(列表格式)
# mail_subject为邮箱主题,mail_text为正文内容,mail_txt_add为附件地址
def send_functtion(self, receivers):
msg = MIMEMultipart() # 创建一个带附件的实例
msg["Subject"] = mail_subject
msg["From"] = mail_user
msg["To"] = ','.join([receivers])
# ---文字部分---
part = MIMEText(mail_text)
msg.attach(part)
# ---附件部分---
part = MIMEApplication(open(mail_txt_add, 'rb').read())
part.add_header('Content-Disposition', 'attachment', filename=os.path.basename(mail_txt_add))
msg.attach(part)
try:
s = smtplib.SMTP(mail_smtp, timeout=(mail_span_time*len(receiver_list)+1000)) # 连接smtp邮件服务器,端口默认是25;超时时间设置大一点
s.login(mail_user, mail_pass) # 登陆服务器
s.sendmail(mail_user, receivers, msg.as_string()) # 发送邮件
s.close()
except Exception as e:
print("error:", e)
# 软件主界面
class a0_MyMainForm(QMainWindow,windows_screen.Ui_MainWindow):
def __init__(self,parent=None):
super(a0_MyMainForm,self).__init__(parent)
#加载页面
self.setupUi(self)
self.initUI()
# 禁止窗口放大
self.setFixedSize(self.width(), self.height())
#链接函数
def initUI(self):
# 1.选择发送邮件地址文件
self.oddtxt_pushButton.clicked.connect(self.oddtxt_function)
# 2.选择附件
self.addtxt_pushButton.clicked.connect(self.addtxt_function)
# 3.发送
self.send_pushButton.clicked.connect(self.send_function)
# 1.选择发送邮件地址文件
def oddtxt_function(self):
send_directory = QFileDialog.getOpenFileName(self, "选取文件", "./", "All Files (*);;Text Files (*.txt)")
if send_directory:
# 如果选择了路径
# 取返回第一个字符串(返回值:第一个为地址,第二个为类型)
send_address = send_directory[0]
else:
# 未选择路径
send_address = ''
# 显示选取的地址
self.oddtxt_lineEdit.setText(send_address)
# 2.选择附件
def addtxt_function(self):
send_directory = QFileDialog.getOpenFileName(self, "选取文件", "./", "All Files (*);;Text Files (*.txt)")
if send_directory:
# 如果选择了路径
send_address = send_directory[0]
else:
# 未选择路径
send_address = ''
# 显示选取的地址
self.addtxt_lineEdit.setText(send_address)
# 3.获取发送参数
def send_function(self):
# 声明为全局变量,直接调取,具体变量解释见下
global mail_user, mail_smtp, mail_pass, receiver_list
global mail_subject, mail_text, mail_txt_add,mail_span_time
# 3.1 mail_user为邮箱用户名
mail_user = self.user_lineEdit.text()
# 3.2 mail_smtp 为邮箱服务器类型
mail_sort = mail_user.split('@')[1] # 截取邮箱后缀
mail_smtp = "smtp."+mail_sort # 生成邮箱服务器类型
# 3.3 mail_pass为授权码
mail_pass = self.pass_lineEdit.text()
# 3.4 receivers为接收邮箱地址(列表格式)
receiver_txt_add = self.oddtxt_lineEdit.text() # 读取接收邮箱文件地址
file = open(receiver_txt_add) # 打开文件
rec_txt = file.read() # 读取文件内容
file.close() # 读取完成后关闭文件
receiver_list = [] # 创建接收邮箱地址存放列表
for i in rec_txt.split(','): # 写入接收邮箱地址
receiver_list.append(i)
# 3.5 mail_subject为邮箱主题
mail_subject = self.title_lineEdit.text()
# 3.6 mail_text为正文内容
mail_text = self.main_lineEdit.text()
# 3.7 mail_txt_add为附件地址
mail_txt_add = self.addtxt_lineEdit.text()
# 3.8 mail_span_time为发送间隔时间
try:
mail_span_time = float(self.span_lineEdit.text())
except:
mail_span_time = 0
# 3.9 开始发送邮件
self.send_progressBar.setValue(0) # 初始化发送进度条
self.send_textBrowser.append('开始发送邮件……') # 显示发送提示
# 实例化多线程对象
self.thread = mailsend_thread() # 创建发送线程
self.thread.send_a_data.connect(self.progress_display) # 弹出发送进度条
self.thread.txt_a_data.connect(self.txt_display) # 弹出发送提示
self.thread.start() # 开始线程
# 3.9.1 更新发送进度条
def progress_display(self,num):
self.send_progressBar.setValue(num)
# 3.9.2 更新发送进度提示
def txt_display(self,txt):
if int(txt) == len(receiver_list):
self.send_textBrowser.append('\n第' + txt + '个邮件发送完成,')
self.send_textBrowser.append('\n全部邮件发送完成!')
else:
self.send_textBrowser.append('\n第' + txt + '个邮件发送完成,')
# 程序运行函数
def mw_run():
app = QApplication(sys.argv)
myWin = a0_MyMainForm()
myWin.show()
sys.exit(app.exec_())
if __name__== '__main__':
mw_run()