paint-brush
Cách gửi xác minh email trong Next.js 14 với NextAuth.js, gửi lại và phản hồi emailtừ tác giả@ljaviertovar
4,398 lượt đọc
4,398 lượt đọc

Cách gửi xác minh email trong Next.js 14 với NextAuth.js, gửi lại và phản hồi email

từ tác giả L Javier Tovar12m2024/04/02
Read on Terminal Reader

dài quá đọc không nổi

Sau khi khám phá cách triển khai hệ thống xác thực trong Next.js 14 với NextAuth.js(Auth.js) trong phần đầu tiên của blog này, điều quan trọng là phải thực hiện bước tiếp theo để đảm bảo tính hợp lệ của thông tin người dùng: xác thực email. Quá trình này không chỉ là một bước bổ sung trong bảo mật ứng dụng của chúng tôi mà còn là một thành phần thiết yếu để đảm bảo rằng các tương tác giữa người dùng và nền tảng là hợp pháp và an toàn. Trong phần thứ hai này, chúng tôi sẽ tập trung vào việc tích hợp xác thực email bằng cách gửi email, sử dụng Resend để gửi email và React Email để tạo các mẫu email hấp dẫn và đầy đủ chức năng.
featured image - Cách gửi xác minh email trong Next.js 14 với NextAuth.js, gửi lại và phản hồi email
L Javier Tovar HackerNoon profile picture
0-item
1-item

Sau khi khám phá cách triển khai hệ thống xác thực trong Next.js 14 với NextAuth.js(Auth.js) trong phần đầu tiên của blog này, điều quan trọng là phải thực hiện bước tiếp theo để đảm bảo tính hợp lệ của thông tin người dùng: xác thực email.


Quá trình này không chỉ là một bước bổ sung trong bảo mật ứng dụng của chúng tôi mà còn là một thành phần thiết yếu để đảm bảo rằng các tương tác giữa người dùng và nền tảng là hợp pháp và an toàn.


Trong phần thứ hai này, chúng tôi sẽ tập trung vào việc tích hợp xác thực email bằng cách gửi email, sử dụng Resend để gửi email và React Email để tạo các mẫu email hấp dẫn và đầy đủ chức năng.

Cấu hình ban đầu

Đảm bảo rằng dự án của bạn đã triển khai hệ thống xác thực được mô tả trong phần đầu tiên của blog. Điều này bao gồm việc cấu hình Next.js 14 và NextAuth đúng cách.


Tích hợp email gửi lại và Ract trong Next.js

Đang cài đặt

  1. Cài đặt các phụ thuộc cần thiết trong dự án. Lần này chúng tôi sẽ sử dụng pnpm bạn có thể sử dụng trình quản lý gói mà bạn chọn.


 pnpm add resend react-email @react-email/components




2. Tạo cấu trúc sau cho dự án:


 ... ├── emails/ │ └── verification-template.tsx ... ├── src/ │ ├── actions/ │ │ ├── email-actions.tsx │ │ └── auth-actions.tsx │ ├── app/ │ │ ... │ │ ├── (primary)/ │ │ │ ├── auth/ │ │ │ │ └── verify-email/ │ │ │ │ └── page.tsx │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ │ │ ... │ ├── components/ │ │ └── auth/ │ │ ├── signin-form.tsx │ │ ├── signup-form.tsx │ │ ... │ ... │ ├── utils.ts │ ... ... ├── .env ...


Tạo mẫu email bằng email phản ứng

React Email cho phép bạn tạo các mẫu email bằng JSX, điều này tạo điều kiện thuận lợi cho việc tạo các email hấp dẫn và nhất quán với thương hiệu của bạn.


Hãy tạo một mẫu email cơ bản dưới dạng thành phần React. Trong trường hợp này, chúng tôi sẽ tạo mẫu sẽ được gửi để người dùng xác nhận email của họ.


