]> 小龙服务器 Git - 微信监控/commitdiff
第6封链接邮件+检测重发+窗口检测 v3.2
author小龙 <xl@szjxzxh.cn>
Thu, 16 Jul 2026 03:59:42 +0000 (11:59 +0800)
committer小龙 <xl@szjxzxh.cn>
Thu, 16 Jul 2026 03:59:42 +0000 (11:59 +0800)
wechat_auto_login.py

index fb593261acbb47cc0d41b9da772f6438e75280e9..92c00a513f73849ebb34c0d80ae104d7410bd0bd 100644 (file)
@@ -201,6 +201,37 @@ try:
             log.error("邮件发送失败: %s", e)
 
 
+    def send_resend_link_email():
+        """发送重发链接邮件(不含二维码,仅文字+链接)"""
+        if not EMAIL_ENABLED or not EMAIL_ACCOUNT:
+            log.warning("邮件未启用或账号未配置,跳过重发邮件")
+            return
+        try:
+            from email.mime.text import MIMEText
+            msg = MIMEText(
+                "微信登录二维码提醒已全部发送完毕,如仍需登录请点击以下链接申请重新发送:\n\n"
+                "https://szjxzxh.cn/wechat-resend.html\n\n"
+                "(点击后监控程序将重新开始发送二维码通知)",
+                "plain", "utf-8"
+            )
+            from email.utils import formataddr
+            msg["From"] = formataddr(("微信助手", EMAIL_ACCOUNT))
+            msg["To"] = EMAIL_TO
+            msg["Subject"] = "微信登录二维码已过期 - 申请重发"
+
+            if USE_SSL:
+                s = smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT, timeout=10)
+            else:
+                s = smtplib.SMTP(SMTP_SERVER, SMTP_PORT, timeout=10)
+                s.starttls()
+            s.login(EMAIL_ACCOUNT, EMAIL_PASSWORD)
+            s.send_message(msg)
+            s.quit()
+            log.info("重发链接邮件已发送至 %s", EMAIL_TO)
+        except Exception as e:
+            log.error("重发链接邮件发送失败: %s", e)
+
+
     def _find_wechat_windows():
         """找到标题严格等于'微信'的可见窗口列表(排除包含'微信'的其他窗口)"""
         return [w for w in gw.getAllWindows() if w.title == "微信"]
@@ -341,6 +372,7 @@ try:
             self.qr_sent_count = 0
             self._last_login_hash = None
             self._user_resized = False
+            self._resend_link_sent = False
 
             self._setup_ui()
 
@@ -481,6 +513,7 @@ try:
                 self.last_md5 = None
                 self.qr_sent_count = 0
                 self._last_login_hash = None
+                self._resend_link_sent = False
                 log.info("监控已停用")
 
         # ── status ──
@@ -672,11 +705,15 @@ try:
                 self._set_status("微信未运行,启动中...")
                 return  # _do_detect 会在下一轮自动启动微信
 
-            # ② 检查邮件是否已发满(含重发次数)
+            # ② 检查邮件已发满后的处理
             if self.hash_mode_emails_sent >= MAX_EMAILS:
-                # 已发满,进入等待重发模式
-                self._check_resend_flag()
-                return
+                if not self._resend_link_sent:
+                    # 还没发第6封链接邮件,继续监测窗口
+                    pass  # 不走下面,会继续执行到窗口尺寸检查
+                else:
+                    # 第6封已发,进入等待重发模式
+                    self._check_resend_flag()
+                    return
 
             # ③ 查窗口尺寸
             wechat_windows = _find_wechat_windows()
@@ -728,37 +765,69 @@ try:
             # 仍然是登录窗口→发通知
             time.sleep(2)
             img2 = _capture_center()
-            qr_path = os.path.join(tempfile.gettempdir(), f"wechat_qr_{int(time.time())}.png")
-            img2.save(qr_path, "PNG")
 
