101 lines
3.3 KiB
Python
101 lines
3.3 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
邮件通知模块
|
|
"""
|
|
|
|
import logging
|
|
import smtplib
|
|
from email.mime.multipart import MIMEMultipart
|
|
from email.mime.text import MIMEText
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class EmailNotifier:
|
|
def __init__(self, config):
|
|
self.smtp_host = config['smtp_host']
|
|
self.smtp_port = config['smtp_port']
|
|
self.smtp_user = config['smtp_user']
|
|
self.smtp_password = config['smtp_password']
|
|
self.to_email = config['to_email']
|
|
self.use_tls = config.get('use_tls', True)
|
|
self.use_ssl = config.get('use_ssl', False)
|
|
|
|
def send(self, notifications):
|
|
"""发送邮件通知"""
|
|
if not notifications:
|
|
return
|
|
|
|
subject = f"【通知监控】发现 {len(notifications)} 条新通知"
|
|
|
|
html_body = self._build_html(notifications)
|
|
text_body = self._build_text(notifications)
|
|
|
|
msg = MIMEMultipart('alternative')
|
|
msg['Subject'] = subject
|
|
msg['From'] = self.smtp_user
|
|
msg['To'] = self.to_email
|
|
|
|
msg.attach(MIMEText(text_body, 'plain', 'utf-8'))
|
|
msg.attach(MIMEText(html_body, 'html', 'utf-8'))
|
|
|
|
try:
|
|
if self.use_ssl:
|
|
server = smtplib.SMTP_SSL(self.smtp_host, self.smtp_port)
|
|
else:
|
|
server = smtplib.SMTP(self.smtp_host, self.smtp_port)
|
|
if self.use_tls:
|
|
server.starttls()
|
|
server.login(self.smtp_user, self.smtp_password)
|
|
server.send_message(msg)
|
|
server.quit()
|
|
logger.info(f"邮件发送成功: {subject}")
|
|
except Exception as e:
|
|
logger.error(f"邮件发送失败: {e}")
|
|
|
|
def _build_html(self, notifications):
|
|
# 按来源网站分组
|
|
from collections import defaultdict
|
|
by_site = defaultdict(list)
|
|
for n in notifications:
|
|
source = n.get('source', '未知来源')
|
|
by_site[source].append(n)
|
|
|
|
html_parts = []
|
|
for site_name, items in by_site.items():
|
|
rows = []
|
|
for n in items:
|
|
date = n.get('date', '')
|
|
rows.append(f'<tr><td><a href="{n["link"]}">{n["title"]}</a></td><td>{date}</td></tr>')
|
|
html_parts.append(f'''
|
|
<h3>{site_name}</h3>
|
|
<table border="1" cellpadding="5" cellspacing="0">
|
|
<thead><tr><th>标题</th><th>日期</th></tr></thead>
|
|
<tbody>{''.join(rows)}</tbody>
|
|
</table>
|
|
''')
|
|
|
|
return f'''
|
|
<html>
|
|
<body>
|
|
<h2>新通知 (共 {len(notifications)} 条)</h2>
|
|
{''.join(html_parts)}
|
|
</body>
|
|
</html>
|
|
'''
|
|
|
|
def _build_text(self, notifications):
|
|
from collections import defaultdict
|
|
by_site = defaultdict(list)
|
|
for n in notifications:
|
|
source = n.get('source', '未知来源')
|
|
by_site[source].append(n)
|
|
|
|
lines = [f'新通知 (共 {len(notifications)} 条)\n']
|
|
for site_name, items in by_site.items():
|
|
lines.append(f'\n=== {site_name} ===')
|
|
for n in items:
|
|
date = n.get('date', '')
|
|
lines.append(f"- {n['title']} {date}")
|
|
lines.append(f" {n['link']}")
|
|
return '\n'.join(lines) |