emails/verification-template.tsx :

 // Import React and necessary components from @react-email/components import * as React from 'react'; import { Body, Button, Container, Head, Hr, Html, Img, Preview, Section, Text } from '@react-email/components'; import { getBaseUrl } from '@/utils'; // Obtain the base URL using the imported function const baseUrl = getBaseUrl(); // Define the properties expected by the VerificationTemplate component interface VerificationTemplateProps { username: string; emailVerificationToken: string; } // Define the VerificationTemplate component that takes the defined properties export const VerificationTemplate = ({ username, emailVerificationToken }: VerificationTemplateProps) => ( <Html> <Head /> <Preview>Preview text that appears in the email client before opening the email.</Preview> <Body style={main}> <Container style={container}> <Img src='my-logo.png' alt='My SaaS' style={logo} /> <Text style={title}>Hi {username}!</Text> <Text style={title}>Welcome to Starter Kit for building a SaaS</Text> <Text style={paragraph}>Please verify your email, with the link below:</Text> <Section style={btnContainer}> {/* Button that takes the user to the verification link */} <Button style={button} href={`${baseUrl}/auth/verify-email?token=${emailVerificationToken}`} > Click here to verify </Button> </Section> <Hr style={hr} /> <Text style={footer}>Something in the footer.</Text> </Container> </Body> </Html> ); // Styles applied to different parts of the email for customization const main = { backgroundColor: '#020817', color: '#ffffff', fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif', }; const container = { margin: '0 auto', padding: '20px 0 48px', }; ...


Thành phần này tạo một mẫu email HTML bao gồm các kiểu và nội dung động.


Thuộc tính được xác định để nhận username y emailVerificationToken . Các thuộc tính này được sử dụng để tùy chỉnh email cho người dùng và tạo liên kết xác minh.


Để xác thực và kiểm tra mẫu React Email cung cấp một lệnh để chạy cục bộ một máy chủ sẽ hiển thị các mẫu mà chúng tôi đã tạo bên trong thư mục email.


  1. Chúng tôi tạo tập lệnh trong package.json để chạy máy chủ.


 { "scripts": { "dev": "email dev" } }


2. Chúng tôi thực thi tập lệnh và tập lệnh này sẽ chạy máy chủ trên localhost ; chúng ta sẽ thấy một màn hình như sau với tất cả các mẫu đã được tạo.


Email phản hồi cục bộ


Trong trường hợp của chúng tôi, chúng tôi chỉ có một mẫu. Như bạn có thể thấy bên dưới, chúng tôi có bản xem trước của email sẽ được gửi cho người dùng.


Email xác thực


Gửi email bằng tính năng gửi lại

  1. Tạo một Gửi lại tài khoản .
  2. Tạo một cái mới MÃ API .
  3. Thêm API KEY vào tệp .env .


 ... # resend RESEND_API_KEY="re_jYiFaXXXXXXXXXXXXXXXXXXX"


4. Để tạo chức năng gửi email, chúng tôi có thể tạo điểm cuối bên trong thư mục api/ và thực hiện các yêu cầu http , tuy nhiên, trong trường hợp này, chúng tôi sẽ thực hiện điều đó bằng cách tận dụng tiềm năng hành động của máy chủ.


actions/email-actions.ts :

 'use server' import React from 'react' import { Resend } from 'resend' // Creates an instance of Resend using the API KEY const resend = new Resend(process.env.RESEND_API_KEY) // Defines the data structure for an email. interface Email { to: string[] // An array of email addresses to which to send the email. subject: string // The subject of the email. react: React.ReactElement // The body of the email as a React element. } export const sendEmail = async (payload: Email) => { const { error } = await resend.emails.send({ from: 'My SaaS <[email protected]>', // Defines the sender's address. ...payload, // Expands the contents of 'payload' to include 'to', 'subject', and 'react'. }) if (error) { console.error('Error sending email', error) return null } console.log('Email sent successfully') return true }


Lưu ý: Để kiểm tra quá trình phát triển miễn phí, bạn phải sử dụng email “[email protected]” làm người gửi, nếu không, bạn sẽ phải thêm một miền tùy chỉnh.


5. Gửi email khi đăng ký người dùng mới.


actions/auth-actions.ts :

 ... import { sendEmail } from './email-actions' import VerificationTemplate from '../../emails/verification-template' // Import a utility function to generate a secure token. import { generateSecureToken } from '@/utils' export async function registerUser(user: Partial<User>) { try { // Creates a new user in the database with the provided data. // Passwords are hashed using bcrypt for security. const createdUser = await prisma.user.create({ data: { ...user, password: await bcrypt.hash(user.password as string, 10), } as User, }) // Generates a secure token to be used for email verification. const emailVerificationToken = generateSecureToken() // Updates the newly created user with the email verification token. await prisma.user.update({ where: { id: createdUser.id, }, data: { emailVerificationToken, }, }) // Sends a verification email to the new user using the sendEmail function. await sendEmail({ to: ['your Resend registered email', createdUser.email], subject: 'Verify your email address', react: React.createElement(VerificationTemplate, { username: createdUser.username, emailVerificationToken }), }) return createdUser } catch (error) { console.log(error) if (error instanceof Prisma.PrismaClientKnownRequestError) { if (error.code === 'P2002') { // Returns a custom error message if the email already exists in the database. return { error: 'Email already exists.' } } } return { error: 'An unexpected error occurred.' } } }


