aboutsummaryrefslogtreecommitdiffhomepage
path: root/server/lib/emailer.ts
diff options
context:
space:
mode:
Diffstat (limited to 'server/lib/emailer.ts')
-rw-r--r--server/lib/emailer.ts51
1 files changed, 51 insertions, 0 deletions
diff --git a/server/lib/emailer.ts b/server/lib/emailer.ts
index 25b0aaedd..6532fb4b4 100644
--- a/server/lib/emailer.ts
+++ b/server/lib/emailer.ts
@@ -15,6 +15,53 @@ import { MAbuseFull, MAbuseMessage, MAccountDefault, MActorFollowActors, MActorF
15import { MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../types/models/video' 15import { MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../types/models/video'
16import { JobQueue } from './job-queue' 16import { JobQueue } from './job-queue'
17 17
18const sanitizeHtml = require('sanitize-html')
19const markdownItEmoji = require('markdown-it-emoji/light')
20const MarkdownItClass = require('markdown-it')
21const markdownIt = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
22
23markdownIt.enable([
24 'linkify',
25 'autolink',
26 'emphasis',
27 'link',
28 'newline',
29 'list'
30])
31
32markdownIt.use(markdownItEmoji)
33
34const toSafeHtml = text => {
35 // Restore line feed
36 const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n')
37
38 // Convert possible markdown (emojis, emphasis and lists) to html
39 const html = markdownIt.render(textWithLineFeed)
40
41 // Convert to safe Html
42 return sanitizeHtml(html, {
43 allowedTags: [ 'a', 'p', 'span', 'br', 'strong', 'em', 'ul', 'ol', 'li' ],
44 allowedSchemes: [ 'http', 'https' ],
45 allowedAttributes: {
46 a: [ 'href', 'class', 'target', 'rel' ]
47 },
48 transformTags: {
49 a: (tagName, attribs) => {
50 let rel = 'noopener noreferrer'
51 if (attribs.rel === 'me') rel += ' me'
52
53 return {
54 tagName,
55 attribs: Object.assign(attribs, {
56 target: '_blank',
57 rel
58 })
59 }
60 }
61 }
62 })
63}
64
18const Email = require('email-templates') 65const Email = require('email-templates')
19 66
20class Emailer { 67class Emailer {
@@ -236,6 +283,7 @@ class Emailer {
236 const video = comment.Video 283 const video = comment.Video
237 const videoUrl = WEBSERVER.URL + comment.Video.getWatchStaticPath() 284 const videoUrl = WEBSERVER.URL + comment.Video.getWatchStaticPath()
238 const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath() 285 const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath()
286 const commentHtml = toSafeHtml(comment.text)
239 287
240 const emailPayload: EmailPayload = { 288 const emailPayload: EmailPayload = {
241 template: 'video-comment-new', 289 template: 'video-comment-new',
@@ -245,6 +293,7 @@ class Emailer {
245 accountName: comment.Account.getDisplayName(), 293 accountName: comment.Account.getDisplayName(),
246 accountUrl: comment.Account.Actor.url, 294 accountUrl: comment.Account.Actor.url,
247 comment, 295 comment,
296 commentHtml,
248 video, 297 video,
249 videoUrl, 298 videoUrl,
250 action: { 299 action: {
@@ -262,6 +311,7 @@ class Emailer {
262 const video = comment.Video 311 const video = comment.Video
263 const videoUrl = WEBSERVER.URL + comment.Video.getWatchStaticPath() 312 const videoUrl = WEBSERVER.URL + comment.Video.getWatchStaticPath()
264 const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath() 313 const commentUrl = WEBSERVER.URL + comment.getCommentStaticPath()
314 const commentHtml = toSafeHtml(comment.text)
265 315
266 const emailPayload: EmailPayload = { 316 const emailPayload: EmailPayload = {
267 template: 'video-comment-mention', 317 template: 'video-comment-mention',
@@ -269,6 +319,7 @@ class Emailer {
269 subject: 'Mention on video ' + video.name, 319 subject: 'Mention on video ' + video.name,
270 locals: { 320 locals: {
271 comment, 321 comment,
322 commentHtml,
272 video, 323 video,
273 videoUrl, 324 videoUrl,
274 accountName, 325 accountName,