Created
October 4, 2022 14:28
-
-
Save voidnerd/8818b25e05efa0255e8f5d89beac1200 to your computer and use it in GitHub Desktop.
Revisions
-
voidnerd created this gist
Oct 4, 2022 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,242 @@ import nodemailer from 'nodemailer' import ViewService from './view' // https://gist.github.com/ndiecodes/6e964e716a2b5b2aa22438912da2b3f3 import Mailgun from 'mailgun.js' import FormData from 'form-data' import { MailgunMessageData } from 'mailgun.js/interfaces/Messages' interface LooseObject { [key: string]: any } interface Attachment { filename: string content?: Buffer } interface _Attachment { filename: string content?: Buffer data?: Buffer } /** Start Mail Helper * MailDrivers: smtp, mailgun */ export default class Mail { public SUBJECT!: string public FROM: string | null = process.env.MAIL_FROM_ADDRESS || null public DATA: LooseObject | null = null public TO: string | undefined = '' public CC: string | undefined = undefined public BCC: string | undefined = undefined public ATTACHMENTS: _Attachment[] = [] public TEXT: string | undefined = undefined public TEMPLATE!: string /** * * @param {String} subject * @returns {Mail} */ subject(subject: string) { this.SUBJECT = subject return this } /** * * @param {String|Array} from * @returns {Mail} */ from(from: string) { this.FROM = from return this } /** * * @param {String|Array} to * @returns {Mail} */ to(to: string) { this.TO = to return this } /** * * @param {String|Array} cc * @returns {Mail} */ cc(cc: string) { this.CC = cc return this } /** * * @param {String|Array} bcc * @returns {Mail} */ bcc(bcc: string) { this.BCC = bcc return this } /** * Attach Single File using Buffer * @param {Array} attachments * @returns {Mail} */ attachFile(attachment: Attachment) { if (process.env.MAIL_DRIVER === 'mailgun') { this._attachMailgunFile(attachment) } else { this.ATTACHMENTS.push(attachment) } return this } /** * Format attachment object for mailgun API * @param attachment * @returns */ private _attachMailgunFile(attachment: Attachment) { return this.ATTACHMENTS.push({ filename: attachment.filename, data: attachment.content, }) } /** * Attach multiple files * @param attachments * @returns */ attachFiles(attachments: Attachment[]) { if (process.env.MAIL_DRIVER === 'mailgun') { this._attachMailgunFiles(attachments) } else { this.ATTACHMENTS = attachments } return this } /** * Format attachment array for mailgun API * @param attachment * @returns */ private _attachMailgunFiles(attachments: Attachment[]): _Attachment[] { this.ATTACHMENTS = attachments.map((attachment) => { return { filename: attachment.filename, data: attachment.content, } }) return this.ATTACHMENTS } /** * * @param {String|Array} template * @returns {Mail} */ template(template: string) { this.TEMPLATE = template return this } /** * * @param {String} text * @returns {Mail} */ text(text: string | undefined) { this.TEXT = text return this } /** * This object(data) will be passed the email view/renderer * @param {Object} data * @returns {Mail} */ data(data: LooseObject) { this.DATA = data return this } /** Validate mail driver message params */ validate() { if (!this.SUBJECT) { throw new Error('Subject Required!') } if (!this.FROM) { throw new Error('From Address Required!') } if (!this.TO) { throw new Error('TO Address Required!') } if (!this.TEMPLATE) { throw new Error('Path to Template File Required!') } } private async mailThroughSMTP(messageParams: MailgunMessageData) { const smtp = nodemailer.createTransport({ host: process.env.MAIL_HOST, port: Number(process.env.MAIL_PORT), secure: false, auth: { user: process.env.MAIL_USERNAME, pass: process.env.MAIL_PASSWORD, }, }) return smtp.sendMail(messageParams) } private async mailThroughMailgun(messageParams: MailgunMessageData) { const mailgun = new Mailgun(FormData) const mg = mailgun.client({ username: 'api', key: process.env.MAILGUN_API_KEY || '', }) return mg.messages.create( process.env.MAILGUN_DOMAIN || '', messageParams ) } /** * * @returns {Promise} */ async send() { this.validate() const html = await new ViewService(this.TEMPLATE, this.DATA).getHtml() const mailOptions: MailgunMessageData = { from: `"${process.env.MAIL_FROM_NAME}" <${this.FROM}>`, to: this.TO, subject: this.SUBJECT, cc: this.CC, bcc: this.BCC, attachments: this.ATTACHMENTS, text: this.TEXT, html: html, } if (process.env.MAIL_DRIVER === 'mailgun') { return this.mailThroughMailgun(mailOptions) } return this.mailThroughSMTP(mailOptions) } }