qq邮箱群发程序

news2025/4/23 6:38:55

1.界面设计

1.1 环境配置

在外部工具位置进行配置

 1.2 UI界面设计

1.2.1 进入QT的UI设计界面

在pycharm中按顺序点击,进入UI编辑界面:

 

 点击第三步后进入QT的UI设计界面,通过点击按钮进行界面设计,设计后进行保存到当前Pycharm项目的文件路径之下。

 1.2.2  .ui文件转换为.py文件

 1.2.3 运行主程序

通过以下代码对ui转换的py文件进行调用:

# -*- coding: utf-8 -*-
import smtplib
import ssl
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr

import sys
from PyQt5.QtWidgets import QApplication,QMainWindow
from EmailSenderUI import Ui_Form  # 加载布局


# 定义主窗口类,继承自QMainWindow和自动生成的UI类Ui_Form
class Mywindow(QMainWindow, Ui_Form):
    def __init__(self):   # 调用父类QMainWindow的初始化方法
        super().__init__()   # 初始化UI界面(由Qt Designer生成的setupUi方法)
        self.setupUi(self)  # 可在此处添加额外的初始化代码(如信号槽连接等)


if __name__ == '__main__':
    # 当直接运行本脚本时执行以下代码(而非被其他模块导入时)
    app = QApplication(sys.argv)   # 创建Qt应用程序实例,sys.argv用于传递命令行参数
    ui = Mywindow()    # 实例化主窗口对象
    ui.show()    # 显示主窗口
    sys.exit(app.exec_())    # 进入Qt主事件循环,等待用户操作。sys.exit()确保程序能正确退出并返回状态码

 运行结果如下图所示:

 注:通过上面的步骤就可以得到一个设计的初始化界面,其具体功能还未实现。

1.3 功能实现——槽函数

UI界面设计的各个控件的名称通过槽函数与相应的功能函数进行连接

2. 完整代码

程序共包含4个文件:main.py,open_show_file.py,发送邮件函数.py,EmailSenderUI.py

2.1 open_show_file.py

import sys
import pandas as pd
from PyQt5.QtWidgets import QApplication,QMainWindow

from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QLabel, QFileDialog, QTextEdit,QTableWidget, QTableWidgetItem, QWidget,QStackedWidget
from sklearn.ensemble import RandomForestRegressor
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error
from sklearn.metrics import *
import numpy as np

import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error

import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
## 设置字符集,防止中文乱码
import matplotlib as mpl    #画图工具
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False



##############################################################################  page1_1_1  ####################################################################################
# 打开文件,选择路径并显示
def open_select_file_def(parent,page1_1_1_via_show):
    options = QFileDialog.Options()  # 创建一个文件对话框选项对象。
    options |= QFileDialog.ReadOnly  # 将选项设置为只读模式,这表示用户只能选择已经存在的文件而不能创建新文件。
    file_path, _ = QFileDialog.getOpenFileName(parent, "Select File", "", "Excel Files (*.xlsx *.xls)", options=options)
    # 调用文件对话框的getOpenFileName方法,该方法会打开文件选择对话框 ;参数:
    # self:表示当前窗口或部件。
    # "Select File":对话框标题。
    # "":默认路径,此处为空字符串表示打开对话框时不指定默认路径。
    # "Excel Files (*.xlsx)":文件类型过滤器,限制用户只能选择Excel文件。
    # options = options:传递前面创建的选项对象。
    if file_path:  # 检查用户是否选择了文件路径,如果选择了文件,则进入下面的代码块。
        selected_file_path = file_path  # 将选择的文件路径保存到对象的 selected_file_path 属性中,以便后续使用。
        page1_1_1_via_show.setText(f"文件路径: {file_path}")  # 将界面上的文件标签的文本设置为显示所选文件的路径。
        page1_1_1_data = pd.read_excel(file_path)  # 使用 pandas 读取 Excel 文件数据
        return page1_1_1_data
    else:
        pass

# 将 Excel 数据填充到表格中。
def show_file_data_def(table_widget, data):
    table_widget.setColumnCount(data.shape[1])  # 将表格小部件的列数设置为data DataFrame的列数,以便为每个数据行创建一个对应的表格列
    table_widget.setRowCount(data.shape[0])  # 将表格小部件的行数设置为data DataFrame的行数,以便为每个数据行创建一个对应的表格行
    table_widget.setHorizontalHeaderLabels(data.columns)  # 将DataFrame的列名设置为表格小部件的水平表头标签
    for row_idx in range(data.shape[0]):
        for col_idx in range(data.shape[1]):
            item = QTableWidgetItem(str(data.iat[row_idx, col_idx]))  # 从DataFrame中获取特定行和列索引位置处的单元格数据,并使用str()函数将其转换为字符串。然后,通过QTableWidgetItem()将该字符串添加到表格小部件的特定单元格中。
            table_widget.setItem(row_idx, col_idx, item)  # 将 QTableWidgetItem 对象放置到表格小部件的特定单元格中,从而将数据显示在表格中
