diff options
Diffstat (limited to 'server/lib/emailer.ts')
-rw-r--r-- | server/lib/emailer.ts | 103 |
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' | |||
5 | import { VideoChannelModel } from '@server/models/video/video-channel' | 5 | import { VideoChannelModel } from '@server/models/video/video-channel' |
6 | import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist' | 6 | import { MVideoBlacklistLightVideo, MVideoBlacklistVideo } from '@server/types/models/video/video-blacklist' |
7 | import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import' | 7 | import { MVideoImport, MVideoImportVideo } from '@server/types/models/video/video-import' |
8 | import { SANITIZE_OPTIONS, TEXT_WITH_HTML_RULES } from '@shared/core-utils' | ||
9 | import { AbuseState, EmailPayload, UserAbuse } from '@shared/models' | 8 | import { AbuseState, EmailPayload, UserAbuse } from '@shared/models' |
10 | import { SendEmailOptions } from '../../shared/models/server/emailer.model' | 9 | import { SendEmailDefaultOptions } from '../../shared/models/server/emailer.model' |
11 | import { isTestInstance, root } from '../helpers/core-utils' | 10 | import { isTestInstance, root } from '../helpers/core-utils' |
12 | import { bunyanLogger, logger } from '../helpers/logger' | 11 | import { bunyanLogger, logger } from '../helpers/logger' |
13 | import { CONFIG, isEmailEnabled } from '../initializers/config' | 12 | import { CONFIG, isEmailEnabled } from '../initializers/config' |
14 | import { WEBSERVER } from '../initializers/constants' | 13 | import { WEBSERVER } from '../initializers/constants' |
15 | import { MAbuseFull, MAbuseMessage, MAccountDefault, MActorFollowActors, MActorFollowFull, MUser } from '../types/models' | 14 | import { MAbuseFull, MAbuseMessage, MAccountDefault, MActorFollowActors, MActorFollowFull, MPlugin, MUser } from '../types/models' |
16 | import { MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../types/models/video' | 15 | import { MCommentOwnerVideo, MVideo, MVideoAccountLight } from '../types/models/video' |
17 | import { JobQueue } from './job-queue' | 16 | import { JobQueue } from './job-queue' |
18 | 17 | import { toSafeHtml } from '../helpers/markdown' | |
19 | const sanitizeHtml = require('sanitize-html') | ||
20 | const markdownItEmoji = require('markdown-it-emoji/light') | ||
21 | const MarkdownItClass = require('markdown-it') | ||
22 | const markdownIt = new MarkdownItClass('default', { linkify: true, breaks: true, html: true }) | ||
23 | |||
24 | markdownIt.enable(TEXT_WITH_HTML_RULES) | ||
25 | |||
26 | markdownIt.use(markdownItEmoji) | ||
27 | |||
28 | const 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 | ||
39 | const Email = require('email-templates') | 19 | const 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 | } |