diff --git a/邮件批量发送脚本.py b/邮件批量发送.py similarity index 87% rename from 邮件批量发送脚本.py rename to 邮件批量发送.py index f722775..ec0b106 100644 --- a/邮件批量发送脚本.py +++ b/邮件批量发送.py @@ -12,6 +12,7 @@ from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.wait import WebDriverWait from selenium.webdriver.remote.webelement import WebElement +from pathlib import Path from datetime import datetime, timedelta from zoneinfo import ZoneInfo from nameparser import HumanName @@ -38,11 +39,6 @@ errors = 0 warnings = 0 greetings = [ - { - "locale": "**", - "default": "不使用问候语", - "registry": [] - }, { "locale": "en", "default": "Hello", @@ -189,7 +185,8 @@ def main(): while True: try: print('[信息] 请选择数据源') - dialog = wx.FileDialog(None, 'Open', wildcard='*.xlsx', style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + title = 'Open (%s)' % args.address + dialog = wx.FileDialog(None, title, wildcard='*.xlsx', style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) if dialog.ShowModal() == wx.ID_OK: filepath = dialog.GetPath() @@ -201,6 +198,9 @@ def main(): workbook = pandas.read_excel(filepath) data = workbook.where(pandas.notnull(workbook), None).to_dict(orient='list') recipients = data.get(args.column_address, []) + + parts = Path(filepath).stem.split('.', 2) + suffix = parts[1].lower() if len(parts) > 1 else None except Exception as e: print(f'[警告] 读取数据表失败:{e}') continue @@ -219,42 +219,38 @@ def main(): # 打开草稿箱 click("li[data-id='default0/Brouillons']", condition=EC.presence_of_element_located) click("button[data-id='default0/Brouillons']", condition=EC.presence_of_element_located) - # 打开邮件 click("ul[aria-label='List view'] li[data-index='0']", condition=EC.presence_of_element_located) - - subject = locate("h1.subject") - print(f'[信息] 已读取邮件:{subject.text}') - - sender = locate("header div.from") - print(f'[信息] 指定发件人:{sender.text[6:].replace('\n', ' ')}') except Exception as e: - print(f'[!!!!] 读取邮件时发生了错误:{e}') - return 5 + print(f'[警告] 打开草稿邮件时发生了错误:{e}') + print(f'[信息] 提示:请手动选择邮件') + pass rate = 60 / (args.interval + 3) length = list.count(sents, None) - command = None timezone = ZoneInfo(args.timezone) if args.timezone else None print(f'[信息] 当前发送速率 {round(rate, 2)} 封/分钟') if rate > 8.33: print('[警告] 当前发送速率已超出限制 8.33 封/分钟') print(f'[信息] 预计使用时间 {timedelta(minutes=length / rate)}') print(f'[信息] 当前时区:{args.timezone or '无'}') - print(f'[信息] 已读取可用问候语 {len(greetings)} 条:', end='\n\n') - for index, item in enumerate(greetings): - print(f'\t[{index}] {item.get('locale')}', end=' ') - print('- %s' % (', '.join(filter(None, item.get('registry'))) or item.get('default'))) + entries = list(filter(lambda it: it.locale == suffix, greetings)) + locale = dict(entries[0]) if len(entries) > 0 else None + print(f'[信息] 当前语言:{str(suffix).upper() if locale else '无'}', end='\n\n') - while command is None: - match input('\n[????] 请选择 (留空取消操作): ').strip(): - case keys if not keys: - print('[信息] 操作取消') - return 0 - case keys if keys.isdigit(): - number = int(keys) - if number < len(greetings): command = number + if input('[????] 确认操作:(y) 确定 / (N) 取消') not in ['Y', 'y']: + print('[信息] 操作取消') + continue + + subject = locate("h1.subject").text.strip() + sender = locate("header div.from").text[6:].replace('\n', ' ') + print(f'[信息] 已读取邮件:{subject}') + print(f'[信息] 指定发件人:{sender}') + + if sender.lower().find(f'<{str(args.address).lower()}>'): + print(f'[警告] 检测到发件人与设定不一致') + print(f'[信息] 提示:请检查邮件是否正确') global date date = datetime.now() @@ -296,20 +292,27 @@ def main(): print('[信息] 正在发送:%s (%.2f %%)' % (recipient, current / limit * 100)) click("button[aria-label='Edit copy']") + if (target := locate("h1.subject").text.strip()) != subject: + print(f'[警告] 邮件主题与设定不一致:{target}') + if input('[????] 是否继续:(y) / (N): ') in ['Y', 'y']: + subject = target + print(f'[信息] 已更新邮件主题设定') + else: + raise Exception('操作取消') + ready(driver, lambda x: x.find_element(By.CSS_SELECTOR, ".io-ox-busy")) locate("div.io-ox-mail-compose-window iframe", condition=EC.frame_to_be_available_and_switch_to_it) - if command > 0 and (entry := greetings[command]): + if locale and (registry := locale.get('registry')): match datetime.now(timezone).hour if timezone else -1: - case hour if 6 <= hour < 12: registry = entry.get('registry')[0] - case hour if 12 <= hour < 18: registry = entry.get('registry')[1] - case hour if 18 <= hour < 21: registry = entry.get('registry')[2] - case _: registry = None + case hour if 6 <= hour < 12: hello = registry[0] + case hour if 12 <= hour < 18: hello = registry[1] + case hour if 18 <= hour < 21: hello = registry[2] + case _: hello = locale.get('default') iframe = driver.switch_to.active_element action = ActionChains(driver) clean = False - hello = registry or entry.get('default') if name is not None and (name := str(name).strip()) and not contains_non_latin_alphabet(name): parts = HumanName(name)