diff options
author | Puyodead1 <puyodead@proton.me> | 2023-01-21 13:53:26 -0500 |
---|---|---|
committer | Puyodead1 <puyodead@protonmail.com> | 2023-02-23 22:38:02 -0500 |
commit | bf55ebc81fa8d3cc4aa4e6fd3735ff0ee659505a (patch) | |
tree | aaa4f9ed991139f03c71074e04aba7e79e428b55 /src/util/util/Email.ts | |
parent | Add Mailgun transport (diff) | |
download | server-bf55ebc81fa8d3cc4aa4e6fd3735ff0ee659505a.tar.xz |
Add mailjet transport
Diffstat (limited to '')
-rw-r--r-- | src/util/util/Email.ts | 163 |
1 files changed, 108 insertions, 55 deletions
diff --git a/src/util/util/Email.ts b/src/util/util/Email.ts index b8019cbd..8899b3c2 100644 --- a/src/util/util/Email.ts +++ b/src/util/util/Email.ts @@ -52,45 +52,20 @@ export function adjustEmail(email?: string): string | undefined { // return email; } -export const Email: { - transporter: Transporter | null; - init: () => Promise<void>; - initSMTP: () => Promise<void>; - initMailgun: () => Promise<void>; - generateVerificationLink: (id: string, email: string) => Promise<string>; - sendVerificationEmail: (user: User, email: string) => Promise<any>; - doReplacements: ( - template: string, - user: User, - emailVerificationUrl?: string, - passwordResetUrl?: string, - ipInfo?: { - ip: string; - city: string; - region: string; - country_name: string; - }, - ) => string; -} = { - transporter: null, - init: async function () { - const { provider } = Config.get().email; - if (!provider) return; - - if (provider === "smtp") await this.initSMTP(); - else if (provider === "mailgun") await this.initMailgun(); - else throw new Error(`Unknown email provider: ${provider}`); - }, - initSMTP: async function () { +const transporters = { + smtp: async function () { + // get configuration const { host, port, secure, username, password } = Config.get().email.smtp; + + // ensure all required configuration values are set if (!host || !port || !secure || !username || !password) return console.error( "[Email] SMTP has not been configured correctly.", ); - console.log(`[Email] Initializing SMTP transport: ${host}`); - this.transporter = nodemailer.createTransport({ + // construct the transporter + const transporter = nodemailer.createTransport({ host, port, secure, @@ -100,41 +75,117 @@ export const Email: { }, }); - await this.transporter.verify((error, _) => { - if (error) { - console.error(`[Email] SMTP error: ${error}`); - this.transporter?.close(); - this.transporter = null; - return; - } - console.log(`[Email] Ready`); + // verify connection configuration + const verified = await transporter.verify().catch((err) => { + console.error("[Email] SMTP verification failed:", err); + return; }); + + // if verification failed, return void and don't set transporter + if (!verified) return; + + return transporter; }, - initMailgun: async function () { + mailgun: async function () { + // get configuration const { apiKey, domain } = Config.get().email.mailgun; + + // ensure all required configuration values are set if (!apiKey || !domain) return console.error( "[Email] Mailgun has not been configured correctly.", ); + let mg; + try { + // try to import the transporter package + mg = require("nodemailer-mailgun-transport"); + } catch { + // if the package is not installed, log an error and return void so we don't set the transporter + console.error( + "[Email] Mailgun transport is not installed. Please run `npm install nodemailer-mailgun-transport --save-optional` to install it.", + ); + return; + } + + // create the transporter configuration object + const auth = { + auth: { + api_key: apiKey, + domain: domain, + }, + }; + + // create the transporter and return it + return nodemailer.createTransport(mg(auth)); + }, + mailjet: async function () { + // get configuration + const { apiKey, apiSecret } = Config.get().email.mailjet; + + // ensure all required configuration values are set + if (!apiKey || !apiSecret) + return console.error( + "[Email] Mailjet has not been configured correctly.", + ); + + let mj; try { - const mg = require("nodemailer-mailgun-transport"); - const auth = { - auth: { - api_key: apiKey, - domain: domain, - }, - }; - - console.log(`[Email] Initializing Mailgun transport...`); - this.transporter = nodemailer.createTransport(mg(auth)); - console.log(`[Email] Ready`); + // try to import the transporter package + mj = require("nodemailer-mailjet-transport"); } catch { + // if the package is not installed, log an error and return void so we don't set the transporter console.error( - "[Email] Mailgun transport is not installed. Please run `npm install nodemailer-mailgun-transport --save` to install it.", + "[Email] Mailjet transport is not installed. Please run `npm install nodemailer-mailjet-transport --save-optional` to install it.", ); return; } + + // create the transporter configuration object + const auth = { + auth: { + apiKey: apiKey, + apiSecret: apiSecret, + }, + }; + + // create the transporter and return it + return nodemailer.createTransport(mj(auth)); + }, +}; + +export const Email: { + transporter: Transporter | null; + init: () => Promise<void>; + generateVerificationLink: (id: string, email: string) => Promise<string>; + sendVerificationEmail: (user: User, email: string) => Promise<any>; + doReplacements: ( + template: string, + user: User, + emailVerificationUrl?: string, + passwordResetUrl?: string, + ipInfo?: { + ip: string; + city: string; + region: string; + country_name: string; + }, + ) => string; +} = { + transporter: null, + init: async function () { + const { provider } = Config.get().email; + if (!provider) return; + + const transporterFn = + transporters[provider as keyof typeof transporters]; + if (!transporterFn) + return console.error(`[Email] Invalid provider: ${provider}`); + console.log(`[Email] Initializing ${provider} transport...`); + const transporter = await transporterFn(); + if (!transporter) return; + this.transporter = transporter; + console.log(`[Email] ${provider} transport initialized.`); }, /** * Replaces all placeholders in an email template with the correct values @@ -214,6 +265,7 @@ export const Email: { user.id, email, ); + // load the email template const rawTemplate = fs.readFileSync( path.join( @@ -223,13 +275,14 @@ export const Email: { ), { encoding: "utf-8" }, ); + // replace email template placeholders const html = this.doReplacements(rawTemplate, user, verificationLink); // extract the title from the email template to use as the email subject const subject = html.match(/<title>(.*)<\/title>/)?.[1] || ""; - // // construct the email + // construct the email const message = { from: Config.get().general.correspondenceEmail || "noreply@localhost", @@ -238,7 +291,7 @@ export const Email: { html, }; - // // send the email + // send the email return this.transporter.sendMail(message); }, }; |