diff --git a/邮件批量发送.py b/邮件批量发送.py index 564ddbe..39dc8cd 100644 --- a/邮件批量发送.py +++ b/邮件批量发送.py @@ -4,14 +4,17 @@ import pandas import time import wx -from selenium import webdriver from selenium.common.exceptions import StaleElementReferenceException, TimeoutException +from selenium.webdriver import Chrome, ChromeOptions from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By +from selenium.webdriver.common.keys import Keys from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.remote.webelement import WebElement +from selenium.webdriver.remote.webdriver import WebDriver +from enum import Enum from pathlib import Path from datetime import datetime, timedelta from zoneinfo import ZoneInfo @@ -71,20 +74,7 @@ greetings = [ } ] -def main(): - try: - print('[信息] 程序初始化中...') - app = wx.App(None) - - print('[信息] 正在启动 Chrome 自动化实例') - opts = webdriver.ChromeOptions() - opts.add_experimental_option("excludeSwitches", ["enable-logging"]) - driver = webdriver.Chrome(opts) - driver.set_page_load_timeout(args.timeout) - except Exception as e: - print(f'[!!!!] 初始化时发生了错误:{e}') - return 1 - +def main(driver: WebDriver): def locate(selector, condition=EC.presence_of_element_located, parent=driver) -> WebElement: for attempt in range(args.retry): try: @@ -122,10 +112,6 @@ def main(): except TimeoutException: continue except: break - def keyin(element: WebElement, value): - try: element.send_keys(value) - except: driver.execute_script(f"arguments[0].value = arguments[1];", element, value) - def ready(driver, predicate): try: wait = WebDriverWait(driver, timeout=args.timeout) @@ -247,7 +233,7 @@ def main(): continue subject = locate("h1.subject").text.strip() - sender = locate("header div.from").text[6:].replace('\n', ' ').strip() + sender = locate("header div.from").text[6:].replace('\n', ' ').strip().lstrip('<').rstrip('>') print(f'[信息] 已读取邮件:{subject}') print(f'[信息] 指定发件人:{sender}') @@ -255,14 +241,22 @@ def main(): print(f'[警告] 检测到发件人与设定不一致') print(f'[信息] 提示:请检查邮件是否正确') + class Status(Enum): + ACTIVE = 0 + INACTIVE = 1 + TERMINATED = 3 + + def isalive(self): return self != Status.TERMINATED + def isactive(self): return self == Status.ACTIVE + global date date = datetime.now() index = 0 - active = True + status = Status.ACTIVE occurrences = {} - while active and index < limit: + while status.isactive() and index < limit: global warnings global errors global sent @@ -288,7 +282,7 @@ def main(): warnings += 1 continue - while active: + while status.isactive(): try: clean = True attempt += 1 @@ -337,12 +331,12 @@ def main(): # 填入收件人 click(wrapper) - keyin(to, recipient) + to.send_keys(recipient + Keys.ENTER) if to.get_attribute('value') != recipient: - print(f'[警告] ({attempt}) 检测到收件人地址不正确,正在重试...') + print(f'[警告] ({attempt}): 检测到收件人地址不正确,正在重试...') elif not clean: - print(f'[警告] ({attempt}) 检测到邮件内容不正确,正在重试...') + print(f'[警告] ({attempt}): 检测到邮件内容不正确,正在重试...') else: # 发送邮件 click("div.io-ox-mail-compose-window button[data-action='send']") @@ -381,15 +375,15 @@ def main(): break except KeyboardInterrupt: print('[信息] 程序中断') - active = False + status = Status.TERMINATED break except Exception as e: - print(f'[警告] 发生错误:{e}') + print(f'[警告] ({attempt}): 发生错误:{e}') key = input('[????] 重试 (r) / 跳过 (s) / 取消 (C): ') if key in ['R', 'r']: continue elif key in ['S', 's']: break - else: active = False + else: status = Status.INACTIVE progress = index / limit * 100 print('[信息] 当前进度:%.2f %%' % progress) @@ -401,13 +395,29 @@ def main(): except Exception as e: print(f'[警告] 写入文件时发生了错误:{e}') - if active and input('[????] 继续运行 (c) / 退出程序 (W): ') in ['C', 'c']: continue + if status.isalive() and input('[????] 继续运行 (c) / 退出程序 (W): ') in ['C', 'c']: continue else: break return 0 -try: status = main() -except KeyboardInterrupt: status = 145 +try: + print('[信息] 程序初始化中...') + app = wx.App(None) + + print('[信息] 正在启动 Chrome 自动化实例') + opts = ChromeOptions() + opts.add_experimental_option("excludeSwitches", ["enable-logging"]) + driver = Chrome(opts) + driver.set_page_load_timeout(args.timeout) + status = main(driver) +except KeyboardInterrupt: + print('[信息] 程序中断') + status = 145 +except Exception as e: + print(f'[!!!!] 致命错误:{e}') + status = 1 +finally: + driver.quit() print(f'[信息] 已发送 {sent} 封;发送失败 {errors} 封;跳过重复项 {warnings} 个') print(f'[信息] 总耗时 {str(datetime.now() - date)}')