HSB-439 feature: invite link with SMTP optional (#4078)

* feat: env variable added in infra-config for smtp enable status

* feat: event emitter added

* feat: added advance mailer configurations from infra config

* test: fix test cases

* feat: added query to see is smtp enabled or not

* feat: email auth provider disabled on smtp disable

* chore: restrict on update directly instead of dedicated mutation

* fix: feedback resolved

* chore: modify mailer module

* chore: error handle in mailer functions

* chore: removed unused imports

* chore: remove event-emit

* chore: update env example

* test: fix broken test cases

* chore: feedback resolved

* chore: isSMTPEnabled moved to infra config resolver

* fix: email can not reenable if smtp not enabled
This commit is contained in:
Mir Arif Hasan
2024-06-27 18:23:40 +06:00
committed by GitHub
parent b3e42bf7c3
commit fa2f73ee40
22 changed files with 13099 additions and 14968 deletions

View File

@@ -0,0 +1,58 @@
import { TransportType } from '@nestjs-modules/mailer/dist/interfaces/mailer-options.interface';
import {
MAILER_SMTP_PASSWORD_UNDEFINED,
MAILER_SMTP_URL_UNDEFINED,
MAILER_SMTP_USER_UNDEFINED,
} from 'src/errors';
import { throwErr } from 'src/utils';
function isSMTPCustomConfigsEnabled(value) {
return value === 'true';
}
export function getMailerAddressFrom(env, config): string {
return (
env.INFRA.MAILER_ADDRESS_FROM ??
config.get('MAILER_ADDRESS_FROM') ??
throwErr(MAILER_SMTP_URL_UNDEFINED)
);
}
export function getTransportOption(env, config): TransportType {
const useCustomConfigs = isSMTPCustomConfigsEnabled(
env.INFRA.MAILER_USE_CUSTOM_CONFIGS ??
config.get('MAILER_USE_CUSTOM_CONFIGS'),
);
if (!useCustomConfigs) {
console.log('Using simple mailer configuration');
return (
env.INFRA.MAILER_SMTP_URL ??
config.get('MAILER_SMTP_URL') ??
throwErr(MAILER_SMTP_URL_UNDEFINED)
);
} else {
console.log('Using advanced mailer configuration');
return {
host: env.INFRA.MAILER_SMTP_HOST ?? config.get('MAILER_SMTP_HOST'),
port: +env.INFRA.MAILER_SMTP_PORT ?? +config.get('MAILER_SMTP_PORT'),
secure:
!!env.INFRA.MAILER_SMTP_SECURE ?? !!config.get('MAILER_SMTP_SECURE'),
auth: {
user:
env.INFRA.MAILER_SMTP_USER ??
config.get('MAILER_SMTP_USER') ??
throwErr(MAILER_SMTP_USER_UNDEFINED),
pass:
env.INFRA.MAILER_SMTP_PASSWORD ??
config.get('MAILER_SMTP_PASSWORD') ??
throwErr(MAILER_SMTP_PASSWORD_UNDEFINED),
},
tls: {
rejectUnauthorized:
!!env.INFRA.MAILER_TLS_REJECT_UNAUTHORIZED ??
!!config.get('MAILER_TLS_REJECT_UNAUTHORIZED'),
},
};
}
}

View File

@@ -2,13 +2,9 @@ import { Global, Module } from '@nestjs/common';
import { MailerModule as NestMailerModule } from '@nestjs-modules/mailer';
import { HandlebarsAdapter } from '@nestjs-modules/mailer/dist/adapters/handlebars.adapter';
import { MailerService } from './mailer.service';
import { throwErr } from 'src/utils';
import {
MAILER_FROM_ADDRESS_UNDEFINED,
MAILER_SMTP_URL_UNDEFINED,
} from 'src/errors';
import { ConfigService } from '@nestjs/config';
import { loadInfraConfiguration } from 'src/infra-config/helper';
import { getMailerAddressFrom, getTransportOption } from './helper';
@Global()
@Module({
@@ -18,24 +14,31 @@ import { loadInfraConfiguration } from 'src/infra-config/helper';
})
export class MailerModule {
static async register() {
const config = new ConfigService();
const env = await loadInfraConfiguration();
let mailerSmtpUrl = env.INFRA.MAILER_SMTP_URL;
let mailerAddressFrom = env.INFRA.MAILER_ADDRESS_FROM;
if (!env.INFRA.MAILER_SMTP_URL || !env.INFRA.MAILER_ADDRESS_FROM) {
const config = new ConfigService();
mailerSmtpUrl = config.get('MAILER_SMTP_URL');
mailerAddressFrom = config.get('MAILER_ADDRESS_FROM');
// If mailer SMTP is DISABLED, return the module without any configuration (service, listener, etc.)
if (env.INFRA.MAILER_SMTP_ENABLE !== 'true') {
console.log('Mailer module is disabled');
return {
module: MailerModule,
};
}
// If mailer is ENABLED, return the module with configuration (service, etc.)
// Determine transport configuration based on custom config flag
let transportOption = getTransportOption(env, config);
// Get mailer address from environment or config
const mailerAddressFrom = getMailerAddressFrom(env, config);
return {
module: MailerModule,
imports: [
NestMailerModule.forRoot({
transport: mailerSmtpUrl ?? throwErr(MAILER_SMTP_URL_UNDEFINED),
transport: transportOption,
defaults: {
from: mailerAddressFrom ?? throwErr(MAILER_FROM_ADDRESS_UNDEFINED),
from: mailerAddressFrom,
},
template: {
dir: __dirname + '/templates',

View File

@@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common';
import { Injectable, Optional } from '@nestjs/common';
import {
AdminUserInvitationMailDescription,
MailDescription,
@@ -7,10 +7,14 @@ import {
import { throwErr } from 'src/utils';
import { EMAIL_FAILED } from 'src/errors';
import { MailerService as NestMailerService } from '@nestjs-modules/mailer';
import { ConfigService } from '@nestjs/config';
@Injectable()
export class MailerService {
constructor(private readonly nestMailerService: NestMailerService) {}
constructor(
@Optional() private readonly nestMailerService: NestMailerService,
private readonly configService: ConfigService,
) {}
/**
* Takes an input mail description and spits out the Email subject required for it
@@ -42,6 +46,8 @@ export class MailerService {
to: string,
mailDesc: MailDescription | UserMagicLinkMailDescription,
) {
if (this.configService.get('INFRA.MAILER_SMTP_ENABLE') !== 'true') return;
try {
await this.nestMailerService.sendMail({
to,
@@ -50,6 +56,7 @@ export class MailerService {
context: mailDesc.variables,
});
} catch (error) {
console.log('Error from sendEmail:', error);
return throwErr(EMAIL_FAILED);
}
}
@@ -64,6 +71,8 @@ export class MailerService {
to: string,
mailDesc: AdminUserInvitationMailDescription,
) {
if (this.configService.get('INFRA.MAILER_SMTP_ENABLE') !== 'true') return;
try {
const res = await this.nestMailerService.sendMail({
to,
@@ -73,6 +82,7 @@ export class MailerService {
});
return res;
} catch (error) {
console.log('Error from sendUserInvitationEmail:', error);
return throwErr(EMAIL_FAILED);
}
}