forked from docmost/docmost
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Nest email module with smtp, postmark and console log drivers * react-email package
- Loading branch information
1 parent
48be0c2
commit 4c573b9
Showing
26 changed files
with
2,763 additions
and
524 deletions.
There are no files selected for viewing
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,3 +21,17 @@ AWS_S3_BUCKET= | |
AWS_S3_ENDPOINT= | ||
AWS_S3_URL= | ||
AWS_S3_USE_PATH_STYLE_ENDPOINT=false | ||
|
||
|
||
# EMAIL drivers: smtp / postmark / log | ||
MAIL_DRIVER=smtp | ||
MAIL_HOST=127.0.0.1 | ||
MAIL_PORT=2525 | ||
MAIL_USERNAME= | ||
MAIL_PASSWORD= | ||
MAIL_FROM_ADDRESS=[email protected] | ||
MAIL_FROM_NAME= | ||
|
||
# for postmark driver | ||
POSTMARK_TOKEN= | ||
|
This file contains 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 characters
This file contains 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 characters
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { SmtpDriver } from './smtp.driver'; | ||
export { PostmarkDriver } from './postmark.driver'; | ||
export { LogDriver } from './log.driver'; |
5 changes: 5 additions & 0 deletions
5
apps/server/src/integrations/mail/drivers/interfaces/mail-driver.interface.ts
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import { MailMessage } from '../../interfaces/mail.message'; | ||
|
||
export interface MailDriver { | ||
sendMail(message: MailMessage): Promise<void>; | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { MailDriver } from './interfaces/mail-driver.interface'; | ||
import { Logger } from '@nestjs/common'; | ||
import { MailMessage } from '../interfaces/mail.message'; | ||
import { mailLogName } from '../mail.utils'; | ||
|
||
export class LogDriver implements MailDriver { | ||
private readonly logger = new Logger(mailLogName(LogDriver.name)); | ||
|
||
async sendMail(message: MailMessage): Promise<void> { | ||
const mailLog = { | ||
to: message.to, | ||
subject: message.subject, | ||
text: message.text, | ||
}; | ||
|
||
this.logger.log(`Logged mail: ${JSON.stringify(mailLog)}`); | ||
} | ||
} |
30 changes: 30 additions & 0 deletions
30
apps/server/src/integrations/mail/drivers/postmark.driver.ts
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { MailDriver } from './interfaces/mail-driver.interface'; | ||
import { PostmarkConfig } from '../interfaces'; | ||
import { ServerClient } from 'postmark'; | ||
import { MailMessage } from '../interfaces/mail.message'; | ||
import { Logger } from '@nestjs/common'; | ||
import { mailLogName } from '../mail.utils'; | ||
|
||
export class PostmarkDriver implements MailDriver { | ||
private readonly logger = new Logger(mailLogName(PostmarkDriver.name)); | ||
private readonly postmarkClient: ServerClient; | ||
|
||
constructor(config: PostmarkConfig) { | ||
this.postmarkClient = new ServerClient(config.postmarkToken); | ||
} | ||
|
||
async sendMail(message: MailMessage): Promise<void> { | ||
try { | ||
await this.postmarkClient.sendEmail({ | ||
From: message.from, | ||
To: message.to, | ||
Subject: message.subject, | ||
TextBody: message.text, | ||
HtmlBody: message.html, | ||
}); | ||
this.logger.debug(`Sent mail to ${message.to}`); | ||
} catch (err) { | ||
this.logger.warn(`Failed to send mail to ${message.to}: ${err}`); | ||
} | ||
} | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { MailDriver } from './interfaces/mail-driver.interface'; | ||
import { SMTPConfig } from '../interfaces'; | ||
import { Transporter } from 'nodemailer'; | ||
import * as nodemailer from 'nodemailer'; | ||
import { MailMessage } from '../interfaces/mail.message'; | ||
import { Logger } from '@nestjs/common'; | ||
import { mailLogName } from '../mail.utils'; | ||
|
||
export class SmtpDriver implements MailDriver { | ||
private readonly logger = new Logger(mailLogName(SmtpDriver.name)); | ||
private readonly transporter: Transporter; | ||
|
||
constructor(config: SMTPConfig) { | ||
this.transporter = nodemailer.createTransport(config); | ||
} | ||
|
||
async sendMail(message: MailMessage): Promise<void> { | ||
try { | ||
await this.transporter.sendMail({ | ||
from: message.from, | ||
to: message.to, | ||
subject: message.subject, | ||
text: message.text, | ||
html: message.html, | ||
}); | ||
|
||
this.logger.debug(`Sent mail to ${message.to}`); | ||
} catch (err) { | ||
this.logger.warn(`Failed to send mail to ${message.to}: ${err}`); | ||
} | ||
} | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './mail.interface'; |
30 changes: 30 additions & 0 deletions
30
apps/server/src/integrations/mail/interfaces/mail.interface.ts
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import SMTPTransport from 'nodemailer/lib/smtp-transport'; | ||
|
||
export enum MailOption { | ||
SMTP = 'smtp', | ||
Postmark = 'postmark', | ||
Log = 'log', | ||
} | ||
|
||
export type MailConfig = | ||
| { driver: MailOption.SMTP; config: SMTPConfig } | ||
| { driver: MailOption.Postmark; config: PostmarkConfig } | ||
| { driver: MailOption.Log; config: LogConfig }; | ||
|
||
export interface SMTPConfig extends SMTPTransport.Options {} | ||
export interface PostmarkConfig { | ||
postmarkToken: string; | ||
} | ||
export interface LogConfig {} | ||
|
||
export interface MailOptions { | ||
mail: MailConfig; | ||
} | ||
|
||
export interface MailOptionsFactory { | ||
createMailOptions(): Promise<MailConfig> | MailConfig; | ||
} | ||
|
||
export interface MailModuleOptions { | ||
imports?: any[]; | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export interface MailMessage { | ||
from: string; | ||
to: string; | ||
subject: string; | ||
text?: string; | ||
html?: string; | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const MAIL_DRIVER_TOKEN = 'MAIL_DRIVER_TOKEN'; | ||
export const MAIL_CONFIG_TOKEN = 'MAIL_CONFIG_TOKEN'; |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { DynamicModule, Global, Module } from '@nestjs/common'; | ||
import { | ||
mailDriverConfigProvider, | ||
mailDriverProvider, | ||
} from './providers/mail.provider'; | ||
import { MailModuleOptions } from './interfaces'; | ||
import { MailService } from './mail.service'; | ||
|
||
@Global() | ||
@Module({}) | ||
export class MailModule { | ||
static forRootAsync(options: MailModuleOptions): DynamicModule { | ||
return { | ||
module: MailModule, | ||
imports: options.imports || [], | ||
providers: [mailDriverConfigProvider, mailDriverProvider, MailService], | ||
exports: [MailService], | ||
}; | ||
} | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Inject, Injectable } from '@nestjs/common'; | ||
import { MAIL_DRIVER_TOKEN } from './mail.constants'; | ||
import { MailDriver } from './drivers/interfaces/mail-driver.interface'; | ||
import { MailMessage } from './interfaces/mail.message'; | ||
import { EnvironmentService } from '../environment/environment.service'; | ||
|
||
@Injectable() | ||
export class MailService { | ||
constructor( | ||
@Inject(MAIL_DRIVER_TOKEN) private mailDriver: MailDriver, | ||
private readonly environmentService: EnvironmentService, | ||
) {} | ||
|
||
async sendMail(message: Omit<MailMessage, 'from'>): Promise<void> { | ||
const sender = `${this.environmentService.getMailFromName()} <${this.environmentService.getMailFromAddress()}> `; | ||
await this.mailDriver.sendMail({ from: sender, ...message }); | ||
} | ||
} |
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export const mailLogName = (driverName: string) => { | ||
return `Mail::${driverName}`; | ||
}; |
67 changes: 67 additions & 0 deletions
67
apps/server/src/integrations/mail/providers/mail.provider.ts
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
import { EnvironmentService } from '../../environment/environment.service'; | ||
import { MailOption, PostmarkConfig, SMTPConfig } from '../interfaces'; | ||
import { SmtpDriver, PostmarkDriver, LogDriver } from '../drivers'; | ||
import { MailDriver } from '../drivers/interfaces/mail-driver.interface'; | ||
import { MailConfig } from '../interfaces'; | ||
import { MAIL_CONFIG_TOKEN, MAIL_DRIVER_TOKEN } from '../mail.constants'; | ||
import SMTPTransport from 'nodemailer/lib/smtp-transport'; | ||
|
||
function createMailDriver(mail: MailConfig): MailDriver { | ||
switch (mail.driver) { | ||
case MailOption.SMTP: | ||
return new SmtpDriver(mail.config as SMTPConfig); | ||
case MailOption.Postmark: | ||
return new PostmarkDriver(mail.config as PostmarkConfig); | ||
case MailOption.Log: | ||
return new LogDriver(); | ||
default: | ||
throw new Error(`Unknown mail driver`); | ||
} | ||
} | ||
|
||
export const mailDriverConfigProvider = { | ||
provide: MAIL_CONFIG_TOKEN, | ||
useFactory: async (environmentService: EnvironmentService) => { | ||
const driver = environmentService.getMailDriver().toLocaleLowerCase(); | ||
|
||
if (driver === MailOption.SMTP) { | ||
return { | ||
driver, | ||
config: { | ||
host: environmentService.getMailHost(), | ||
port: environmentService.getMailPort(), | ||
connectionTimeout: 30 * 1000, // 30 seconds | ||
auth: { | ||
user: environmentService.getMailUsername(), | ||
pass: environmentService.getMailPassword(), | ||
}, | ||
} as SMTPTransport.Options, | ||
}; | ||
} | ||
|
||
if (driver === MailOption.Postmark) { | ||
return { | ||
driver, | ||
config: { | ||
postmarkToken: environmentService.getPostmarkToken(), | ||
} as PostmarkConfig, | ||
}; | ||
} | ||
|
||
if (driver === MailOption.Log) { | ||
return { | ||
driver, | ||
}; | ||
} | ||
|
||
throw new Error(`Unknown mail driver: ${driver}`); | ||
}, | ||
|
||
inject: [EnvironmentService], | ||
}; | ||
|
||
export const mailDriverProvider = { | ||
provide: MAIL_DRIVER_TOKEN, | ||
useFactory: (config: MailConfig) => createMailDriver(config), | ||
inject: [MAIL_CONFIG_TOKEN], | ||
}; |
This file contains 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 characters
This file contains 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 characters
This file contains 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 characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
.env | ||
# compiled output | ||
/dist | ||
/node_modules | ||
|
||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
pnpm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
lerna-debug.log* | ||
|
||
# OS | ||
.DS_Store |
Oops, something went wrong.