##############################################################################  page1_1_1  ####################################################################################

2.2 发送邮件函数.py:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import os

import pandas as pd



def send_email(
        from_addr,
        password,
        to_addrs,
        subject,
        body,
        attachments=None,
        smtp_server="smtp.qq.com",
        smtp_port=587
):
    msg = MIMEMultipart()
    msg["From"] = from_addr
    msg["To"] = ",".join(to_addrs)
    msg["Subject"] = subject
    msg.attach(MIMEText(body, "plain", "utf-8"))
    # 添加附件
    if attachments:
        for file_path in attachments:
            part = MIMEBase("application", "octet-stream")
            with open(file_path, "rb") as f:
                part.set_payload(f.read())
            encoders.encode_base64(part)
            part.add_header(
                "Content-Disposition",
                f"attachment; filename={os.path.basename(file_path)}",
            )
            msg.attach(part)


    server = smtplib.SMTP(smtp_server, smtp_port)
    server.starttls()
    try:
        server.login(from_addr, password)
    except Exception as e:
        return "登录失败","请输入正确的邮箱账号和授权码"
    try:
        server.sendmail(
            from_addr,
            to_addrs,
            msg.as_string()
        )
        # print(f"邮件 {to_addrs} 发送成功!")
        return f"{to_addrs} ","成功"
    except Exception as e:
        # print(f"发送失败:{str(e)}")
        # print(f"邮件 {to_addrs} 发送失败!")
        return f"{to_addrs} ","失败"
    finally:
        server.quit()

2.3 main.py:

# -*- coding: utf-8 -*-
import smtplib
import ssl
from email.mime.text import MIMEText
from email.header import Header
from email.utils import formataddr
import pandas as pd
import sys
from PyQt5.QtWidgets import QApplication,QMainWindow
from EmailSenderUI import Ui_Form  # 加载布局
from 软件功能函数.open_show_file import open_select_file_def,show_file_data_def
from 软件功能函数.发送邮件函数 import send_email

from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QPushButton, QLabel, QFileDialog, QTextEdit, \
    QTableWidget, QTableWidgetItem, QWidget,QStackedWidget
from sklearn.ensemble import RandomForestRegressor
from PyQt5.QtGui import QPixmap, QImage
from PyQt5.QtCore import Qt

from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import mean_squared_error, mean_absolute_error
from sklearn.metrics import *
import numpy as np

import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error

import matplotlib.pyplot as plt
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
## 设置字符集,防止中文乱码
import matplotlib as mpl    #画图工具

import re

mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False


# 定义主窗口类,继承自QMainWindow和自动生成的UI类Ui_Form
class Mywindow(QMainWindow, Ui_Form):
    def __init__(self):   # 调用父类QMainWindow的初始化方法
        super().__init__()   # 初始化UI界面(由Qt Designer生成的setupUi方法)
        self.setupUi(self)  # 可在此处添加额外的初始化代码(如信号槽连接等)

        # 通过槽函数 将控件名称与功能实现函数连接
        self.pushButton_open.clicked.connect(self.button_open_file)  # 连接 pushButton_open 钮到 button_open_file 函数方法
        self.pushButton_confirm.clicked.connect(self.email_information)
        self.pushButton_send.clicked.connect(self.send_information)


# 函数功能实现
    # 打开文件夹,获取接收方账号等信息
    def button_open_file(self):
        self.data_frame = open_select_file_def(self, self.lineEdit_via_show)
        show_file_data_def(self.email_show, self.data_frame)

# 确实邮件发送方信息
    def email_information(self):
        try:
            self.EmailAccount_text = self.sender_email.text().strip()  # 获取文本内容,并去除首位空格
            self.EmailCode_text = self.sender_email_code.text().strip() # 获取文本内容
            if not self.EmailAccount_text or not self.EmailCode_text:
                self.label_information.setText("请确认发送方账号和验证码的输入信息")
                return
            # 邮箱格式验证(正则表达式)
            if not re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', self.EmailAccount_text):
                self.label_information.setText("发送方的邮箱格式不正确")
                return
            else:
                self.label_information.setText("发送方账号和验证码输入成功")
                # 此处可添加后续逻辑(如调用发送邮件函数)
        except Exception as e:
            print(f"信息读取错误: {str(e)}")  # 明确打印错误类型

