Hướng dẫn triển khai chức năng quên mật khẩu trong NestJS 9 sử dụng Nodemailer
Tóm tắt
Bài viết này sẽ hướng dẫn bạn cách xây dựng chức năng quên mật khẩu trong ứng dụng NestJS, sử dụng Nodemailer để gửi email và Handlebars để tạo template email. Chúng ta sẽ từng bước thực hiện từ cài đặt đến triển khai chi tiết.
Mục tiêu
- Cài đặt và cấu hình Nodemailer và Handlebars.
- Tạo dịch vụ gửi email cho ứng dụng.
- Tạo module và service để quản lý nhiều loại email.
- Triển khai chức năng quên mật khẩu trong Auth Controller.
- Tạo template email sử dụng Handlebars.
1. Cài đặt các thư viện cần thiết
Đầu tiên, bạn cần cài đặt hai thư viện Nodemailer và Handlebars. Mở terminal và chạy các lệnh sau:
npm install nodemailer
npm install handlebars
2. Cấu hình Nodemailer
Tiếp theo, bạn cần cấu hình Nodemailer để gửi email. Tạo một file mailer.service.ts
với nội dung sau:
typescript
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import nodemailer from 'nodemailer';
import Handlebars from 'handlebars';
import fs from 'node:fs/promises';
@Injectable()
export class MailerService {
private readonly transporter: nodemailer.Transporter;
constructor(private readonly configService: ConfigService) {
this.transporter = nodemailer.createTransport({
host: configService.get<string>('mailer.host', { infer: true }),
port: configService.get<number>('mailer.port', { infer: true }),
secure: configService.get<boolean>('mailer.secure', { infer: true }),
auth: {
user: configService.get<string>('mailer.user', { infer: true }),
pass: configService.get<string>('mailer.password', { infer: true }),
},
debug: true,
});
}
async sendMail({
templatePath,
context,
...mailOptions
}: nodemailer.SendMailOptions & {
templatePath: string;
context: Record<string, unknown>;
}): Promise<void> {
let html: string | undefined;
if (templatePath) {
const template = await fs.readFile(templatePath, 'utf-8');
html = Handlebars.compile(template, { strict: true })(context);
}
await this.transporter.sendMail({
...mailOptions,
from: mailOptions.from
? mailOptions.from
: `"${this.configService.get<string>('mailer.defaultName', { infer: true })}" <${this.configService.get<string>('mailer.defaultEmail', { infer: true })}>`,
html: mailOptions.html ? mailOptions.html : html,
});
}
}
Giải thích từng phần
- nodemailer.createTransport: Dùng để tạo một transporter nhằm gửi email.
- sendMail: Hàm này kết hợp Handlebars để biên dịch template email và gửi đi.
3. Cấu hình file .env
Thêm các thông tin cấu hình cần thiết vào file .env
của bạn:
MAILER_HOST=smtp.gmail.com
MAILER_PORT=587
MAILER_USER=your-email@gmail.com
MAILER_PASSWORD=your-email-password
MAILER_SECURE=false
MAILER_DEFAULT_NAME=Your Name
MAILER_DEFAULT_EMAIL=your-email@gmail.com
4. Tạo module Mailer
Tiếp theo, bạn tạo một module để chứa MailerService. Tạo file mailer.module.ts
và điền nội dung phù hợp.
5. Import MailerModule vào AppModule
Bạn cần import MailerModule vào AppModule để có thể sử dụng nó trong toàn ứng dụng:
typescript
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { MailerModule } from './mailer/mailer.module';
import { AuthModule } from './auth/auth.module';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
}),
MailerModule,
AuthModule,
],
controllers: [],
providers: [],
})
export class AppModule {}
6. Tạo chức năng quên mật khẩu trong Auth Controller
Tiếp theo, tạo file auth.controller.ts
với nội dung sau:
typescript
import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
import { ForgotPasswordDto } from './dto/forgot-password.dto';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('forgot-password')
async forgotPassword(@Body() forgotPasswordDto: ForgotPasswordDto) {
return this.authService.forgotPassword(forgotPasswordDto);
}
}
Sau đó, tạo service để xử lý chức năng quên mật khẩu. Tạo file auth.service.ts
với nội dung như sau:
typescript
import { Injectable } from '@nestjs/common';
import { MailsService } from 'src/mails/mails.service';
import { ForgotPasswordDto } from './dto/forgot-password.dto';
@Injectable()
export class AuthService {
constructor(private readonly mailsService: MailsService) {}
async forgotPassword(forgotPasswordDto: ForgotPasswordDto) {
const { email, userName, token } = forgotPasswordDto;
await this.mailsService.forgotPassword({
to: email,
data: {
token,
user_name: userName,
},
});
return { message: 'Email đặt lại mật khẩu đã được gửi.' };
}
}
7. Tạo module MailsService
Bạn cần tạo một module để quản lý và gửi các loại email như quên mật khẩu, xác thực, v.v. Tạo file mails.service.ts
với nội dung như sau:
typescript
import { Injectable } from '@nestjs/common';
import path from 'path';
import { ConfigService } from '@nestjs/config';
import { MailerService } from 'src/mailer/mailer.service';
@Injectable()
export class MailsService {
constructor(
private readonly mailerService: MailerService,
private readonly configService: ConfigService,
) {}
async forgotPassword(mailData: {
to: string;
data: {
token: string;
user_name: string;
};
}): Promise<void> {
await this.mailerService.sendMail({
to: mailData.to,
subject: 'Đặt lại mật khẩu',
templatePath: path.join(
this.configService.get<string>('mailer.workingDirectory', {
infer: true,
}),
'src',
'mails',
'templates',
'reset-password.hbs',
),
context: {
username: mailData.data.user_name,
resetLink: `${this.configService.get<string>('app.clientURL')}/reset-password?token=${mailData.data.token}`,
},
});
}
}
8. Kết luận
Qua bài viết này, bạn đã học cách triển khai chức năng quên mật khẩu trong ứng dụng NestJS bằng cách sử dụng Nodemailer và Handlebars. Chức năng này sẽ tự động gửi email đến người dùng với liên kết để họ có thể đặt lại mật khẩu của mình. Bạn có thể tùy chỉnh thêm nội dung và giao diện email theo nhu cầu của dự án. Chúc bạn thành công trong việc triển khai chức năng này!
source: viblo