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.ts103
1 files changed, 57 insertions, 46 deletions
diff --git a/server/lib/emailer.ts b/server/lib/emailer.ts
index 969eae77b..2fad82bcc 100644
--- a/server/lib/emailer.ts
+++ b/server/lib/emailer.ts
@@ -5,36 +5,16 @@ import { join } from 'path'
5import { VideoChannelModel } from '@server/models/video/video-channel' 5import { VideoChannelModel } from '@server/models/video/video-channel'
6import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist' 6import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist'
7import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import' 7import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import'
8import { SANITIZE_OPTIONS, TEXT_WITH_HTML_RULES } from '@shared/core-utils'
9import { AbuseState, EmailPayload, UserAbuse } from '@shared/models' 8import { AbuseState, EmailPayload, UserAbuse } from '@shared/models'
10import { SendEmailOptions } from '../../shared/models/server/emailer.model' 9import { SendEmailDefaultOptions } from '../../shared/models/server/emailer.model'
11import { isTestInstance, root } from '../helpers/core-utils' 10import { isTestInstance, root } from '../helpers/core-utils'
12import { bunyanLogger, logger } from '../helpers/logger' 11import { bunyanLogger, logger } from '../helpers/logger'
13import { CONFIG, isEmailEnabled } from '../initializers/config' 12import { CONFIG, isEmailEnabled } from '../initializers/config'
14import { WEBSERVER } from '../initializers/constants' 13import { WEBSERVER } from '../initializers/constants'
15import { MAbuseFull, MAbuseMessage, MAccountDefault, MActorFollowActors, MActorFollowFull, MUser } from '../types/models' 14import { MAbuseFull, MAbuseMessage, MAccountDefault, MActorFollowActors, MActorFollowFull, MPlugin, MUser } from '../types/models'
16import { MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../types/models/video' 15import { MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../types/models/video'
17import { JobQueue } from './job-queue' 16import { JobQueue } from './job-queue'
18 17import { toSafeHtml } from '../helpers/markdown'
19const sanitizeHtml = require('sanitize-html')
20const markdownItEmoji = require('markdown-it-emoji/light')
21const MarkdownItClass = require('markdown-it')
22const markdownIt = new MarkdownItClass('default', { linkify: true, breaks: true, html: true })
23
24markdownIt.enable(TEXT_WITH_HTML_RULES)
25
26markdownIt.use(markdownItEmoji)
27
28const toSafeHtml = text => {
29 // Restore line feed
30 const textWithLineFeed = text.replace(/<br.?\/?>/g, '\r\n')
31
32 // Convert possible markdown (emojis, emphasis and lists) to html
33 const html = markdownIt.render(textWithLineFeed)
34
35 // Convert to safe Html
36 return sanitizeHtml(html, SANITIZE_OPTIONS)
37}
38 18
39const Email = require('email-templates') 19const Email = require('email-templates')
40 20
@@ -403,9 +383,9 @@ class Emailer {
403 } 383 }
404 384
405 async addVideoAutoBlacklistModeratorsNotification (to: string[], videoBlacklist: MVideoBlacklistLightVideo) { 385 async addVideoAutoBlacklistModeratorsNotification (to: string[], videoBlacklist: MVideoBlacklistLightVideo) {
406 const VIDEO_AUTO_BLACKLIST_URL = WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list' 386 const videoAutoBlacklistUrl = WEBSERVER.URL + '/admin/moderation/video-auto-blacklist/list'
407 const videoUrl = WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath() 387 const videoUrl = WEBSERVER.URL + videoBlacklist.Video.getWatchStaticPath()
408 const channel = (await VideoChannelModel.loadByIdAndPopulateAccount(videoBlacklist.Video.channelId)).toFormattedSummaryJSON() 388 const channel = (await VideoChannelModel.loadAndPopulateAccount(videoBlacklist.Video.channelId)).toFormattedSummaryJSON()
409 389
410 const emailPayload: EmailPayload = { 390 const emailPayload: EmailPayload = {
411 template: 'video-auto-blacklist-new', 391 template: 'video-auto-blacklist-new',
@@ -417,7 +397,7 @@ class Emailer {
417 videoName: videoBlacklist.Video.name, 397 videoName: videoBlacklist.Video.name,
418 action: { 398 action: {
419 text: 'Review autoblacklist', 399 text: 'Review autoblacklist',
420 url: VIDEO_AUTO_BLACKLIST_URL 400 url: videoAutoBlacklistUrl
421 } 401 }
422 } 402 }
423 } 403 }
@@ -472,6 +452,36 @@ class Emailer {
472 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload }) 452 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
473 } 453 }
474 454
455 addNewPeerTubeVersionNotification (to: string[], latestVersion: string) {
456 const emailPayload: EmailPayload = {
457 to,
458 template: 'peertube-version-new',
459 subject: `A new PeerTube version is available: ${latestVersion}`,
460 locals: {
461 latestVersion
462 }
463 }
464
465 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
466 }
467
468 addNewPlugionVersionNotification (to: string[], plugin: MPlugin) {
469 const pluginUrl = WEBSERVER.URL + '/admin/plugins/list-installed?pluginType=' + plugin.type
470
471 const emailPayload: EmailPayload = {
472 to,
473 template: 'plugin-version-new',
474 subject: `A new plugin/theme version is available: ${plugin.name}@${plugin.latestVersion}`,
475 locals: {
476 pluginName: plugin.name,
477 latestVersion: plugin.latestVersion,
478 pluginUrl
479 }
480 }
481
482 return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
483 }
484
475 addPasswordResetEmailJob (username: string, to: string, resetPasswordUrl: string) { 485 addPasswordResetEmailJob (username: string, to: string, resetPasswordUrl: string) {
476 const emailPayload: EmailPayload = { 486 const emailPayload: EmailPayload = {
477 template: 'password-reset', 487 template: 'password-reset',
@@ -569,26 +579,27 @@ class Emailer {
569 }) 579 })
570 580
571 for (const to of options.to) { 581 for (const to of options.to) {
572 await email 582 const baseOptions: SendEmailDefaultOptions = {
573 .send(merge( 583 template: 'common',
574 { 584 message: {
575 template: 'common', 585 to,
576 message: { 586 from: options.from,
577 to, 587 subject: options.subject,
578 from: options.from, 588 replyTo: options.replyTo
579 subject: options.subject, 589 },
580 replyTo: options.replyTo 590 locals: { // default variables available in all templates
581 }, 591 WEBSERVER,
582 locals: { // default variables available in all templates 592 EMAIL: CONFIG.EMAIL,
583 WEBSERVER, 593 instanceName: CONFIG.INSTANCE.NAME,
584 EMAIL: CONFIG.EMAIL, 594 text: options.text,
585 instanceName: CONFIG.INSTANCE.NAME, 595 subject: options.subject
586 text: options.text, 596 }
587 subject: options.subject 597 }
588 } 598
589 }, 599 // overriden/new variables given for a specific template in the payload
590 options // overriden/new variables given for a specific template in the payload 600 const sendOptions = merge(baseOptions, options)
591 ) as SendEmailOptions) 601
602 await email.send(sendOptions)
592 .then(res => logger.debug('Sent email.', { res })) 603 .then(res => logger.debug('Sent email.', { res }))
593 .catch(err => logger.error('Error in email sender.', { err })) 604 .catch(err => logger.error('Error in email sender.', { err }))
594 } 605 }