# 发送邮件
    def send_information(self):
        sender_account = self.EmailAccount_text
        sender_password = self.EmailCode_text
        results = []
        for index, row in self.data_frame.iterrows():
            # 提取当前行数据
            to_email = row.iloc[0]
            subject = row.iloc[1]
            body = row.iloc[2]
            result = send_email(from_addr=sender_account, password=sender_password, to_addrs=to_email, subject=subject,body=body)
            results.append(result)

        # 设置表格的行数和列数
        self.email_send_information.setRowCount(len(results))
        self.email_send_information.setColumnCount(2)  # 假设有三个字段:Name, Age, City
        # 设置表头
        self.email_send_information.setHorizontalHeaderLabels(["邮箱账号","邮件发送状态"])
        # 填充数据
        for row, row_data in enumerate(results):
            self.email_send_information.setItem(row, 0, QTableWidgetItem(str(row_data[0])))
            self.email_send_information.setItem(row, 1, QTableWidgetItem(str(row_data[1])))

if __name__ == '__main__':
    # 当直接运行本脚本时执行以下代码(而非被其他模块导入时)
    app = QApplication(sys.argv)   # 创建Qt应用程序实例,sys.argv用于传递命令行参数
    ui = Mywindow()    # 实例化主窗口对象
    ui.show()    # 显示主窗口
    sys.exit(app.exec_())    # 进入Qt主事件循环,等待用户操作。sys.exit()确保程序能正确退出并返回状态码

2.4 EmailSenderUI.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'EmailSenderUI.ui'
#
# Created by: PyQt5 UI code generator 5.12
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Form(object):
    def setupUi(self, Form):
        Form.setObjectName("Form")
        Form.resize(778, 827)
        self.pushButton_open = QtWidgets.QPushButton(Form)
        self.pushButton_open.setGeometry(QtCore.QRect(60, 30, 101, 41))
        self.pushButton_open.setObjectName("pushButton_open")
        self.lineEdit_via_show = QtWidgets.QLineEdit(Form)
        self.lineEdit_via_show.setGeometry(QtCore.QRect(190, 30, 471, 41))
        self.lineEdit_via_show.setObjectName("lineEdit_via_show")
        self.sender_email = QtWidgets.QLineEdit(Form)
        self.sender_email.setGeometry(QtCore.QRect(70, 310, 461, 41))
        self.sender_email.setText("")
        self.sender_email.setObjectName("sender_email")
        self.pushButton_confirm = QtWidgets.QPushButton(Form)
        self.pushButton_confirm.setGeometry(QtCore.QRect(560, 320, 91, 91))
        self.pushButton_confirm.setObjectName("pushButton_confirm")
        self.sender_email_code = QtWidgets.QLineEdit(Form)
        self.sender_email_code.setGeometry(QtCore.QRect(70, 390, 461, 41))
        self.sender_email_code.setText("")
        self.sender_email_code.setObjectName("sender_email_code")
        self.label = QtWidgets.QLabel(Form)
        self.label.setGeometry(QtCore.QRect(80, 280, 131, 31))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(Form)
        self.label_2.setGeometry(QtCore.QRect(80, 360, 191, 31))
        self.label_2.setObjectName("label_2")
        self.email_show = QtWidgets.QTableWidget(Form)
        self.email_show.setGeometry(QtCore.QRect(60, 80, 601, 192))
        self.email_show.setObjectName("email_show")
        self.email_show.setColumnCount(0)
        self.email_show.setRowCount(0)
        self.email_send_information = QtWidgets.QTableWidget(Form)
        self.email_send_information.setGeometry(QtCore.QRect(60, 570, 591, 171))
        self.email_send_information.setObjectName("email_send_information")
        self.email_send_information.setColumnCount(0)
        self.email_send_information.setRowCount(0)
        self.pushButton_send = QtWidgets.QPushButton(Form)
        self.pushButton_send.setGeometry(QtCore.QRect(60, 520, 591, 41))
        self.pushButton_send.setObjectName("pushButton_send")
        self.label_information = QtWidgets.QLabel(Form)
        self.label_information.setGeometry(QtCore.QRect(80, 460, 571, 41))
        self.label_information.setObjectName("label_information")

        self.retranslateUi(Form)
        QtCore.QMetaObject.connectSlotsByName(Form)

    def retranslateUi(self, Form):
        _translate = QtCore.QCoreApplication.translate
        Form.setWindowTitle(_translate("Form", "Form"))
        self.pushButton_open.setText(_translate("Form", "打开"))
        self.pushButton_confirm.setText(_translate("Form", "确认"))
        self.label.setText(_translate("Form", "发送方的邮箱账号:"))
        self.label_2.setText(_translate("Form", "发送方的邮箱账号的授权码:"))
        self.pushButton_send.setText(_translate("Form", "发送"))
        self.label_information.setText(_translate("Form", "信息:"))


