【python】~实现工具软件:QQ邮件即时、定时发送
界面展示:
界面1:邮件设置
界面2:定时设置
界面3:发送日志
AI实现提示词:
发给豆包app:
把这个程序新增一个UI界面并带有如上功能,让我选择文件并可以设置定时间发送文件,请使用python代码帮我实现。把这个程序新增一个UI界面并带有如上功能,让我选择文件并可以设置定时间发送文件,请使用python代码帮我实现。
实现步骤:
1、新建一个txt文本文件,把如下代码复制进去,然后保存并修改文件后缀名为: .py结尾
(PS: 必须提前安装好python运行行环境)
import tkinter as tk
from tkinter import filedialog, ttk, messagebox
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.application import MIMEApplication
import time
import threading
import datetime
import os
from tkinter import fontclass EmailSenderApp:def __init__(self, root):self.root = rootself.root.title("邮件定时发送工具")self.root.geometry("700x600")self.root.minsize(600, 500)# 确保中文显示正常self.default_font = font.nametofont("TkDefaultFont")self.default_font.configure(family="SimHei", size=10)self.root.option_add("*Font", self.default_font)# 状态和进度 - 提前到界面创建之前初始化self.status_var = tk.StringVar(value="就绪")self.progress_var = tk.DoubleVar(value=0)# 邮件配置self.email_config = {'smtp_server': tk.StringVar(value='smtp.qq.com'),'smtp_port': tk.IntVar(value=465),'use_ssl': tk.BooleanVar(value=True),'sender_email': tk.StringVar(),'sender_password': tk.StringVar(),'recipient_email': tk.StringVar(),'subject': tk.StringVar(value='今日工作总结'),'body': tk.StringVar()}# 定时设置self.timer_config = {'send_now': tk.BooleanVar(value=True),'send_at': tk.StringVar(value=self._get_default_time()),'file_path': tk.StringVar()}# 创建界面self._create_widgets()def _get_default_time(self):# 默认设置为明天早上9点tomorrow = datetime.datetime.now() + datetime.timedelta(days=1)return tomorrow.strftime("%Y-%m-%d 09:00")def _create_widgets(self):# 创建标签页tab_control = ttk.Notebook(self.root)# 邮件设置标签页email_tab = ttk.Frame(tab_control)tab_control.add(email_tab, text="邮件设置")# 定时设置标签页timer_tab = ttk.Frame(tab_control)tab_control.add(timer_tab, text="定时设置")# 日志标签页log_tab = ttk.Frame(tab_control)tab_control.add(log_tab, text="发送日志")tab_control.pack(expand=1, fill="both")# === 邮件设置页面 ===# SMTP服务器设置smtp_frame = ttk.LabelFrame(email_tab, text="SMTP服务器设置")smtp_frame.pack(fill="x", padx=10, pady=5)ttk.Label(smtp_frame, text="SMTP服务器:").grid(row=0, column=0, sticky="w", padx=5, pady=5)ttk.Entry(smtp_frame, textvariable=self.email_config['smtp_server']).grid(row=0, column=1, sticky="ew", padx=5, pady=5)ttk.Label(smtp_frame, text="端口:").grid(row=0, column=2, sticky="w", padx=5, pady=5)ttk.Entry(smtp_frame, textvariable=self.email_config['smtp_port'], width=10).grid(row=0, column=3, sticky="w", padx=5, pady=5)ttk.Checkbutton(smtp_frame, text="使用SSL", variable=self.email_config['use_ssl']).grid(row=0, column=4, sticky="w", padx=5, pady=5)# 发件人设置sender_frame = ttk.LabelFrame(email_tab, text="发件人信息")sender_frame.pack(fill="x", padx=10, pady=5)ttk.Label(sender_frame, text="邮箱:").grid(row=0, column=0, sticky="w", padx=5, pady=5)ttk.Entry(sender_frame, textvariable=self.email_config['sender_email']).grid(row=0, column=1, sticky="ew", padx=5, pady=5)ttk.Label(sender_frame, text="授权码:").grid(row=1, column=0, sticky="w", padx=5, pady=5)ttk.Entry(sender_frame, textvariable=self.email_config['sender_password'], show="*").grid(row=1, column=1, sticky="ew", padx=5, pady=5)# 收件人设置recipient_frame = ttk.LabelFrame(email_tab, text="收件人信息")recipient_frame.pack(fill="x", padx=10, pady=5)ttk.Label(recipient_frame, text="收件人邮箱:").grid(row=0, column=0, sticky="w", padx=5, pady=5)ttk.Entry(recipient_frame, textvariable=self.email_config['recipient_email']).grid(row=0, column=1, sticky="ew", padx=5, pady=5)# 邮件内容设置content_frame = ttk.LabelFrame(email_tab, text="邮件内容")content_frame.pack(fill="both", expand=True, padx=10, pady=5)ttk.Label(content_frame, text="主题:").grid(row=0, column=0, sticky="w", padx=5, pady=5)ttk.Entry(content_frame, textvariable=self.email_config['subject']).grid(row=0, column=1, sticky="ew", padx=5, pady=5)ttk.Label(content_frame, text="正文:").grid(row=1, column=0, sticky="nw", padx=5, pady=5)self.body_text = tk.Text(content_frame, height=10, width=50)self.body_text.grid(row=1, column=1, sticky="nsew", padx=5, pady=5)# 配置列和行的权重,使文本区域可以扩展content_frame.columnconfigure(1, weight=1)content_frame.rowconfigure(1, weight=1)# === 定时设置页面 ===timer_frame = ttk.LabelFrame(timer_tab, text="发送选项")timer_frame.pack(fill="x", padx=10, pady=5)ttk.Radiobutton(timer_frame, text="立即发送", variable=self.timer_config['send_now'], value=True).grid(row=0, column=0, sticky="w", padx=5, pady=5)ttk.Radiobutton(timer_frame, text="定时发送", variable=self.timer_config['send_now'], value=False).grid(row=0, column=1, sticky="w", padx=5, pady=5)time_frame = ttk.LabelFrame(timer_tab, text="定时设置 (YYYY-MM-DD HH:MM)")time_frame.pack(fill="x", padx=10, pady=5)ttk.Entry(time_frame, textvariable=self.timer_config['send_at']).pack(fill="x", padx=5, pady=5)file_frame = ttk.LabelFrame(timer_tab, text="附件选择")file_frame.pack(fill="x", padx=10, pady=5)ttk.Entry(file_frame, textvariable=self.timer_config['file_path']).grid(row=0, column=0, sticky="ew", padx=5, pady=5)ttk.Button(file_frame, text="浏览文件", command=self._browse_file).grid(row=0, column=1, sticky="e", padx=5, pady=5)file_frame.columnconfigure(0, weight=1)# === 日志页面 ===log_frame = ttk.LabelFrame(log_tab, text="发送日志")log_frame.pack(fill="both", expand=True, padx=10, pady=5)self.log_text = tk.Text(log_frame, height=10, width=50)self.log_text.pack(fill="both", expand=True, padx=5, pady=5)self.log_text.config(state=tk.DISABLED)# === 底部状态栏和按钮 ===status_frame = ttk.Frame(self.root)status_frame.pack(fill="x", side="bottom", padx=10, pady=5)ttk.Label(status_frame, textvariable=self.status_var).pack(side="left")ttk.Progressbar(status_frame, variable=self.progress_var, length=200).pack(side="right")button_frame = ttk.Frame(self.root)button_frame.pack(fill="x", side="bottom", padx=10, pady=5)ttk.Button(button_frame, text="发送邮件", command=self._send_email).pack(side="right", padx=5)ttk.Button(button_frame, text="保存设置", command=self._save_settings).pack(side="right", padx=5)def _browse_file(self):filename = filedialog.askopenfilename(title="选择文件",filetypes=[("所有文件", "*.*"), ("文本文件", "*.txt"), ("Word文档", "*.docx")])if filename:self.timer_config['file_path'].set(filename)def _log(self, message):self.log_text.config(state=tk.NORMAL)self.log_text.insert(tk.END, f"{datetime.datetime.now().strftime('%H:%M:%S')} - {message}\n")self.log_text.see(tk.END)self.log_text.config(state=tk.DISABLED)def _save_settings(self):# 从文本框更新正文内容self.email_config['body'].set(self.body_text.get("1.0", tk.END).strip())try:with open('email_settings.ini', 'w', encoding='utf-8') as f:f.write(f"smtp_server={self.email_config['smtp_server'].get()}\n")f.write(f"smtp_port={self.email_config['smtp_port'].get()}\n")f.write(f"use_ssl={self.email_config['use_ssl'].get()}\n")f.write(f"sender_email={self.email_config['sender_email'].get()}\n")f.write(f"recipient_email={self.email_config['recipient_email'].get()}\n")f.write(f"subject={self.email_config['subject'].get()}\n")f.write(f"body={self.email_config['body'].get()}\n")f.write(f"send_at={self.timer_config['send_at'].get()}\n")f.write(f"file_path={self.timer_config['file_path'].get()}\n")self._log("设置已保存")messagebox.showinfo("成功", "设置已保存到 email_settings.ini")except Exception as e:self._log(f"保存设置失败: {str(e)}")messagebox.showerror("错误", f"保存设置失败: {str(e)}")def _load_settings(self):try:if os.path.exists('email_settings.ini'):with open('email_settings.ini', 'r', encoding='utf-8') as f:lines = f.readlines()settings = {}for line in lines:key, value = line.strip().split('=', 1)settings[key] = value# 恢复设置self.email_config['smtp_server'].set(settings.get('smtp_server', ''))self.email_config['smtp_port'].set(int(settings.get('smtp_port', 465)))self.email_config['use_ssl'].set(settings.get('use_ssl', 'True') == 'True')self.email_config['sender_email'].set(settings.get('sender_email', ''))self.email_config['recipient_email'].set(settings.get('recipient_email', ''))self.email_config['subject'].set(settings.get('subject', ''))self.email_config['body'].set(settings.get('body', ''))self.timer_config['send_at'].set(settings.get('send_at', self._get_default_time()))self.timer_config['file_path'].set(settings.get('file_path', ''))# 更新文本框内容self.body_text.delete("1.0", tk.END)self.body_text.insert(tk.END, self.email_config['body'].get())self._log("设置已加载")except Exception as e:self._log(f"加载设置失败: {str(e)}")def _send_email(self):# 从文本框更新正文内容self.email_config['body'].set(self.body_text.get("1.0", tk.END).strip())# 验证输入if not self.email_config['sender_email'].get():messagebox.showerror("错误", "请输入发件人邮箱")returnif not self.email_config['sender_password'].get():messagebox.showerror("错误", "请输入发件人授权码")returnif not self.email_config['recipient_email'].get():messagebox.showerror("错误", "请输入收件人邮箱")return# 如果选择定时发送,验证时间格式if not self.timer_config['send_now'].get():try:send_time = datetime.datetime.strptime(self.timer_config['send_at'].get(), "%Y-%m-%d %H:%M")if send_time < datetime.datetime.now():messagebox.showerror("错误", "发送时间不能早于当前时间")returnexcept ValueError:messagebox.showerror("错误", "时间格式不正确,请使用 YYYY-MM-DD HH:MM 格式")return# 更新状态self.status_var.set("准备发送...")self._log("开始处理邮件发送请求")# 在单独线程中执行发送任务threading.Thread(target=self._send_email_thread, daemon=True).start()def _send_email_thread(self):try:# 如果选择定时发送,等待到指定时间if not self.timer_config['send_now'].get():send_time = datetime.datetime.strptime(self.timer_config['send_at'].get(), "%Y-%m-%d %H:%M")wait_seconds = (send_time - datetime.datetime.now()).total_seconds()self._log(f"等待中,将于 {self.timer_config['send_at'].get()} 发送邮件")self.status_var.set(f"等待中,将于 {self.timer_config['send_at'].get()} 发送")# 分段等待,以便可以更新进度条while wait_seconds > 0:time.sleep(1)wait_seconds -= 1progress = 100 - (wait_seconds / (send_time - datetime.datetime.now()).total_seconds() * 100)self.progress_var.set(progress)self.status_var.set(f"等待中: {int(progress)}%")# 开始发送邮件self._log("读取今日小结文档中")self.progress_var.set(20)self.status_var.set("读取文档中...")# 准备邮件内容msg = MIMEMultipart()msg['From'] = self.email_config['sender_email'].get()msg['To'] = self.email_config['recipient_email'].get()msg['Subject'] = self.email_config['subject'].get()# 添加正文msg.attach(MIMEText(self.email_config['body'].get(), 'plain', 'utf-8'))# 添加附件file_path = self.timer_config['file_path'].get()if file_path and os.path.exists(file_path):with open(file_path, 'rb') as f:attachment = MIMEApplication(f.read(), _subtype=os.path.splitext(file_path)[1][1:])attachment.add_header('Content-Disposition', 'attachment', filename=os.path.basename(file_path))msg.attach(attachment)self._log(f"已添加附件: {os.path.basename(file_path)}")else:self._log("未选择附件")self._log("正在编写邮件正文")self.progress_var.set(50)self.status_var.set("编写邮件正文...")# 连接SMTP服务器并发送邮件self._log(f"正在连接到 SMTP 服务器: {self.email_config['smtp_server'].get()}")if self.email_config['use_ssl'].get():server = smtplib.SMTP_SSL(self.email_config['smtp_server'].get(), self.email_config['smtp_port'].get())else:server = smtplib.SMTP(self.email_config['smtp_server'].get(), self.email_config['smtp_port'].get())server.starttls() # 使用TLS加密self.progress_var.set(70)self.status_var.set("正在登录邮箱...")self._log(f"正在使用邮箱 {self.email_config['sender_email'].get()} 登录")server.login(self.email_config['sender_email'].get(), self.email_config['sender_password'].get())self.progress_var.set(80)self.status_var.set("正在发送邮件...")self._log(f"正在发送给: {self.email_config['recipient_email'].get()}")server.sendmail(self.email_config['sender_email'].get(),self.email_config['recipient_email'].get(),msg.as_string())server.quit()# 完成发送self.progress_var.set(100)self.status_var.set("邮件发送成功!")self._log("邮件发送成功!下班愉快!")# 提示用户self.root.after(0, lambda: messagebox.showinfo("成功", "邮件发送成功!"))except Exception as e:self.progress_var.set(0)self.status_var.set(f"发送失败: {str(e)}")self._log(f"发送失败: {str(e)}")self.root.after(0, lambda: messagebox.showerror("错误", f"发送失败: {str(e)}"))if __name__ == "__main__":root = tk.Tk()app = EmailSenderApp(root)# 尝试加载保存的设置app._load_settings()root.mainloop()
2、运行此python文件:
打开电脑上的powershell窗口,输入:python + 空格 + 此文件电脑存放路径,然后按一下回车:
如下:
运行成功!!!
运行成功后,我们去QQ邮箱官网:https://mail.qq.com/
登录上自己的邮箱之后,去获取【授权码】:
往下找到并点击【继续获取授权码】:
使用手机微信扫码发送信息之后,点击【我已发送】
之后,弹窗就可以获取到授权码了。复制粘贴到python程序界面中的【授权码】:
如下填写后。再点击【发送邮件】即可
功能介绍:
这是一个功能完整的邮件定时发送工具,具有以下特点:
- 美观易用的图形界面,采用标签页设计,分为邮件设置、定时设置和发送日志三个部分
- 完整的邮件配置选项,包括 SMTP 服务器设置、发件人和收件人信息、邮件主题和正文
- 灵活的定时发送功能,可以选择立即发送或指定未来的日期和时间发送
- 文件选择功能,支持添加附件
- 发送进度显示和日志记录,方便跟踪邮件发送状态
- 设置保存和加载功能,下次打开程序时可以恢复之前的配置
使用方法:
- 填写邮件服务器信息、发件人和收件人邮箱
- 输入邮件主题和正文
- 选择是否立即发送或定时发送
- 如果需要,选择要附加的文件
- 点击 “发送邮件” 按钮开始发送
注意:
- 程序会保存设置到 email_settings.ini 文件,下次启动时会自动加载
- 对于 QQ 邮箱等需要授权码的邮箱,需要先在邮箱设置中开启 SMTP 服务并获取授权码
- 程序会在日志标签页中记录所有操作和状态信息,方便排查问题