diff --git a/robot.py b/robot.py index f2f92c6..b8d14f6 100644 --- a/robot.py +++ b/robot.py @@ -17,6 +17,7 @@ from plugin_common.plugin_interface import PluginStatus from plugin_common.plugin_manager import PluginManager from plugin_common.plugin_registry import PluginRegistry from sehuatang.shehuatang import pdf_file_path +from utils.email_util import EmailSender from utils.revoke.message_auto_revoke import MessageAutoRevoke from utils.robot_cmd.robot_command import GroupBotManager, Feature, PermissionStatus @@ -93,6 +94,12 @@ class Robot: # 加载插件 self.LOG.info("插件系统初始化完成") + self.email_sender = EmailSender( + smtp_server="smtp.163.com", + smtp_port=465, + sender_email="bovine_liu@163.com", + sender_password="LTS9BhmX9XhS36QS" + ) def init_wechat_ipad(self): """初始化wechat_ipad客户端""" @@ -215,6 +222,8 @@ class Robot: self.LOG.error(f"获取新消息失败 {e}") if "用户可能退出" in str(e): self.LOG.error(f"用户可能退出: {e}") + self.email_sender.send_wechat_alert("bovine_liu@163.com", f"用户可能退出: {e}", self.wxid, + self.nickname) await self.login_twice_auto_auth() await asyncio.sleep(5) continue @@ -315,6 +324,8 @@ class Robot: self.LOG.error(f"wechat_ipad heartbeat: {e}") if "用户可能退出" in str(e): self.LOG.error(f"用户可能退出: {e}") + self.email_sender.send_wechat_alert("bovine_liu@163.com", f"用户可能退出: {e}", self.wxid, + self.nickname) await self.login_twice_auto_auth() await asyncio.sleep(60) @@ -332,6 +343,8 @@ class Robot: self.LOG.error(f"wechat_ipad heartbeat long: {e}") if "用户可能退出" in str(e): self.LOG.error(f"用户可能退出: {e}") + self.email_sender.send_wechat_alert("bovine_liu@163.com", f"用户可能退出: {e}", self.wxid, + self.nickname) await self.login_twice_auto_auth() await asyncio.sleep(120) diff --git a/utils/email_util.py b/utils/email_util.py new file mode 100644 index 0000000..0fc9f6a --- /dev/null +++ b/utils/email_util.py @@ -0,0 +1,133 @@ +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from email.mime.base import MIMEBase +from email import encoders +import os +import time + + +class EmailSender: + def __init__(self, smtp_server, smtp_port, sender_email, sender_password): + """初始化邮件发送工具类 + + Args: + smtp_server (str): SMTP 服务器地址 + smtp_port (int): SMTP 服务器端口 + sender_email (str): 发件人邮箱地址 + sender_password (str): 发件人邮箱密码或授权码 + """ + self.smtp_server = smtp_server + self.smtp_port = smtp_port + self.sender_email = sender_email + self.sender_password = sender_password + + def send_email(self, recipient, subject, body, is_html=False, attachments=None): + """发送电子邮件 + + Args: + recipient (str or list): 收件人邮箱地址,单个地址或地址列表 + subject (str): 邮件主题 + body (str): 邮件正文内容 + is_html (bool): 是否为 HTML 格式内容 + attachments (list): 附件文件路径列表 + + Returns: + bool: 发送成功返回 True,失败返回 False + """ + try: + # 创建邮件对象 + msg = MIMEMultipart() + msg['From'] = self.sender_email + msg['Subject'] = subject + + # 处理收件人 + if isinstance(recipient, str): + msg['To'] = recipient + else: + msg['To'] = ", ".join(recipient) + + # 添加邮件正文 + if is_html: + msg.attach(MIMEText(body, 'html', 'utf-8')) + else: + msg.attach(MIMEText(body, 'plain', 'utf-8')) + + # 处理附件 + if attachments: + for file_path in attachments: + if os.path.isfile(file_path): + with open(file_path, 'rb') as f: + part = MIMEBase('application', 'octet-stream') + part.set_payload(f.read()) + + # 编码附件 + encoders.encode_base64(part) + + # 添加附件头信息 + part.add_header( + 'Content-Disposition', + f'attachment; filename= {os.path.basename(file_path)}' + ) + msg.attach(part) + + # 连接 SMTP 服务器并发送 + with smtplib.SMTP_SSL(self.smtp_server, self.smtp_port) as server: + server.login(self.sender_email, self.sender_password) + server.send_message(msg) + + return True + + except Exception as e: + print(f"发送邮件失败: {str(e)}") + return False + + def send_wechat_alert(self, recipient, error_msg, wxid, nickname, attachments=None): + """发送微信机器人异常通知邮件 + + Args: + recipient (str or list): 收件人邮箱地址 + error_msg (str): 错误信息 + wxid (str): 微信ID + nickname (str): 微信昵称 + attachments (list): 附件文件路径列表 + + Returns: + bool: 发送成功返回 True,失败返回 False + """ + subject = "微信机器人异常通知:用户可能退出" + content = f""" + + +

微信机器人异常通知

+

检测到微信机器人出现"用户可能退出"异常

+

错误信息: {error_msg}

+

时间: {time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}

+

机器人信息:

+ + + + """ + return self.send_email(recipient, subject, content, is_html=True, attachments=attachments) + + +# 使用示例 +if __name__ == "__main__": + # 配置示例(请替换为实际的 SMTP 服务器信息) + email_sender = EmailSender( + smtp_server="smtp.163.com", + smtp_port=465, + sender_email="bovine_liu@163.com", + sender_password="LTS9BhmX9XhS36QS" + ) + # 发送微信机器人异常通知 + email_sender.send_wechat_alert( + recipient="bovine_liu@163.com", + error_msg="用户未响应,可能是未登录或退出", + wxid="wxid_123456789", + nickname="TestBot", + attachments=["error_log.txt"] + ) \ No newline at end of file