import poplib
import ssl
import email
from email.header import decode_header
import time
import pymysql

# 关闭SSL校验，解决老Python握手重置
#ssl._create_default_https_context = ssl._create_unverified_context

# ========== 邮箱配置 自行修改 ==========
MAIL_HOST = "pop.163.com"
MAIL_PORT = 995
MAIL_USER = "lyudream@163.com"
MAIL_PWD = "DVZxyF5NKCkR6fL5"

# ========== 本地MariaDB配置 ==========
DB_HOST = "127.0.0.1"
DB_USER = "root"
DB_PWD = "hp93000"
DB_NAME = "alert_mail_stat"

# 解码邮件标题、正文
def decode_str(s):
    value, charset = decode_header(s)[0]
    if charset:
        value = value.decode(charset)
    return value

# 获取邮件正文
def get_email_content(msg):
    content = ""
    if msg.is_multipart():
        for part in msg.walk():
            content_type = part.get_content_type()
            content_disposition = str(part.get("Content-Disposition"))
            if content_type == 'text/plain' and 'attachment' not in content_disposition:
                payload = part.get_payload(decode=True)
                charset = part.get_charset()
                if charset is None:
                    charset = 'utf-8'
                content = payload.decode(charset, errors='ignore')
                break
    else:
        payload = msg.get_payload(decode=True)
        charset = msg.get_charset()
        if charset is None:
            charset = 'utf-8'
        content = payload.decode(charset, errors='ignore')
    return content

# 简单解析告警关键字（适配Alertmanager中文邮件模板：告警名称、实例、级别）
def parse_alert_info(text):
    alert_name = ""
    instance = ""
    severity = "unknown"
    lines = text.splitlines()
    for line in lines:
        if "告警名称" in line:
            alert_name = line.split("：")[-1].strip()
        if "实例" in line:
            instance = line.split("：")[-1].strip()
        if "级别" in line:
            s_val = line.split("：")[-1].strip()
            if s_val.lower() in ["critical", "严重"]:
                severity = "critical"
            elif s_val.lower() in ["warning", "警告"]:
                severity = "warning"
    return alert_name, instance, severity

# 主抓取逻辑
def crawl_mail():
    # 连接数据库
    db = pymysql.connect(host=DB_HOST, user=DB_USER, password=DB_PWD, database=DB_NAME, charset='utf8mb4')
    cursor = db.cursor()

    # 连接POP3邮箱
    pop_conn = poplib.POP3_SSL(MAIL_HOST, MAIL_PORT)
    pop_conn.user(MAIL_USER)
    pop_conn.pass_(MAIL_PWD)
    total_num, total_size = pop_conn.stat()
    print(f"当前邮箱总邮件数量: {total_num}")

    if total_num == 0:
        print("暂无新邮件")
        pop_conn.quit()
        db.close()
        return

    # 从最新一封开始遍历
    for idx in range(total_num, 0, -1):
        # 获取邮件原始内容
        resp, raw_lines, octet = pop_conn.retr(idx)
        raw_msg = b'\r\n'.join(raw_lines).decode('utf-8', errors='ignore')
        msg = email.message_from_string(raw_msg)

        # 生成唯一标识去重
        mail_uid = msg.get("Message-ID", str(time.time()))

        # 查重，避免重复入库
        cursor.execute("SELECT id FROM alert_log WHERE mail_uid=%s", (mail_uid,))
        if cursor.fetchone():
            print(f"邮件{idx}已存在数据库，跳过")
            continue

        # 解析标题、发件人
        subject = decode_str(msg.get("Subject", ""))
        from_addr = msg.get("From", "")

        # ===================== 临时关闭发件人过滤，全部邮件放行测试 =====================
        # if "prometheusalert" not in from_addr.lower():
        #     print(f"邮件{idx}发件人不匹配，跳过，发件人：{from_addr}")
        #     continue

        # 调试打印所有邮件基础信息
        print("\n========================================")
        print(f"【调试】正在处理第 {idx} 封邮件")
        print(f"发件人：{from_addr}")
        print(f"邮件标题：{subject}")
        print("========================================")

        # 正文解析告警字段
        body = get_email_content(msg)
        alert_name, instance, severity = parse_alert_info(body)
        if not alert_name:
            print(f"邮件{idx}未识别到【告警名称】关键字，跳过")
            continue

        # 区分触发/恢复告警
        alert_type = 1
        if "恢复" in subject or "resolved" in subject.lower():
            alert_type = 2

        now = time.strftime("%Y-%m-%d %H:%M:%S")
        sql = """
        INSERT INTO alert_log
        (mail_uid, alert_type, alert_name, instance, severity, starts_at, ends_at, content, receive_time)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
        """
        cursor.execute(sql, (mail_uid, alert_type, alert_name, instance, severity, now, None, body, now))
        db.commit()
        print(f"入库成功 | 告警:{alert_name} 实例:{instance}")

    pop_conn.quit()
    cursor.close()
    db.close()
    print("\n本次抓取全部完成")

if __name__ == "__main__":
    crawl_mail()
