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:
58
packages/hoppscotch-backend/src/mailer/helper.ts
Normal file
58
packages/hoppscotch-backend/src/mailer/helper.ts
Normal 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'),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user