-            self.hash_mode_emails_sent += 1
+            if self.hash_mode_emails_sent >= MAX_EMAILS:
+                if not self._resend_link_sent:
+                    # 第5封已发完,现在二维码过期了,发第6封链接邮件
+                    send_resend_link_email()
+                    self._resend_link_sent = True
+                    self._set_status("二维码已过期,等待重发")
+                    log.info("二维码已过期,第6封链接邮件已发送")
+                    self.root.after(PAUSE * 1000, self._check_resend_flag)
+                    return
+            else:
+                # 正常发邮件(第1-5封)
+                qr_path = os.path.join(tempfile.gettempdir(), f"wechat_qr_{int(time.time())}.png")
+                img2.save(qr_path, "PNG")
+
+                self.hash_mode_emails_sent += 1
 
-            # 发邮件
-            send_qr_email(qr_path)
+                # 发邮件
+                send_qr_email(qr_path)
 
-            # 短信:只在第1次发(无论多少轮,只发一次)
-            if self.hash_mode_emails_sent == 1:
-                if SMS_PHONE:
-                    send_sms("888888", SMS_PHONE)
+                # 短信:只在第1次发(无论多少轮,只发一次)
+                if self.hash_mode_emails_sent == 1:
+                    if SMS_PHONE:
+                        send_sms("888888", SMS_PHONE)
 
-            # 第5封邮件末尾带重发链接
-            if self.hash_mode_emails_sent == MAX_EMAILS:
-                # TODO: 发第5封邮件时包含重发链接
-                log.info("邮件已发满 %d 次,进入等待重发模式", MAX_EMAILS)
+                # 第5封邮件已发完,继续监测,等二维码过期再发第6封
+                if self.hash_mode_emails_sent >= MAX_EMAILS and not self._resend_link_sent:
+                    log.info("第5封邮件已发送,等待二维码过期...")
+                    self._set_status("第5封已发送,等待二维码过期")
 
-            self.last_md5 = _md5_of_image(img2)
-            self._set_status(f"请扫码登录 ({self.hash_mode_emails_sent}/{MAX_EMAILS})")
-            self.root.after(PAUSE * 1000, self._hash_loop_tick)
+                self.last_md5 = _md5_of_image(img2)
+                self._set_status(f"请扫码登录 ({self.hash_mode_emails_sent}/{MAX_EMAILS})")
+                self.root.after(PAUSE * 1000, self._hash_loop_tick)
 
         def _check_resend_flag(self):
             """检查服务器上是否有重发标记"""
-            url = "https://szjxzxh.cn/wechat_resend.flag"
+
+            # ① 先查窗口尺寸
+            wechat_windows = _find_wechat_windows()
+            visible = [w for w in wechat_windows if w.visible]
+            login_window = None
+            for w in visible:
+                if w.width < 700 and w.height < 850:
+                    login_window = w
+                    break
+
+            if not login_window:
+                # 窗口变大了 → 已登录
+                self.hash_mode = False
+                self._last_login_hash = None
+                self.qr_sent_count = 0
+                self._resend_link_sent = False
+                self._set_status("微信运行中")
+                log.info("微信已登录,退出等待重发模式")
+                return
+
+            # ② 查flag
             import requests
+            url = "https://szjxzxh.cn/wechat_resend.flag"
             try:
                 resp = requests.get(url, timeout=5)
                 if resp.status_code == 200:
                     # 用户申请了重发,删除flag文件
-                    # 先删服务器上的flag
                     delete_url = "https://szjxzxh.cn/cgi/wechat_resend.py?action=delete"
                     try:
                         requests.get(delete_url, timeout=5)
@@ -767,6 +836,7 @@ try:
                     # 重置计数,开始新一轮
                     self.hash_mode_emails_sent = 0
                     self.last_md5 = None
+                    self._resend_link_sent = False
                     self._set_status("准备重新发送通知...")
                     log.info("检测到重发请求,开始新一轮通知")
                     self.root.after(PAUSE * 1000, self._hash_loop_tick)