WWW.YOUINFO.SITE
标签聚合 waline

/tag/waline

LinuxDo 最新话题 · 2026-06-08 16:51:18+08:00 · tech

写在前面: 本文首发于 Asahi Blog ,可能会出现 用词不当、不分主次、逻辑不明 等各种 错误 ,以及 入机式发言 ,希望各位佬友批评指正。 升级完 OpenList 的那一刻,我以为只是常规的 bugfix 更新,结果打开主页一看——评论区消失了。 CSS 好端端的,Waline 的样式文件请求返回 200,但 <div id="waline"> 里空空如也,高度是一个令人绝望的 908.812×0 。 折腾了一段时间之后,把问题锁定在了 v4.2.2 的一个 Breaking Change 上。这篇文章就把整个来龙去脉记录下来,顺带把修复方案整合一下,希望踩过同样坑的朋友少花点时间。 问题复现 根据 Waline快速上手中的方案 ,在旧版本(≤ 4.1.10)中仅需在主页的 元数据 README 里写一段 HTML,CSS 和 JS 全部内联: <!-- Waline 容器 --> <link rel="stylesheet" href="https://unpkg.com/@waline/client@v3/dist/waline.css" /> <div id="waline-comment" style="margin: 20px auto; max-width: 960px;"> <h2 style="text-align:center">- 评论 Comments -</h2> <div id="waline"></div> </div> <!-- Waline JS 初始化 --> <script type="module"> import { init } from 'https://unpkg.com/@waline/client@v3/dist/waline.js'; init({ el: '#waline', serverURL: 'https://comments.example.com', emoji: false, comment: true, search: false, path: window.location.pathname, }); </script> 升级到 4.2.2 之后,这段代码的表现变成: <link> 的 CSS 请求正常发出并返回 <script type="module"> 中的 JS 完全没有执行 #waline 容器尺寸为 908.812×0 (宽度撑开了,但高度为 0,Waline 从未初始化) 根本原因:PR #2346 把过滤逻辑从后端搬到了前端 v4.2.2 的 Release Notes 里有两条 Breaking Changes,其中一条就是: settings : Move FilterReadMeScripts to frontend - by @xrgzs in #2346 这条改动对应 commit a5ba6a0 ,看一下实际 diff 就很清楚了。 旧版后端做了什么 旧版的 server/handles/down.go 在代理 .md 文件时,如果 FilterReadMeScripts 开关为 true (默认开启),会在 后端 走一套完整的处理流水线: 用 goldmark 把 Markdown 源文件渲染成 HTML 用 bluemonday 的 UGC Policy 对 HTML 进行 sanitize(消毒) 把清洗过的 HTML 以 text/html 形式返回给前端 bluemonday 的 UGC Policy 会 剥除 <script> 、 <link> 等危险标签 ,这是它的设计初衷。但这套流水线只在 直接代理 .md 文件 时(走 /d/ 路径)才触发,主页展示 README 走的是 /api/fs/get API 接口,后端直接原样返回 Markdown 内容,不经过 bluemonday。 所以旧版真正起作用的机制在前端:前端把 README 内容渲染为 HTML 注入到页面后,会对其中的 <script> 标签做一次 克隆重新 append 的处理,让它们实际执行。 <script type="module"> 就是通过这个机制被触发的。 新版改动:32 行代码的删除 commit a5ba6a0 从 down.go 里 整体删除 了那 31 行后端清洗逻辑,同时移除了对 goldmark 和 bluemonday 两个依赖库的引用,并在 setting.go 里给 FilterReadMeScripts 的配置加上了注释 // frontend ,意思是:这个开关的实际执行逻辑已经全部交给前端负责了。 这是一次架构上的合理重构——把视图层的过滤放在前端做,后端减负,逻辑更清晰。 但问题在于 :前端新版本对 README 内容里 <script> 标签的处理比之前更严格, type="module" 形式的脚本会被 直接过滤掉,不再执行 。 这就解释了所有现象: 现象 原因 CSS 正常加载 <link> 标签通过了前端的过滤,或走了不同处理路径 JS 完全不执行 <script type="module"> 被前端新过滤器丢弃 #waline 高度为 0 容器 div 存在,但 Waline 从未初始化,内容为空 顺便一提, <script type="module"> 在被 innerHTML 动态插入 DOM 时,浏览器本身也不会自动执行——这是浏览器的安全规范,ES Module 的 import 语义只在顶层脚本上下文有效。所以即使前端没过滤,不经过特殊处理的 module script 也跑不起来。旧版前端的克隆 append 机制恰好绕过了这个限制,新版则没有。 完整修复方案 修复思路是把代码分散到三个不同的注入点,各司其职,完全绕开 README 的过滤器: 第一步:自定义头部(Custom Head)—— 放 CSS 进入 设置 → 全局 → 自定义头部 ,填入: <link rel="stylesheet" href="https://unpkg.com/@waline/client@v3/dist/waline.css"> <head> 里的 <link> 走标准 HTML 解析路径,完全不经过任何 README 过滤器,稳定可靠。 第二步:自定义 Body(Custom Body)—— 放 JS 初始化逻辑 进入 设置 → 全局 → 自定义 Body ,填入以下完整代码: <!-- 引入 UMD 版本的 Waline(挂载到 window.Waline 全局变量) --> <script src="https://unpkg.com/@waline/client@v3/dist/waline.umd.js"></script> <script> (function() { let walineInstance = null; let initTimer = null; function doInitWaline() { const walineEl = document.querySelector('#waline'); if (!walineEl || typeof Waline === 'undefined') return; // 容器内已有内容,说明 Waline 正常挂载着,无需重复初始化 if (walineEl.children.length > 0) return; // 有旧实例先销毁,防止内存泄漏 if (walineInstance && typeof walineInstance.destroy === 'function') { try { walineInstance.destroy(); } catch(e) {} walineInstance = null; } walineInstance = Waline.init({ el: '#waline', serverURL: 'https://comments.example.xyz', // 替换为你的 Waline 服务地址 emoji: false, comment: true, search: false, path: window.location.pathname, }); } // 防抖:SPA 路由切换时 DOM 频繁变动,延迟 300ms 等待稳定 function debouncedInit() { clearTimeout(initTimer); initTimer = setTimeout(doInitWaline, 300); } // 1. 页面首次加载 doInitWaline(); // 2. 监听 DOM 变化(SPA 框架动态重建 DOM 时触发) const observer = new MutationObserver(debouncedInit); observer.observe(document.body, { childList: true, subtree: true }); // 3. 拦截 History API(前进/后退/框架内部路由跳转) const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function() { originalPushState.apply(this, arguments); debouncedInit(); }; history.replaceState = function() { originalReplaceState.apply(this, arguments); debouncedInit(); }; window.addEventListener('popstate', debouncedInit); })(); </script> 为什么改用 UMD 而不是 ESM? 原来的 import { init } from '...waline.js' 是 ES Module 写法,有两个问题:一是动态插入的 <script type="module"> 浏览器不执行;二是前端过滤器会丢弃它。改用 waline.umd.js 后,脚本加载后直接把 Waline 挂到 window 上,后续代码用 Waline.init() 调用,完全是普通的全局变量方式,没有任何模块化限制。 为什么需要 MutationObserver 和 History API 拦截? OpenList 是基于 SolidJS 的 SPA(单页应用)。当你从别的目录切换回主页时,整个 DOM 树会被 SolidJS 销毁并重建,之前初始化的 Waline 实例也随之消失。如果只在页面加载时初始化一次,路由切换回来后评论区就空了。 MutationObserver 监听 document.body 的子树变化,每次 DOM 重建后都会触发重新初始化; history.pushState/replaceState 的拦截则覆盖了框架内部路由跳转的场景;300ms 防抖避免 DOM 频繁变动时重复触发。 第三步:主页元数据 README —— 只保留容器 div 回到主页元数据,把 <script> 和 <link> 全部删掉,只保留 HTML 容器: <div id="waline-comment" style="margin: 20px auto; max-width: 960px;"> <h2 style="text-align:center">- 评论 Comments -</h2> <div id="waline"></div> </div> 纯粹的 <div> 不含任何可执行内容,不会被任何过滤器动到。JS 找到这个 #waline 容器后负责挂载,CSS 从 <head> 里来,三方各归其位。 三种注入点的本质区别 理解这三个位置的差异,以后遇到类似问题就不会懵了: 注入点 处理机制 能跑 <script> ? 能跑 <link> ? 主页元数据 README 前端 Markdown 渲染 + 新版过滤器 (被过滤) 看情况,不稳定 自定义 Body 直接注入 <body> ,不走 README 过滤器 自定义 Head 注入 <head> ,标准 HTML 解析 README 的设计初衷是内容展示,过滤脚本是合理的安全考量。需要执行 JS 的逻辑就应该放到 Custom Body/Head 这两个专门为此设计的位置。 1 个帖子 - 1 位参与者 阅读完整话题

