paint-brush
Comment envoyer une vérification par e-mail dans Next.js 14 avec NextAuth.js, renvoyer et réagir par e-mailpar@ljaviertovar
3,973 lectures
3,973 lectures

Comment envoyer une vérification par e-mail dans Next.js 14 avec NextAuth.js, renvoyer et réagir par e-mail

par L Javier Tovar12m2024/04/02
Read on Terminal Reader

Trop long; Pour lire

Après avoir exploré comment implémenter un système d'authentification dans Next.js 14 avec NextAuth.js(Auth.js) dans la première partie de ce blog, il est crucial de passer à l'étape suivante pour garantir la validité des informations utilisateur : la validation des e-mails. Ce processus constitue non seulement une étape supplémentaire dans la sécurité de notre application, mais un élément essentiel pour garantir que les interactions entre l'utilisateur et la plateforme sont légitimes et sécurisées. Dans cette deuxième partie, nous nous concentrerons sur l'intégration de la validation des emails par l'envoi d'emails, en utilisant Resend pour l'envoi d'emails, et React Email pour créer des modèles d'emails attractifs et fonctionnels.
featured image - Comment envoyer une vérification par e-mail dans Next.js 14 avec NextAuth.js, renvoyer et réagir par e-mail
L Javier Tovar HackerNoon profile picture
0-item
1-item

Après avoir exploré comment implémenter un système d'authentification dans Next.js 14 avec NextAuth.js(Auth.js) dans la première partie de ce blog, il est crucial de passer à l'étape suivante pour garantir la validité des informations utilisateur : la validation des e-mails.


Ce processus constitue non seulement une étape supplémentaire dans la sécurité de notre application, mais un élément essentiel pour garantir que les interactions entre l'utilisateur et la plateforme sont légitimes et sécurisées.


Dans cette deuxième partie, nous nous concentrerons sur l'intégration de la validation des emails par l'envoi d'emails, en utilisant Resend pour l'envoi d'emails, et React Email pour créer des modèles d'emails attractifs et fonctionnels.

Configuration initiale

Assurez-vous que votre projet dispose déjà du système d'authentification décrit dans la première partie du blog implémenté. Cela inclut la configuration correcte de Next.js 14 et NextAuth.


Intégration de renvoi et de courrier électronique Ract dans Next.js

Configuration

  1. Installez les dépendances nécessaires au projet. Cette fois, nous utiliserons pnpm vous pouvez utiliser le gestionnaire de paquets de votre choix.


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




2. Créez la structure suivante pour le projet :


 ... ├── 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 ...


Création de modèles d'e-mails avec React Email

React Email vous permet de créer des modèles d'e-mails à l'aide de JSX, ce qui facilite la création d'e-mails attrayants et cohérents avec votre marque.


Créons un modèle d'e-mail de base en tant que composant React. Dans ce cas, nous créerons le modèle qui sera envoyé à l'utilisateur pour confirmer son email.


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', }; ...


Ce composant crée un modèle d'e-mail HTML qui inclut des styles et du contenu dynamique.


Les propriétés sont définies pour recevoir username et emailVerificationToken . Ces propriétés sont utilisées pour personnaliser l'e-mail pour l'utilisateur et générer le lien de vérification.


Pour valider et tester le modèle, React Email fournit une commande pour exécuter localement un serveur qui exposera les modèles que nous avons créés dans le dossier emails.


  1. Nous créons le script dans le package.json pour exécuter le serveur.


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


2. Nous exécutons le script et cela exécutera le serveur sur localhost ; nous verrons un écran comme celui-ci avec tous les modèles créés.


E-mail de réaction local


Dans notre cas, nous n'avons qu'un seul modèle. Comme vous pouvez le voir ci-dessous, nous avons un aperçu de l'e-mail qui sera envoyé à l'utilisateur.


Vérification de l'E-mail


Envoi d'e-mails avec renvoi

  1. Créer un Renvoyer le compte .
  2. Créer un nouveau CLÉ API .
  3. Ajoutez la API KEY au fichier .env .


 ... # resend RESEND_API_KEY="re_jYiFaXXXXXXXXXXXXXXXXXXX"


4. Pour créer la fonctionnalité d'envoi d'e-mails, nous pourrions créer des points de terminaison dans le dossier api/ et faire des requêtes http , cependant, à cette occasion nous le ferons en profitant du potentiel des actions du serveur.


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 }


Remarque : Pour tester en développement gratuit, vous devez utiliser comme expéditeur l'e-mail « [email protected] », sinon vous devrez ajouter un domaine personnalisé.


5. Envoyez l'e-mail lors de l'enregistrement d'un nouvel utilisateur.


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.' } } }


Une fois l'utilisateur créé et le jeton de vérification généré, la fonction envoie un e-mail au nouvel utilisateur.


Cet e-mail est construit à l'aide du composant VerificationTemplate React, personnalisé avec le nom de l'utilisateur et le jeton de vérification. Cette étape est cruciale pour vérifier que l'adresse e-mail de l'utilisateur est valide et contrôlée par l'utilisateur.


Inscription réussie


Page pour valider le jeton

Une fois l'e-mail envoyé à l'utilisateur, celui-ci contiendra un lien qui le ramènera au site. Pour valider l'email, pour cela, nous devons créer la page.


(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> ) }


Après avoir validé avec succès l'e-mail de l'utilisateur, nous verrons le message suivant.


Page pour valider le token


Nous allons désormais implémenter une dernière validation lorsque l'utilisateur souhaite se connecter et n'a pas encore vérifié son email.


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) } } ... 


Vérification de l'E-mail


C'est ça! 🎉


L'utilisateur pourra valider son email et finaliser son inscription dans notre application.


🧑‍💻 Repo ici

Conclusion

Nous savons déjà comment créer et envoyer des e-mails à l'aide de React Email et Resend. Ce processus vous permet d'exploiter vos connaissances de React pour concevoir des e-mails efficacement tout en conservant un flux de travail familier et productif.


Vous pouvez expérimenter différents composants et propriétés pour créer des e-mails parfaitement adaptés aux besoins de vos projets.


Vous souhaitez entrer en contact avec l'auteur ?


J'adore me connecter avec des amis du monde entier sur 𝕏 .


Également publié ici