feat:自动更换ip+流量监控

This commit is contained in:
2026-01-07 17:19:53 +08:00
commit 035da64084
27 changed files with 6182 additions and 0 deletions

197
services/email_service.py Normal file
View File

@@ -0,0 +1,197 @@
"""邮件发送服务"""
from __future__ import annotations
import logging
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from typing import Optional
logger = logging.getLogger(__name__)
def send_email(
smtp_host: str,
smtp_port: int,
smtp_user: str,
smtp_password: str,
use_tls: bool,
to_email: str,
subject: str,
body: str,
html_body: Optional[str] = None,
) -> dict:
"""
发送邮件
Args:
smtp_host: SMTP 服务器地址
smtp_port: SMTP 端口
smtp_user: SMTP 用户名
smtp_password: SMTP 密码
use_tls: 是否使用 TLS
to_email: 收件人邮箱
subject: 邮件主题
body: 纯文本内容
html_body: HTML 内容(可选)
Returns:
{"ok": True/False, "message": "..."}
"""
try:
# 创建邮件
msg = MIMEMultipart("alternative")
msg["Subject"] = subject
msg["From"] = smtp_user
msg["To"] = to_email
# 添加纯文本内容
part1 = MIMEText(body, "plain", "utf-8")
msg.attach(part1)
# 添加 HTML 内容
if html_body:
part2 = MIMEText(html_body, "html", "utf-8")
msg.attach(part2)
# 连接 SMTP 服务器
if use_tls:
server = smtplib.SMTP(smtp_host, smtp_port, timeout=30)
server.starttls()
else:
server = smtplib.SMTP_SSL(smtp_host, smtp_port, timeout=30)
server.login(smtp_user, smtp_password)
server.sendmail(smtp_user, [to_email], msg.as_string())
server.quit()
logger.info("Email sent successfully to %s: %s", to_email, subject)
return {"ok": True, "message": "邮件发送成功"}
except smtplib.SMTPAuthenticationError as e:
logger.error("SMTP authentication failed: %s", e)
return {"ok": False, "message": "SMTP 认证失败,请检查用户名和密码"}
except smtplib.SMTPConnectError as e:
logger.error("SMTP connection failed: %s", e)
return {"ok": False, "message": "无法连接到 SMTP 服务器"}
except Exception as e:
logger.exception("Failed to send email")
return {"ok": False, "message": str(e)}
def send_traffic_alert_email(
smtp_host: str,
smtp_port: int,
smtp_user: str,
smtp_password: str,
use_tls: bool,
to_email: str,
machine_name: str,
aws_service: str,
current_traffic_gb: float,
limit_gb: float,
traffic_type: str, # "total" or "upload"
) -> dict:
"""
发送流量预警邮件
Args:
machine_name: 机器名称
aws_service: 服务类型ec2/lightsail
current_traffic_gb: 当前流量GB
limit_gb: 限制流量GB
traffic_type: 流量类型total=总流量, upload=上传流量)
"""
if traffic_type == "total":
traffic_desc = "总流量(上传+下载)"
else:
traffic_desc = "上传流量"
subject = f"[ProxyAuto] 流量预警 - {machine_name}"
body = f"""
流量预警通知
机器名称: {machine_name}
服务类型: {aws_service.upper()}
预警类型: {traffic_desc}超限
当前{traffic_desc}: {current_traffic_gb:.2f} GB
设定限制: {limit_gb:.2f} GB
超出: {current_traffic_gb - limit_gb:.2f} GB
系统已自动暂停该机器的 IP 自动更换任务。
---
ProxyAuto Pro 自动通知
"""
html_body = f"""
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; line-height: 1.6; color: #333; }}
.container {{ max-width: 600px; margin: 0 auto; padding: 20px; }}
.header {{ background: linear-gradient(135deg, #1F6BFF, #3D8BFF); color: white; padding: 20px; border-radius: 8px 8px 0 0; }}
.content {{ background: #f9f9f9; padding: 20px; border: 1px solid #e0e0e0; border-top: none; border-radius: 0 0 8px 8px; }}
.alert {{ background: #FEE2E2; border-left: 4px solid #EF4444; padding: 15px; margin: 15px 0; border-radius: 4px; }}
.info-row {{ display: flex; justify-content: space-between; padding: 10px 0; border-bottom: 1px solid #e0e0e0; }}
.info-label {{ color: #666; }}
.info-value {{ font-weight: 600; }}
.footer {{ text-align: center; padding: 15px; color: #999; font-size: 12px; }}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h2 style="margin: 0;">流量预警通知</h2>
</div>
<div class="content">
<div class="alert">
<strong>警告:</strong>{traffic_desc}已超出设定限制!
</div>
<div class="info-row">
<span class="info-label">机器名称</span>
<span class="info-value">{machine_name}</span>
</div>
<div class="info-row">
<span class="info-label">服务类型</span>
<span class="info-value">{aws_service.upper()}</span>
</div>
<div class="info-row">
<span class="info-label">当前{traffic_desc}</span>
<span class="info-value" style="color: #EF4444;">{current_traffic_gb:.2f} GB</span>
</div>
<div class="info-row">
<span class="info-label">设定限制</span>
<span class="info-value">{limit_gb:.2f} GB</span>
</div>
<div class="info-row">
<span class="info-label">超出流量</span>
<span class="info-value" style="color: #EF4444;">{current_traffic_gb - limit_gb:.2f} GB</span>
</div>
<p style="margin-top: 20px; color: #666;">
系统已自动暂停该机器的 IP 自动更换任务。请登录控制台查看详情。
</p>
</div>
<div class="footer">
ProxyAuto Pro 自动通知
</div>
</div>
</body>
</html>
"""
return send_email(
smtp_host=smtp_host,
smtp_port=smtp_port,
smtp_user=smtp_user,
smtp_password=smtp_password,
use_tls=use_tls,
to_email=to_email,
subject=subject,
body=body,
html_body=html_body,
)