Sau khi người dùng được tạo và mã thông báo xác minh được tạo, hàm sẽ gửi email đến người dùng mới.


Email này được tạo bằng cách sử dụng thành phần VerificationTemplate React, được cá nhân hóa bằng tên người dùng và mã thông báo xác minh. Bước này rất quan trọng để xác minh địa chỉ email của người dùng là hợp lệ và do người dùng kiểm soát.


Đăng ký thành công


Trang để xác thực mã thông báo

Sau khi email được gửi đến người dùng, email này sẽ có liên kết đưa anh ta quay lại trang web. Để xác thực email, đối với điều này, chúng ta cần tạo trang.


(primary)/auth/verify-email/page.tsx :

 /* All imports */ // Defines the prop types for the VerifyEmailPage component. interface VerifyEmailPageProps { searchParams: { [key: string]: string | string[] | undefined } } export default async function VerifyEmailPage({ searchParams }: VerifyEmailPageProps) { let message = 'Verifying email...' let verified = false if (searchParams.token) { // Checks if a verification token is provided in the URL. // Attempts to find a user in the database with the provided email verification token. const user = await prisma.user.findUnique({ where: { emailVerificationToken: searchParams.token as string, }, }) // Conditionally updates the message and verified status based on the user lookup. if (!user) { message = 'User not found. Check your email for the verification link.' } else { // If the user is found, updates the user record to mark the email as verified. await prisma.user.update({ where: { emailVerificationToken: searchParams.token as string, }, data: { emailVerified: true, emailVerificationToken: null, // Clears the verification token. }, }) message = `Email verified! ${user.email}` verified = true // Sets the verified status to true. } } else { // Updates the message if no verification token is found. message = 'No email verification token found. Check your email.' } return ( <div className='grid place-content-center py-40'> <Card className='max-w-sm text-center'> <CardHeader> <CardTitle>Email Verification</CardTitle> </CardHeader> <CardContent> <div className='w-full grid place-content-center py-4'> {verified ? <EmailCheckIcon size={56} /> : <EmailWarningIcon size={56} />} </div> <p className='text-lg text-muted-foreground' style={{ textWrap: 'balance' }}> {message} </p> </CardContent> <CardFooter> {verified && ( // Displays a sign-in link if the email is successfully verified. <Link href={'/auth/signin'} className='bg-primary text-white text-sm font-medium hover:bg-primary/90 h-10 px-4 py-2 rounded-lg w-full text-center'> Sign in </Link> )} </CardFooter> </Card> </div> ) }


Sau khi xác thực thành công email của người dùng, chúng ta sẽ thấy thông báo sau.


Trang để xác thực mã thông báo


Bây giờ, chúng tôi sẽ triển khai xác thực lần cuối khi người dùng muốn đăng nhập và chưa xác minh email của mình.


components/auth/sigin-form.tsx :

 ... async function onSubmit(values: InputType) { try { setIsLoading(true) const response = await signIn('credentials', { redirect: false, email: values.email, password: values.password, }) if (!response?.ok) { // if the email is not verified we will show a message to the user. if (response?.error === 'EmailNotVerified') { toast({ title: 'Please, verify your email first.', variant: 'warning', }) return } toast({ title: 'Something went wrong!', description: response?.error, variant: 'destructive', }) return } toast({ title: 'Welcome back! ', description: 'Redirecting you to your dashboard!', }) router.push(callbackUrl ? callbackUrl : '/') } catch (error) { console.log({ error }) toast({ title: 'Something went wrong!', description: "We couldn't create your account. Please try again later!", variant: 'destructive', }) } finally { setIsLoading(false) } } ... 


Email xác thực


Đó là nó! 🎉


Người dùng sẽ có thể xác thực email của mình và hoàn tất đăng ký trong ứng dụng của chúng tôi.


🧑‍💻 Repo ở đây

Phần kết luận

Chúng ta đã biết cách tạo và gửi email bằng React Email và Resend. Quá trình này cho phép bạn tận dụng kiến thức về React để thiết kế email hiệu quả trong khi vẫn duy trì quy trình làm việc quen thuộc và hiệu quả.


Bạn có thể thử nghiệm với các thành phần và thuộc tính khác nhau để tạo email hoàn toàn phù hợp với nhu cầu dự án của mình.


Bạn muốn kết nối với Tác giả?


Thích kết nối với bạn bè trên khắp thế giới trên 𝕏 .


Cũng được xuất bản ở đây