2.5 文件目录结构

 

2.6 程序运行界面

获取邮箱授权码_qq邮箱授权码如何获取-CSDN博客文章浏览阅读1.6k次。登录QQ邮箱:依次点击:设置--账号。_qq邮箱授权码如何获取 https://blog.csdn.net/javin4715/article/details/140911566?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522b863bb97086e7c2892e63c5833317f87%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=b863bb97086e7c2892e63c5833317f87&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_click~default-1-140911566-null-null.142^v102^pc_search_result_base7&utm_term=qq%E9%82%AE%E7%AE%B1%E6%8E%88%E6%9D%83%E7%A0%81&spm=1018.2226.3001.4187

 3. 代码打包成APP

 使用下面代码在终端进行打包:


pyinstaller -F -w app.py -n xxx # 其中app.py为你的.py代码名字; xxx 为打包时设置的软件名字
pyinstaller -F -w main.py -n EmailQQ

其中:打包时会自动去添加需要的代码,因此app.py为主函数代码。如下图所示:

 当生成完成后,将会在项目的文件路径下看到多了3个文件build、 dist 、app.spec,其中在dist目录下看到有一个 EmailQQ.exe 文件,这就是使用 PyInstaller 工具生成的 EXE 程序。 


打包方法介绍https://blog.csdn.net/qq_68639191/article/details/136215464?spm=1011.2415.3001.5331

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2331876.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

K8S学习之基础七十九:关闭istio功能

关闭istio功能 kubectl get ns --show-labels kubectl label ns default istio-injection-有istio-injectionenabled的命名空间,pod都会开启istio功能 反之,如果要开启istio,在对应命名空间打上该标签即可

上门预约洗鞋店小程序都具备哪些功能?

现在大家对洗鞋子的清洗条件越来越高,在家里不想去,那就要拿去洗鞋店去洗。如果有的客户没时间去洗鞋店,这个时候,有个洗鞋店小程序就可以进行上门取件,帮助没时间的客户去取需要清洗的鞋子,这样岂不是既帮…

蓝桥杯——走迷宫(Java-BFS)

这是一个经典的BFS算法 1. BFS算法保证最短路径 核心机制:广度优先搜索按层遍历所有可能的路径,首次到达终点的路径长度即为最短步数。这是BFS的核心优势。队列的作用:通过队列按先进先出的顺序处理节点,确保每一步探索的都是当…

下载firefox.tar.xz后如何将其加入到Gnome启动器

起因:近期(2025-04-07)发现firefox公布了130.0 版本,可以对pdf文档进行签名了,想试一下,所以卸载了我的Debian12上的firefox-esr,直接下载了新版本的tar.xz 包。 经过一番摸索,实现了将其加入Gn…

加密≠安全:文件夹密码遗忘背后的数据丢失风险与应对

在数字化时代,保护个人隐私和数据安全变得尤为重要。许多人选择对重要文件夹进行加密,以防止未经授权的访问。然而,一个常见且令人头疼的问题也随之而来——文件夹加密密码遗忘。当你突然发现自己无法访问那些加密的文件夹时,那种…

【开源宝藏】30天学会CSS - DAY12 第十二课 从左向右填充的文字标题动画

用伪元素搞定文字填充动效:一行 JS 不写,效果炸裂 你是否曾经在设计页面标题时,觉得纯文字太寡淡?或者想做一个有动感的文字特效,但又不想引入 JS 甚至 SVG? 在这篇文章中,我们将通过 一段不到…

nginx或tengine服务器,配置HTTPS下使用WebSocket的线上环境实践!

问题描述: HTTPS 下发起WS连接,连接失败,Chrom 浏览器报错。 socket.js:19 Mixed Content: The page at https://app.XXX.com was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint ws://172.16.10.80:903…

【Oracle篇】跨字符集迁移:基于数据泵的ZHS16GBK转AL32UTF8全流程迁移

