317cec70689693aba2b344fd4d0b257df203e7f4
[oweals/peertube.git] / server / lib / emailer.ts
1 import { createTransport, Transporter } from 'nodemailer'
2 import { isTestInstance } from '../helpers/core-utils'
3 import { logger } from '../helpers/logger'
4 import { CONFIG } from '../initializers'
5 import { JobQueue } from './job-queue'
6 import { EmailPayload } from './job-queue/handlers/email'
7 import { readFileSync } from 'fs'
8
9 class Emailer {
10
11   private static instance: Emailer
12   private initialized = false
13   private transporter: Transporter
14
15   private constructor () {}
16
17   init () {
18     // Already initialized
19     if (this.initialized === true) return
20     this.initialized = true
21
22     if (CONFIG.SMTP.HOSTNAME && CONFIG.SMTP.PORT) {
23       logger.info('Using %s:%s as SMTP server.', CONFIG.SMTP.HOSTNAME, CONFIG.SMTP.PORT)
24
25       let tls
26       if (CONFIG.SMTP.CA_FILE) {
27         tls = {
28           ca: [ readFileSync(CONFIG.SMTP.CA_FILE) ]
29         }
30       }
31
32       let auth
33       if (CONFIG.SMTP.USERNAME && CONFIG.SMTP.PASSWORD) {
34         auth = {
35           user: CONFIG.SMTP.USERNAME,
36           pass: CONFIG.SMTP.PASSWORD
37         }
38       }
39
40       this.transporter = createTransport({
41         host: CONFIG.SMTP.HOSTNAME,
42         port: CONFIG.SMTP.PORT,
43         secure: CONFIG.SMTP.TLS,
44         ignoreTLS: isTestInstance(),
45         tls,
46         auth
47       })
48     } else {
49       if (!isTestInstance()) {
50         logger.error('Cannot use SMTP server because of lack of configuration. PeerTube will not be able to send mails!')
51       }
52     }
53   }
54
55   async checkConnectionOrDie () {
56     if (!this.transporter) return
57
58     try {
59       const success = await this.transporter.verify()
60       if (success !== true) this.dieOnConnectionFailure()
61
62       logger.info('Successfully connected to SMTP server.')
63     } catch (err) {
64       this.dieOnConnectionFailure(err)
65     }
66   }
67
68   addForgetPasswordEmailJob (to: string, resetPasswordUrl: string) {
69     const text = `Hi dear user,\n\n` +
70       `It seems you forgot your password on ${CONFIG.WEBSERVER.HOST}! ` +
71       `Please follow this link to reset it: ${resetPasswordUrl}.\n\n` +
72       `If you are not the person who initiated this request, please ignore this email.\n\n` +
73       `Cheers,\n` +
74       `PeerTube.`
75
76     const emailPayload: EmailPayload = {
77       to: [ to ],
78       subject: 'Reset your PeerTube password',
79       text
80     }
81
82     return JobQueue.Instance.createJob({ type: 'email', payload: emailPayload })
83   }
84
85   sendMail (to: string[], subject: string, text: string) {
86     if (!this.transporter) {
87       throw new Error('Cannot send mail because SMTP is not configured.')
88     }
89
90     return this.transporter.sendMail({
91       from: CONFIG.SMTP.FROM_ADDRESS,
92       to: to.join(','),
93       subject,
94       text
95     })
96   }
97
98   private dieOnConnectionFailure (err?: Error) {
99     logger.error('Failed to connect to SMTP %s:%d.', CONFIG.SMTP.HOSTNAME, CONFIG.SMTP.PORT, err)
100     process.exit(-1)
101   }
102
103   static get Instance () {
104     return this.instance || (this.instance = new this())
105   }
106 }
107
108 // ---------------------------------------------------------------------------
109
110 export {
111   Emailer
112 }