😶🌫️添加邮件模板以美观
This commit is contained in:
		@@ -31,6 +31,7 @@ rss_subscribe:
 | 
			
		||||
  github_username: willow-god
 | 
			
		||||
  github_repo: Friend-Circle-Lite
 | 
			
		||||
  your_blog_url: https://blog.qyliu.top/
 | 
			
		||||
  email_template: "./rss_subscribe/email_template.html"
 | 
			
		||||
 | 
			
		||||
# SMTP 配置
 | 
			
		||||
# 解释:使用其中的相关配置实现上面两种功能,若无推送要求可以不配置,请将以上两个配置置为false
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
import smtplib
 | 
			
		||||
from email.mime.multipart import MIMEMultipart
 | 
			
		||||
from email.mime.text import MIMEText
 | 
			
		||||
from jinja2 import Environment, FileSystemLoader
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
def email_sender(
 | 
			
		||||
    target_email, 
 | 
			
		||||
@@ -10,6 +12,8 @@ def email_sender(
 | 
			
		||||
    password, 
 | 
			
		||||
    subject, 
 | 
			
		||||
    body,
 | 
			
		||||
    template_path=None,
 | 
			
		||||
    template_data=None,
 | 
			
		||||
    use_tls=True,
 | 
			
		||||
    ):
 | 
			
		||||
    """
 | 
			
		||||
@@ -20,11 +24,12 @@ def email_sender(
 | 
			
		||||
    sender_email (str): 发信邮箱地址。
 | 
			
		||||
    smtp_server (str): SMTP 服务地址。
 | 
			
		||||
    port (int): SMTP 服务端口。
 | 
			
		||||
    use_ssl (bool): 是否使用 SSL 加密。
 | 
			
		||||
    username (str): SMTP 服务用户名。
 | 
			
		||||
    password (str): SMTP 服务密码。
 | 
			
		||||
    subject (str): 邮件主题。
 | 
			
		||||
    body (str): 邮件内容。
 | 
			
		||||
    template_path (str): HTML 模板文件路径。默认为 None。
 | 
			
		||||
    template_data (dict): 渲染模板的数据。默认为 None。
 | 
			
		||||
    use_tls (bool): 是否使用 TLS 加密。默认为 True。
 | 
			
		||||
    """
 | 
			
		||||
    # 创建 MIME 对象
 | 
			
		||||
    msg = MIMEMultipart()
 | 
			
		||||
@@ -32,8 +37,15 @@ def email_sender(
 | 
			
		||||
    msg['To'] = target_email
 | 
			
		||||
    msg['Subject'] = subject
 | 
			
		||||
 | 
			
		||||
    # 添加邮件内容
 | 
			
		||||
    msg.attach(MIMEText(body, 'plain'))
 | 
			
		||||
    if template_path and template_data:
 | 
			
		||||
        # 使用 Jinja2 渲染 HTML 模板
 | 
			
		||||
        env = Environment(loader=FileSystemLoader(os.path.dirname(template_path)))
 | 
			
		||||
        template = env.get_template(os.path.basename(template_path))
 | 
			
		||||
        html_content = template.render(template_data)
 | 
			
		||||
        msg.attach(MIMEText(html_content, 'html'))
 | 
			
		||||
    else:
 | 
			
		||||
        # 添加纯文本邮件内容
 | 
			
		||||
        msg.attach(MIMEText(body, 'plain'))
 | 
			
		||||
 | 
			
		||||
    # 连接到 SMTP 服务器并发送邮件
 | 
			
		||||
    try:
 | 
			
		||||
@@ -46,7 +58,7 @@ def email_sender(
 | 
			
		||||
    except Exception as e:
 | 
			
		||||
        print(f'无法发送邮件到 {target_email}. 错误: {e}')
 | 
			
		||||
 | 
			
		||||
def send_emails(emails, sender_email, smtp_server, port, password, subject, body, use_tls=True):
 | 
			
		||||
def send_emails(emails, sender_email, smtp_server, port, password, subject, body, template_path=None, template_data=None, use_tls=True):
 | 
			
		||||
    """
 | 
			
		||||
    循环发送邮件给指定的多个邮箱。
 | 
			
		||||
 | 
			
		||||
@@ -58,12 +70,11 @@ def send_emails(emails, sender_email, smtp_server, port, password, subject, body
 | 
			
		||||
    password (str): SMTP 服务密码。
 | 
			
		||||
    subject (str): 邮件主题。
 | 
			
		||||
    body (str): 邮件内容。
 | 
			
		||||
    use_tls (bool): 是否使用 TLS 加密,默认为 True。
 | 
			
		||||
    template_path (str): HTML 模板文件路径。默认为 None。
 | 
			
		||||
    template_data (dict): 渲染模板的数据。默认为 None。
 | 
			
		||||
    use_tls (bool): 是否使用 TLS 加密。默认为 True。
 | 
			
		||||
    """
 | 
			
		||||
    for email in emails:
 | 
			
		||||
        print(f'正在发送邮件到 {email}')
 | 
			
		||||
        print(f'---------------------------\n邮件主题: {subject}\n邮件内容: {body}\n发件人: {sender_email}\n---------------------------')
 | 
			
		||||
        email_sender(email, sender_email, smtp_server, port, password, subject, body, use_tls)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        email_sender(email, sender_email, smtp_server, port, password, subject, body, template_path, template_data, use_tls)
 | 
			
		||||
@@ -2,4 +2,5 @@ datetime
 | 
			
		||||
python-dateutil==2.9.0.post0
 | 
			
		||||
requests
 | 
			
		||||
feedparser==6.0.11
 | 
			
		||||
PyYAML==6.0.1
 | 
			
		||||
PyYAML==6.0.1
 | 
			
		||||
jinja2==3.1.2
 | 
			
		||||
							
								
								
									
										135
									
								
								rss_subscribe/email_template.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								rss_subscribe/email_template.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,135 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
    <title>最新文章通知</title>
 | 
			
		||||
    <style>
 | 
			
		||||
        body {
 | 
			
		||||
            font-family: Arial, sans-serif;
 | 
			
		||||
            background-color: #f4f4f4;
 | 
			
		||||
            margin: 0;
 | 
			
		||||
            padding: 0;
 | 
			
		||||
        }
 | 
			
		||||
        .container {
 | 
			
		||||
            background-color: #ffffff;
 | 
			
		||||
            margin: 50px auto;
 | 
			
		||||
            padding: 40px;
 | 
			
		||||
            border-radius: 10px;
 | 
			
		||||
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
 | 
			
		||||
            width: 80%;
 | 
			
		||||
            max-width: 600px;
 | 
			
		||||
        }
 | 
			
		||||
        .header {
 | 
			
		||||
            margin-top: 30px;
 | 
			
		||||
            text-align: center;
 | 
			
		||||
            padding-bottom: 20px;
 | 
			
		||||
        }
 | 
			
		||||
        .header h1 {
 | 
			
		||||
            margin: 0;
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            text-overflow: ellipsis;
 | 
			
		||||
        }
 | 
			
		||||
        .content {
 | 
			
		||||
            font-size: 16px;
 | 
			
		||||
            line-height: 1.6;
 | 
			
		||||
        }
 | 
			
		||||
        .content p {
 | 
			
		||||
            margin: 10px 0;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        .content .title {
 | 
			
		||||
            display: inline-block;
 | 
			
		||||
            max-width: 100%;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            text-overflow: ellipsis;
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
            vertical-align: middle;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .content p strong {
 | 
			
		||||
            display: inline-block;
 | 
			
		||||
            max-width: 100px;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            text-overflow: ellipsis;
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
            vertical-align: middle;
 | 
			
		||||
        }
 | 
			
		||||
        .content .summary {
 | 
			
		||||
            display: -webkit-box;
 | 
			
		||||
            -webkit-box-orient: vertical;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            text-overflow: ellipsis;
 | 
			
		||||
            word-wrap: break-word;
 | 
			
		||||
            word-break: break-all;
 | 
			
		||||
        }
 | 
			
		||||
        .content .published {
 | 
			
		||||
            display: inline-block;
 | 
			
		||||
            max-width: 100%;
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            text-overflow: ellipsis;
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
            vertical-align: middle;
 | 
			
		||||
        }
 | 
			
		||||
        .button {
 | 
			
		||||
            display: block;
 | 
			
		||||
            width: 200px;
 | 
			
		||||
            max-width: 100%;
 | 
			
		||||
            margin: 20px auto;
 | 
			
		||||
            padding: 10px 20px;
 | 
			
		||||
            text-align: center;
 | 
			
		||||
            background-color: #007bff;
 | 
			
		||||
            color: #ffffff;
 | 
			
		||||
            text-decoration: none;
 | 
			
		||||
            border-radius: 5px;
 | 
			
		||||
        }
 | 
			
		||||
        .button:hover {
 | 
			
		||||
            background-color: #0056b3;
 | 
			
		||||
        }
 | 
			
		||||
        @media (max-width: 300px) {
 | 
			
		||||
            .button {
 | 
			
		||||
                width: auto;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        .footer {
 | 
			
		||||
            text-align: center;
 | 
			
		||||
            margin-top: 20px;
 | 
			
		||||
            font-size: 18px;
 | 
			
		||||
            color: #777777;
 | 
			
		||||
        }
 | 
			
		||||
        .unsubscribe {
 | 
			
		||||
            text-align: center;
 | 
			
		||||
            margin-top: 60px;
 | 
			
		||||
            font-size: 12px;
 | 
			
		||||
            color: #777777;
 | 
			
		||||
        }
 | 
			
		||||
        .unsubscribe a {
 | 
			
		||||
            color: #777777;
 | 
			
		||||
            text-decoration: none;
 | 
			
		||||
        }
 | 
			
		||||
        .unsubscribe a:hover {
 | 
			
		||||
            text-decoration: underline;
 | 
			
		||||
        }
 | 
			
		||||
    </style>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <div class="container">
 | 
			
		||||
        <div class="header">
 | 
			
		||||
            <h1>清羽飞扬の最新文章</h1>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="content">
 | 
			
		||||
            <p><strong>文章标题:</strong> <span class="title">{{ title }}</span></p>
 | 
			
		||||
            <p><strong>文章内容:</strong> <span class="summary">{{ summary }}</span></p>
 | 
			
		||||
            <p><strong>发布时间:</strong> <span class="published">{{ published }}</span></p>
 | 
			
		||||
        </div>
 | 
			
		||||
        <a href="{{ link }}" class="button">阅读更多</a>
 | 
			
		||||
        <div class="footer">
 | 
			
		||||
            <p>感谢您的订阅!</p>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="unsubscribe">
 | 
			
		||||
            <p><a href="https://github.com/willow-god/Friend-Circle-Lite/issues">取消订阅</a></p>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
@@ -1,13 +1,5 @@
 | 
			
		||||
{
 | 
			
		||||
    "articles": [
 | 
			
		||||
        {
 | 
			
		||||
            "title": "Spikformer脉冲神经网络学习",
 | 
			
		||||
            "author": "",
 | 
			
		||||
            "link": "https://blog.qyliu.top/posts/67189760/",
 | 
			
		||||
            "published": "2024-07-06 05:33",
 | 
			
		||||
            "summary": "近期我们进行了人工智能实训,我们小组选择的是脉冲神经网络,不同于原先的神经网络,这个网络采用的是脉冲信号,目前脉冲神经网络的效果并不是很好,但是因为是一个全新的神经网络架构,并且基于生物启发的计算方式,使得它们在处理稀疏和非结构化数据时具有独特的优势。",
 | 
			
		||||
            "content": "近期我们进行了人工智能实训,我们小组选择的是脉冲神经网络,不同于原先的神经网络,这个网络采用的是脉冲信号,目前脉冲神经网络的效果并不是很好,但是因为是一个全新的神经网络架构,并且基于生物启发的计算方式,使得它们在处理稀疏和非结构化数据时具有独特的优势。"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "title": "东软软件园实习日记",
 | 
			
		||||
            "author": "",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								run.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								run.py
									
									
									
									
									
								
							@@ -38,6 +38,7 @@ if config["rss_subscribe"]["enable"]:
 | 
			
		||||
    github_username = config["rss_subscribe"]["github_username"]
 | 
			
		||||
    github_repo = config["rss_subscribe"]["github_repo"]
 | 
			
		||||
    your_blog_url = config["rss_subscribe"]["your_blog_url"]
 | 
			
		||||
    email_template = config["rss_subscribe"]["email_template"]
 | 
			
		||||
    # 获取最近更新的文章
 | 
			
		||||
    latest_articles = get_latest_articles_from_link(
 | 
			
		||||
        url=your_blog_url,
 | 
			
		||||
@@ -58,6 +59,13 @@ if config["rss_subscribe"]["enable"]:
 | 
			
		||||
            print("获取到的邮箱列表为:", email_list)
 | 
			
		||||
        # 循环latest_articles,发送邮件
 | 
			
		||||
        for article in latest_articles:
 | 
			
		||||
            template_data = {
 | 
			
		||||
                "title": article["title"],
 | 
			
		||||
                "summary": article["summary"],
 | 
			
		||||
                "published": article["published"],
 | 
			
		||||
                "link": article["link"]
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            send_emails(
 | 
			
		||||
                emails=email_list["emails"],
 | 
			
		||||
                sender_email=email,
 | 
			
		||||
@@ -66,5 +74,7 @@ if config["rss_subscribe"]["enable"]:
 | 
			
		||||
                password=password,
 | 
			
		||||
                subject="清羽飞扬の最新文章:" + article["title"],
 | 
			
		||||
                body="文章链接:" + article["link"] + "\n" + "文章内容:" + article["summary"] + "\n" + "发布时间:" + article["published"],
 | 
			
		||||
                template_path=email_template,
 | 
			
		||||
                template_data=template_data,
 | 
			
		||||
                use_tls=use_tls
 | 
			
		||||
            )
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user