@@ -5,6 +5,7 @@ import { MailerConfig } from './mail.config';
55import { I18nContext } from 'nestjs-i18n' ;
66import { I18nTranslations } from '../i18n' ;
77import { MaybeType } from '~/common/types' ;
8+ import { MailData } from './mail-data.interface' ;
89
910@Injectable ( )
1011export class MailService {
@@ -136,79 +137,71 @@ export class MailService {
136137 } ) ;
137138 }
138139
139- // async sendForgotPasswordMail(
140- // { userEmail, firstName, otpCode }: ForgotPasswordEmailDTO,
141- // lang,
142- // transporter?: string,
143- // retryCount = 0,
144- // ) {
145- // const i18Context = new I18nContext(lang, this.i18n);
146- // if (retryCount > this.MAX_RETRIES) {
147- // this.logger.debug(`Send mail failed: too many retries`);
148- // return {
149- // message: 'Failed to send email',
150- // };
151- // }
152-
153- // const transporterName = this.resolveTransporter(transporter);
154- // const message = `Mail sent: ${userEmail}`;
155- // this.logger.debug(
156- // `Sending forgot password mail to ${userEmail} with transporter: ${transporterName}`,
157- // );
158- // return this.mailerService
159- // .sendMail({
160- // transporterName,
161- // to: userEmail,
162- // subject: i18Context.t('emailMessage.RESET_PASSWORD_SUBJECT'),
163- // template: 'forgot-password',
164- // context: {
165- // userEmail,
166- // firstName,
167- // otpCode,
168- // FORGOT_PASSWORD_TEXT_1: i18Context.t('emailMessage.FORGOT_PASSWORD_TEXT_1'),
169- // YOUR_OTP_CODE_TEXT: i18Context.t('emailMessage.YOUR_OTP_CODE_TEXT'),
170- // EXPIRED_TIME_OTP_TEXT: i18Context.t('emailMessage.EXPIRED_TIME_OTP_TEXT', {
171- // args: {
172- // time: '5',
173- // },
174- // }),
175- // INSTRUCTIONS: i18Context.t('emailMessage.INSTRUCTIONS'),
176- // INSTRUCTIONS_TEXT_ENTER_OTP_RESET_PASSWORD: i18Context.t(
177- // 'emailMessage.INSTRUCTIONS_TEXT_ENTER_OTP_RESET_PASSWORD',
178- // ),
179- // EMAIL_CREDIT: i18Context.t('emailMessage.EMAIL_CREDIT'),
180- // },
181- // attachments: [
182- // {
183- // filename: 'logo-red.png',
184- // path: join(this.TEMPLATES_PATH, 'images/logo-red.png'),
185- // cid: 'logo_red',
186- // },
187- // ],
188- // })
189- // .then(() => {
190- // this.logger.debug(`Mail sent: ${userEmail}`);
191- // return {
192- // message: message,
193- // };
194- // })
195- // .catch(async (error) => {
196- // this.logger.debug(`Send mail failed: ${error.message}`);
197- // transporter = this.getNextTransporter(transporterName);
198- // this.logger.debug(`Retry send mail with transporter: ${transporter}`);
199- // return await this.sendForgotPasswordMail(
200- // { userEmail, firstName, otpCode },
201- // lang,
202- // transporter,
203- // retryCount + 1,
204- // );
205- // })
206- // .finally(() => {
207- // return {
208- // message: message,
209- // };
210- // });
211- // }
140+ async forgotPassword (
141+ mailData : MailData < { hash : string ; tokenExpires : number } > ,
142+ retryData : {
143+ retryCount ?: number ;
144+ transporter ?: string ;
145+ } = { retryCount : 0 , transporter : SENDGRID_TRANSPORT } ,
146+ ) {
147+ const { retryCount = 0 , transporter = SENDGRID_TRANSPORT } = retryData ;
148+
149+ if ( retryCount > this . MAX_RETRIES ) {
150+ this . logger . debug ( `Send mail failed: too many retries` ) ;
151+ return {
152+ message : 'Failed to send email' ,
153+ } ;
154+ }
155+
156+ const i18n = I18nContext . current < I18nTranslations > ( ) ;
157+ let resetPasswordTitle : MaybeType < string > ;
158+ let text1 : MaybeType < string > ;
159+ let text2 : MaybeType < string > ;
160+ let text3 : MaybeType < string > ;
161+ let text4 : MaybeType < string > ;
162+
163+ if ( i18n ) {
164+ [ resetPasswordTitle , text1 , text2 , text3 , text4 ] = await Promise . all ( [
165+ i18n . t ( 'mail-context.RESET_PASSWORD.title' ) ,
166+ i18n . t ( 'mail-context.RESET_PASSWORD.text1' ) ,
167+ i18n . t ( 'mail-context.RESET_PASSWORD.text2' ) ,
168+ i18n . t ( 'mail-context.RESET_PASSWORD.text3' ) ,
169+ i18n . t ( 'mail-context.RESET_PASSWORD.text4' ) ,
170+ ] ) ;
171+ }
172+
173+ const url = new URL ( process . env . FE_DOMAIN + '/password-change' ) ;
174+ url . searchParams . set ( 'hash' , mailData . data . hash ) ;
175+ url . searchParams . set ( 'expires' , mailData . data . tokenExpires . toString ( ) ) ;
176+
177+ let transporterName = this . resolveTransporter ( transporter ) ;
178+ await this . mailerService
179+ . sendMail ( {
180+ to : mailData . to ,
181+ subject : resetPasswordTitle ,
182+ text : `${ url . toString ( ) } ${ resetPasswordTitle } ` ,
183+ template : 'reset-password' ,
184+ context : {
185+ title : resetPasswordTitle ,
186+ url : url . toString ( ) ,
187+ actionTitle : resetPasswordTitle ,
188+ app_name : 'TechCell.cloud' ,
189+ text1,
190+ text2,
191+ text3,
192+ text4,
193+ } ,
194+ } )
195+ . catch ( async ( error ) => {
196+ this . logger . debug ( `Send mail failed: ${ error . message } ` ) ;
197+ transporterName = this . getNextTransporter ( transporterName ) ;
198+ this . logger . debug ( `Retry send mail with transporter: ${ transporterName } ` ) ;
199+ await this . forgotPassword ( mailData , {
200+ transporter : transporterName ,
201+ retryCount : retryCount + 1 ,
202+ } ) ;
203+ } ) ;
204+ }
212205
213206 private resolveTransporter ( transporter = SENDGRID_TRANSPORT ) {
214207 if ( ! this . TRANSPORTERS . includes ( transporter ) ) {
0 commit comments