💫《博主主页》:奈斯DB-CSDN博客 🔥《擅长领域》:擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控;并对SQLserver、NoSQL(MongoDB)有了解 💖如果觉得文章对你有所帮…

西门子S7-1200PLC 工艺指令PID_Temp进行控温

1.硬件需求: 西门子PLC:CPU 1215C DC/DC/DC PLC模块:SM 1231 TC模块 个人电脑:已安装TIA Portal V17软件 加热套:带加热电源线以及K型热电偶插头 固态继电器:恩爵 RT-SSK4A2032-08S-F 其他&#xff1…

vant4+vue3上传一个pdf文件并实现pdf的预览。使用插件pdf.js

注意下载的插件的版本"pdfjs-dist": "^2.2.228", npm i pdfjs-dist2.2.228 然后封装一个pdf的遮罩。因为pdf文件有多页,所以我用了swiper轮播的形式展示。因为用到移动端,手动滑动页面这样比点下一页下一页的方便多了。 直接贴代码…

2025 数字中国创新大赛数字安全赛道数据安全产业积分争夺赛初赛-东部赛区WriteUp

2025 数字中国创新大赛数字安全赛道数据安全产业积分争夺赛初赛-东部赛区WriteUp 数据安全:ez_upload(60分): 模型安全:数据分析:溯源与取证:1-1:1-2: 数据社工:2-2:2-3:2-4: 数据跨境&#xff…

2025 年网络安全终极指南

我们生活在一个科技已成为日常生活不可分割的一部分的时代。对数字世界的依赖性日益增强的也带来了更大的网络风险。 网络安全并不是IT专家的专属特权,而是所有用户的共同责任。通过简单的行动,我们可以保护我们的数据、隐私和财务,降低成为…

1.6-抓包技术(Burp Suite\Yakit抓包\Web、APP、小程序)

1.6-抓包技术(Burp Suite\Yakit抓包\Web、APP、小程序) 如果要使用抓包软件,基本上第一步都是要安装证书的。原因如下: 客户端(浏览器或应用)会检测到证书不受信任,并弹出 证书错误&#xff0…

图解力扣回溯及剪枝问题的模板应用

文章目录 选哪个的问题17. 电话号码的字母组合题目描述解题代码图解复杂度 选不选的问题78. 子集题目描述解题代码图解复杂度 两相转化77. 组合题目描述解题代码法一:按选哪个的思路法二:按选不选的思路 图解选哪个:选不选 复杂度 选哪个的问…

Elasticsearch 8.X 如何利用嵌入向量提升搜索能力?

众所周知,Elasticsearch 是一个非常流行的搜索引擎,因为它速度快、扩展性强,尤其擅长全文搜索。 近两年,向量嵌入(Vector Embedding)技术的引入,让 Elasticsearch 在处理高级搜索场景时变得更强…

MySQL体系架构(一)

1.1.MySQL的分支与变种 MySQL变种有好几个,主要有三个久经考验的主流变种:Percona Server,MariaDB和 Drizzle。它们都有活跃的用户社区和一些商业支持,均由独立的服务供应商支持。同时还有几个优秀的开源关系数据库,值得我们了解一下。 1.1.1.Drizzle Drizzle是真正的M…

深度强化学习基础 0:通用学习方法

过去自己学习深度强化学习的痛点: 只能看到各种术语、数学公式勉强看懂,没有建立清晰且准确关联 多变量交互关系浮于表面,有时候连环境、代理控制的变量都混淆 模型种类繁多,概念繁杂难整合、对比或复用,无框架分析所…

虚幻5的C++调试踩坑

本地调试VS附加调试 踩坑1 预编译版本的UE5没有符号文件,无法调试源码 官方代码调试所需要的符号文件bdp需要下载导入。我安装的5.5.4是预编译版本,并非ue5源码。所以不含bdp文件。需要调试官方代码则需要通过EPIC中下载安装。右键UE版本,打…

通信协议详解(十):PSI5 —— 汽车安全传感器的“抗干扰狙击手”

一、PSI5是什么? 一句话秒懂 PSI5就像传感器界的“防弹信使”:在汽车安全系统(如气囊)中,用两根线同时完成供电数据传输,即便车祸时线路受损,仍能确保关键信号准确送达! 基础概念…

从零开始学Python游戏编程18-函数3

《从零开始学Python游戏编程17-函数2》中,通过代码重构的方式将游戏的主要代码写入到自定义函数runGame()中。对于runGame()中的代码,可以继续对其进行重构,以达到简化代码结构的目的。 1 自定义函数askPlayer() 1.1 函数作用 自定义函数a…