LinuxDo 最新话题 · 2026-05-17 14:32:06+08:00 · tech

Waline 默认前端用 Vue 做的,很重,所以换了一个轻点的 Sodesu。 但是这个前端有个问题, 没办法接人机验证 。 所以自己 Vibe 了一下,感觉非常不错。 Haku – 17 May 26 给 Waline 前端加了人机验证 | Haku Turnstile 其实就是一个 Cloudflare 做的人机验证小组件。 长这样 前些时日换了 Sodesu 作为 Waline 的评论前端,体验很好,的确是符合文档里写的体积极小。但是在部分场景,比如我的博客,遇到人机验证就麻烦大了。有一位读者发评论表示(通过 Giscus … 1 个帖子 - 1 位参与者 阅读完整话题

linux.do · 2026-05-04 16:09:36+08:00 · tech

Haku – 3 May 26 给 Waline 做自己的通知邮箱! | Haku 为了一个简简单单的域名邮箱,我花了很久很久。 没有买专业域名邮箱服务的钱,但是发现 Resend 可以自定义发件邮箱,所以简单做个记录,说说用在 Waline 设置评论回复通知的操作。 市面常见的免费邮箱虽然已经够用,但是当需要给自己的服务做收发邮件时,有一个自己域名的邮箱会美观很多。比如我的域名是 karlbaey.top ,我希望我的读者收到评论回复通知时,是来自于 notifications at karlbaey dot top 这个邮箱,就需要自己折腾折腾 Resend 和 Cloudflare。不会太难,设置几个 DNS 记录的事。 要是自购 VPS 而且开了一大堆端口 [1] 而且你前一任租客是个纯良公民拿了 VPS 什么都不干就当我什么都没说,自己拉个 docker 开邮局就行,反正我没有这个折腾的闲心。一个推荐的方案是 Mailu。 叫 Cloudflare 给你自动转发邮件 这至少需要你购买一个域名。免费域名也行,但是要能放在 Cloudflare 上。 在 这个页面 ,就能看到接入域名的提示。 转发到 Gmail 是可选的,转发到 QQ 邮箱也行,因为我们不依赖 Cloudflare 发邮件。然后设置 Cloudflare 的邮箱白名单。 这样其实就好了。但是为了防止 Cloudflare 乱发邮件,还得给特定的邮箱设置转发到 Gmail。比如我的邮箱是 hi at karlbaey dot top (记作邮箱 A),就设置一个。 这样就可以了。下面就是 Resend 那一边的事。 用 Resend 自定义发件邮箱 目前的自定义发件域名服务只有 Resend 一家是免费且额度充足的 [2] ,免费版每天可以发 100 封邮件, 这儿有官网 。跟 Resend 比起来,QQ 邮箱不能绑自定义域名;Gmail 会显示由你的 Gmail 邮箱代发,泄露风险大;Outlook 则是逼着用户开 Microsoft 365。综合考量,Resend 是最佳的选择。 嫌弃发信额度少,就考虑日后换成 Larksuite 也可以,那个一天可以发 450 封邮件,非常慷慨。 先注册一个 Resend,这个很简单,你甚至可以用你的域名邮箱注册。反正上面已经配置好了 Cloudflare 的 catch-all 规则,Resend 的验证邮件会飞到 Gmail 邮箱里边。 注册成功之后就能进入 Dashboard。选择侧栏的 Domains。 如果你照着上面 Cloudflare 配置域名邮件转发的话,下面应该会自动跳出来一个小黄云跟“Auto configure”,点那个就行。一共是 1 条 MX 记录和 3 条 TXT 记录。 在 创建新 API Key 里边 写给 Waline 的 Key,Name 随意填。然后你就能看见 只显示一次 的 Key,把它复制好,下面给 Waline 用。 这样就好了。我用的是 notifications at karlbaey dot top 来发件。 Waline 配置邮件传递 少来了,真以为有人会发评论啊。 Waline 的文档里已经写好了 怎么配置评论通知的环境变量 。我是把 Waline 部署在 Vercel 上的,跳到环境变量(Environment Variables)页面添加就行。下面是一个参考的表格。 变量名 示例值 说明 SMTP_SERVICE Resend 固定填 Resend SMTP_USER resend 固定填 resend SMTP_PASS re_123456789... 你的 Resend API Key SMTP_SECURE true Resend 推荐 SENDER_NAME 你的博客名称 邮件显示的发送者名称 SENDER_EMAIL [email protected] 你用来发信的邮箱 AUTHOR_EMAIL [email protected] 接收通知的管理员邮箱 这样就配置完了。要是你愿意继续折腾可以往下看。 Waline 的邮件模板 我基于 Waline 给的东西 自己魔改了一番,由于它用的是 Nunjunks 模板(不是我熟悉的 Hugo 模板 ),所以可以插入一些条件语法。 重要 !每一个环境变量都需要压缩成一行之后输入 Vercel。HTML 找个地方压缩就行,压缩后不影响解析。 先是两个邮件标题模板。 # 访客收到博主的回复时,邮件的标题 MAIL_SUBJECT="您在 【{{site.name}}】 的评论收到了 {{self.nick}} 的回复" # 博主收到新评论(或新回复)时,邮件的标题 MAIL_SUBJECT_ADMIN="【{{site.name}}】新评论:{{self.nick}} 的留言" 然后是给访客评论用的 MAIL_TEMPLATE 。 <div style="max-width:600px;margin:0 auto;font-family:Arial,sans-serif;background:#f6f8fa;padding:20px"> <h2 style="color:#24292e">{{site.name}}</h2> <p>您在 <a href="{{site.postUrl}}" style="color:#0366d6">【{{site.name}}】</a> 的评论:</p> <blockquote style="background:#fff;padding:12px;border-left:4px solid #d1d5da;margin:12px 0;white-space:pre-wrap">{{parent.comment | safe}}</blockquote> <p><strong>{{self.nick}}</strong> 回复了您:</p> <blockquote style="background:#fff;padding:12px;border-left:4px solid #2ea44f;margin:12px 0;white-space:pre-wrap">{{self.comment | safe}}</blockquote> <a href="{{site.postUrl}}" style="display:inline-block;padding:8px 16px;background:#0366d6;color:#fff;text-decoration:none;border-radius:6px;margin-top:8px">点击查看详情</a> <p style="color:#586069;font-size:12px;margin-top:24px">此邮件由系统自动发送,请勿直接回复。</p> </div> 还有最后给博主的通知模板 MAIL_TEMPLATE_ADMIN 。 <div style="max-width:600px;margin:0 auto;font-family:Arial,sans-serif;background:#f6f8fa;padding:20px"> <h2 style="color:#4169E1">🔔 新评论通知</h2> <p><strong>评论者:</strong>{{self.nick}}</p> <p><strong>来源:</strong>{{self.os}} · {{self.browser}} {% if parent %} <div style="background:#fff3cd;padding:8px 12px;margin:12px 0;border-left:4px solid #f0ad4e"> <p style="margin:0"><strong>回复给:</strong>{{parent.nick}}</p> <blockquote style="margin:8px 0 0;white-space:pre-wrap;color:#586069">{{parent.comment | safe}}</blockquote> </div> {% endif %} <blockquote style="background:#fff;padding:12px;border-left:4px solid #0366d6;margin:12px 0;white-space:pre-wrap">{{self.comment | safe}}</blockquote> <a href="{{site.postUrl}}" style="display:inline-block;padding:8px 16px;background:#2ea44f;color:#fff;text-decoration:none;border-radius:6px">查看评论</a> <p style="color:#586069;font-size:12px;margin-top:16px">系统自动发送,来自 {{self.os}} · {{self.browser}}</p> </div> 效果图大概是下面这样。我把评论通知推到 QQ 邮箱,没有测试过其他家的样子。配色乱搞的,好奇我怎么配色的参考 这里 。 反正我是看过各种各样花里胡哨的评论提醒,有信封式的、有黑黑绿绿黑客式的,甚至还有一点 CSS 都不会写、把整个版面搞得乱七八糟的。我这个重在简单明了,不考虑那么多七七八八的了,关于我的哲学,感兴趣的看 漫漫长路 去(发稿时只有一篇文 )。 See Also 【Cloudflare Docs】Enable Email Routing (英文)←本文基于 Cloudflare 的邮件路由文档写成。 包括:25(SMTP)、465(SMTPS)、587(SMTP提交)、143(IMAP)、993(IMAPS)、110(POP3)、995(POP3S)。其中,25 端口(TCP)用于邮件服务器间投递,至关重要且常被 VPS 厂商封锁,需申请解封。此外,如果使用 Web 界面管理邮局,需开放 80(HTTP)和 443(HTTPS)端口。 ↩︎ 其余的就是 AWS SES 这一类服务了,个人没有负担这费用的必要。 ↩︎ 1 个帖子 - 1 位参与者 阅读完整话题

linux.do · 2026-05-04 00:31:45+08:00 · tech

搭建waline 官网已经给出很详细的搭建教程了 教程 启用 waline 评论 在博客配置文件 _config.stellar.yml 中启用 waline 评论 ######## Comments ######## comments: service: waline # beaudar, utterances, giscus, twikoo, waline, artalk comment_title: 快来参与讨论吧~ # Waline # https://waline.js.org/ waline: js: https://gcore.jsdelivr.net/npm/@waline/[email protected]/dist/waline.js css: https://gcore.jsdelivr.net/npm/@waline/[email protected]/dist/waline.css meta_css: https://gcore.jsdelivr.net/npm/@waline/[email protected]/dist/waline-meta.css # Waline server address url, you should set this to your own link serverURL: https://waline.js.org/ # 这里改成自己的链接 locale: placeholder: 😎嗨,朋友,留下脚印再走呗。 reaction: true 自定义模板 打开vercel给你创建的GitHub仓库,找到 index.cjs ,将代码替换为 const Application = require('@waline/vercel'); module.exports = Application({ async postSave(comment) { // do what ever you want after save comment }, mailSubjectAdmin: '{{site.name | safe}} 上有新评论了', mailTemplateAdmin: `<div style="background: url(https://image.baidu.com/search/down?url=https://tva3.sinaimg.cn/large/c56b8822ly1h62npb7s1ej201y01y0lh.jpg);padding:40px 0px 20px;margin:0px;background-color:#FFCDCE;width:100%;"> <style type="text/css">@media screen and (max-width:600px){.afterimg,.beforeimg{display:none!important}}</style> <div style="border-radius: 10px 10px 10px 10px;font-size:14px;color: #555555;width: 530px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;max-width:100%;background: ##ffffff;"> <img class="beforeimg" style="width:530px;height:317px;pointer-events:none" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png"> <img src="https://tc.ailingsi.top/i/2026/05/02/69f5903474029.png" style="width:100%;overflow:hidden;pointer-events:none;margin-top: -120px;"> <div style="width:100%;background:#f8d1ce;color:#9d2850;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;background: url(https://tva2.sinaimg.cn/large/c56b8822ly1h61tb7tagcj20ii01u3yc.jpg) left top no-repeat;display: flex;justify-content: center;flex-direction: column;"> <p style="font-size:16px;font-weight: bold;text-align:center;word-break:break-all;margin:0;"> 您在<a style="text-decoration:none;color: #9d2850;" href="{{site.url}}"target="_blank">{{site.name}}</a>上的文章有了新的评论</p> </div> <div class="formmain" style="background:#fff;width:100%;max-width:800px;margin:auto auto;overflow:hidden;margin-bottom: -155px;"> <div style="margin:40px auto;width:90%;"><p><strong>{{self.nick}}</strong> 回复说:</p> <div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{self.comment | safe}}</div> <p style="text-align:center;position: relative;z-index: 99;">您可以点击<a style="text-decoration:none;color:#cf5c83" href="{{site.postUrl}}" target="_blank">查看回复的完整內容</a></p> <img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" style="width:100%;margin:25px auto 5px auto;display:block;pointer-events:none"> <p class="bottomhr" style="font-size:12px;text-align:center;color:#999">笑的博客竭诚为您服务!</p> </div> </div> <img class="afterimg" style="width:535px;height:317px;z-index:100;margin-left: -3px;"src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png"> </div> </div>`, mailSubject: '{{parent.nick}},您在『{{site.name}}』上发表的评论收到了来自 {{self.nick}} 的回复', mailTemplate: `<div style="background: url(https://image.baidu.com/search/down?url=https://tva3.sinaimg.cn/large/c56b8822ly1h62npb7s1ej201y01y0lh.jpg);padding:40px 0px 20px;margin:0px;background-color:#FFCDCE;width:100%;"> <style type="text/css">@media screen and (max-width:600px){.afterimg,.beforeimg{display:none!important}}</style> <div style="border-radius: 10px 10px 10px 10px;font-size:14px;color: #555555;width: 530px;font-family:'Century Gothic','Trebuchet MS','Hiragino Sans GB',微软雅黑,'Microsoft Yahei',Tahoma,Helvetica,Arial,'SimSun',sans-serif;margin:50px auto;max-width:100%;background: ##ffffff;"> <img class="beforeimg" style="width:530px;height:317px;z-index:-100;pointer-events:none" src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/before.png"> <img src="https://tc.ailingsi.top/i/2026/05/02/69f5903474029.png" style="width:100%;overflow:hidden;pointer-events:none;margin-top: -120px;"> <div style="width:100%;background:#f8d1ce;color:#9d2850;background-image: -moz-linear-gradient(0deg, rgb(67, 198, 184), rgb(255, 209, 244));height: 66px;background: url(https://tva2.sinaimg.cn/large/c56b8822ly1h61tb7tagcj20ii01u3yc.jpg) left top no-repeat;display: flex;justify-content: center;flex-direction: column;"> <p style="font-size:16px;font-weight: bold;text-align:center;word-break:break-all;margin:0;"> 您在<a style="text-decoration:none;color: #9d2850;" href="{{site.url}}">『{{site.name | safe}}』</a>上的留言有新回复啦!</p> </div> <div class="formmain" style="background:#fff;width:100%;max-width:800px;margin:auto auto;overflow:hidden;margin-bottom: -155px;"> <div style="margin:40px auto;width:90%;"><p>😊Hi,{{parent.nick}},您曾在文章上发表评论:</p> <div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{parent.comment | safe}}</div> <p><strong>{{self.nick}}</strong> 给您的回复如下:</p> <div style="background: #fafafa repeating-linear-gradient(-45deg,#fff,#fff 1.125rem,transparent 1.125rem,transparent 2.25rem);box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15);margin:20px 0px;padding:15px;border-radius:5px;font-size:15px;color:#555555;">{{self.comment | safe}}</div> <p>您可以点击<a style="text-decoration:none; color:#cf5c83" href="{{site.postUrl}}" target="_blank"> 查看回复的完整內容 </a>,欢迎再次光临<a style="text-decoration:none; color:#cf5c83" href="{{site.url}}" target="_blank"> {{site.name}} </a>。<hr /> <p style="font-size:14px;color:#b7adad;text-align:center;position: relative;z-index: 99;">本邮件为系统自动发送,请勿直接回复邮件哦,可到博文内容回复。<br />{{site.url}}</p> </p> <img src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/line.png" style="width:100%;margin:25px auto 5px auto;display:block;pointer-events:none"> <p class="bottomhr" style="font-size:12px;text-align:center;color:#999">笑的博客竭诚为您服务!</p> </div> </div> <img class="afterimg" style="width:535px;height:317px;z-index:100;margin-left: -3px;"src="https://npm.elemecdn.com/hexo-butterfly-envelope/lib/after.png"> </div> </div>` }); 可以进行修改,将其中一些字符串替换成你自己的 预览 配置邮件通知 登录到 vercel ,找到自己的项目设置,添加环境变量 Environment Variables 获取qq授权码 以QQ邮箱为例 登录 QQ邮箱网页版 ,右上角呼出侧边栏,然后点左下角设置,切换到标准版 然后点击左上角设置,点击下方的 账号与安全 ,点击设备管理,授权码管理,可以添加授权码(如未启用,请先启用smtp服务), 手机版的表格有些bug,横屏才能看全 ,如果显示 [email protected] ,刷新一下就行了~ 变量名 变量值(示例) 说明 SMTP_SERVICE QQ 邮箱服务商,点击 这里 查看你的邮箱是否支持,若不支持,填后面的 SMTP_HOST smtp.qq.com SMTP 服务器地址,一般可以在邮箱的设置中找到,不支持上面那个空的时候填 SMTP_PORT 465 SMTP 服务器端口,一般可以在邮箱的设置中找到,,不支持第一个空的时候填 SMTP_USER [email protected] SMTP 邮件发送服务的用户名,一般为登录邮箱。 SMTP_PASS qq授权码 如果服务商没有授权码提供,则可能是登录密码 SMTP_SECURE true 否使用 SSL 连接 SMTP SITE_NAME 灵思博客 网站名称,用于在消息中显示 SITE_URL https://你的网站.top/ 网站地址,用于在消息中显示 AUTHOR_EMAIL 123456789.com 博主邮箱,用来接收新评论通知。如果是博主发布的评论则不进行提醒通知 SENDER_NAME 灵思-blog 自定义发送邮件的发件人(选填) SENDER_EMAIL [email protected] 自定义发送邮件的发件地址,一般与 SMTP_USER 一致(选填,需与 SENDER_NAME 同时填入) 恭喜你,可以顺利接收到邮箱通知了 1 个帖子 - 1 位参与者 阅读完整话题