Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for AdonisJs - Events and Mailing Part 1
Ted Ngeene
Ted Ngeene

Posted on • Originally published attngeene.com

     

AdonisJs - Events and Mailing Part 1

Welcome back to the fourth installment of the AdonisJs series!

A web framework's ability to handle events and mailing greatly add to its appeal. Luckily, Adonis provides these in an easily configurable way that will set you on your path to building robust APIs and web apps.

In this article, I'll show just how we go about these two crucial concepts in modern software development. In order to achieve our goal, we'll build upon theprevious article, where we talked about user registration and login.

If you're not familiar with the concept of events in software development, worry not.

Events can be described as actions that are triggered by another action in a system, for example, you'd want your users to be emailed upon successful registration. In this case, the email sending is an event triggered by successful user registration.

What we'll be working on

For this tutorial, we're going to implement an event that emails our users an activation link for their accounts. The purpose of this is to enforce security in our application.
We definitely wouldn't have bots and fictitious accounts registering in our application.

We'll look at two approaches we can employ to achieve this, but before we do that, let's set up the mailer.

Installing Adonis Mailing package.

Since we'll need users to receive emails, we need a way to make our system be able to send them. Luckily, Adonis also has amailer package for this. To install, run

 npm i @adonisjs/mail
Enter fullscreen modeExit fullscreen mode

As usual, we also need to configure the package preferences,

node ace invoke @adonisjs/mail

For my configuration, I'll be using SMTP

tngeene adonis mail config

Open up theenv.ts file and paste the following values.

SMTP_HOST: Env.schema.string({ format: 'host' }),SMTP_PORT: Env.schema.number(),SMTP_USERNAME: Env.schema.string(),SMTP_PASSWORD: Env.schema.string(),DEFAULT_FROM_EMAIL: Env.schema.string(),
Enter fullscreen modeExit fullscreen mode

These values are the environment variables for our SMTP configuration. I recommend validating them in theenv.ts file.
TheDEFAULT_FROM_EMAIL is the email that will appear as the sender from our application.
The main environment variables will reside in the.env file. We'll get there in a minute.

Setting up our SMTP service

The Simple Mail Transfer Protocol(SMTP) is an internet standard communication protocol for electronic mail transmission. Mail servers and other message transfer agents use SMTP to send and receive mail messages.

There are a number of SMTP providers; including, google, mailgun, SendGrid...and so on. However, since we are not building a production-ready application yet, I'll be usingmailtrap.

tngeene adonis mailtrap

Mailtrap is an email testing tool that Captures SMTP traffic from staging and dev environments. Simply put, it mocks real-world emails in a sandbox environment. Head over to theirwebsite, create an account, and navigate to the demo inbox section.

tngeene adonisjs mailtrap demo inbox

Next, open the .env file located in your project's root directory and paste these constants.

  SMTP_HOST=smtp.mailtrap.io  SMTP_PORT=2525  SMTP_USERNAME=<your_mailtrap_username>  SMTP_PASSWORD=<your_mailtrap_password>  DEFAULT_FROM_EMAIL=admin@fitit.com #varies
Enter fullscreen modeExit fullscreen mode

The username and password values are found on the mailtrap dashboard, under theintegrations section.

Now that we have all that setup, we'll get straight right into actual coding.

Approach 1 - Using a function in a model

This approach will involve us having a function inside our user model that will handle email sending. We'll call this function in our authController, right after a successful registration.

Open theapp/Models/User.ts. We'll import several packages at the top,

importMailfrom'@ioc:Adonis/Addons/Mail'importEnvfrom'@ioc:Adonis/Core/Env'importRoutefrom'@ioc:Adonis/Core/Route'
Enter fullscreen modeExit fullscreen mode

Next, after all the model column definitions, we'll write asendVerificationEmail function.

publicasyncsendVerificationEmail(){constappDomain=Env.get('APP_URL')constappName=Env.get('APP_NAME')constcurrentYear=newDate().getFullYear()consturl=Route.builder().params({email:this.email}).prefixUrl(appDomain).makeSigned('verifyEmail',{expiresIn:'24hours'})Mail.send((message)=>{message.from(Env.get('DEFAULT_FROM_EMAIL').to(this.email).subject('Please verify your email').htmlView('emails/auth/verify',{user:this,url,appName,appDomain,currentYear})})}
Enter fullscreen modeExit fullscreen mode

The code above is contains several building blocks that helps to achieve the email sending functionality.

constappDomain=Env.get('APP_URL')constappName=Env.get('APP_NAME')
Enter fullscreen modeExit fullscreen mode

These are values which reside in our.env file. If you don't have them already, you can check out theenv.example file of thisproject repo

My current values are

  APP_NAME=Fitit  APP_URL=http://127.0.0.1:3333
Enter fullscreen modeExit fullscreen mode
constcurrentYear=newDate().getFullYear()
Enter fullscreen modeExit fullscreen mode

we get the current year. We'll inject this as a variable in our html template for our email

consturl=Route.builder().params({email:this.email}).prefixUrl(appDomain).makeSigned('verifyEmail',{expiresIn:'24hours'})
Enter fullscreen modeExit fullscreen mode

We're using the Route package to encode our user data into an activation token. ThemakeSigned() function is tied to averifyEmail route that we'll build in the next part. Finally, we set an expiry period for the token. For this case, I set the period to 24 hours. That way, if a user fails to verify their account within that duration, their account won't be activated.

Mail.send((message)=>{message.from(Env.get('DEFAULT_FROM_EMAIL').to(this.email).subject('Please verify your email').htmlView('emails/auth/verify',{user:this,url,appName,appDomain,currentYear})})
Enter fullscreen modeExit fullscreen mode

This section makes use of the adonis mailer package. We're giving instructions to the program to send an email to the created user's email. The email will appear as received from the valueDEFAULT_FROM_EMAIL in our.env file.
The subject line will be, "Please verify your email".

ThehtmlView method contains the template our email will read from, that is, the html code that styles our verification email.
For this, create a folder namedresources in the project root directory. The entry point for all Adonis html templates must be located within this folder.
Since we initialized this project as an API only, we'll install the package that enables us to have.edge templates

npm i @adonisjs/view

The first argument the function takes is the html template to read from.
Create aemails\auth\verify.edge file and paste the code from thisgithub gist. The next argument it takes are the variables to be read in the html template. In our case,

{ user: this, url, appName, appDomain, currentYear }
Enter fullscreen modeExit fullscreen mode

Writing the Verify Email controller

We're going to write an email verification controller that will be responsible for validating and activating a user's account.

node ace make:controller users/EmailVerificationsController
Enter fullscreen modeExit fullscreen mode

Open the created file and copy this snippet.

import{HttpContextContract}from'@ioc:Adonis/Core/HttpContext'importUserfrom'App/Models/User'import{DateTime}from'luxon'exportdefaultclassEmailVerificationsController{publicasyncconfirm({response,request,params}:HttpContextContract){if(request.hasValidSignature()){constuser=awaitUser.findByOrFail('email',params.email)if(!user.isActivated){user.email_verified_at=DateTime.local()user.isActivated=trueuser.save()returnresponse.status(202).send({message:'Account verified and activated'})}else{returnresponse.status(409).send({message:'Account was already verified'})}}else{returnresponse.status(403).send({error:{message:'Invalid token'}})}}}
Enter fullscreen modeExit fullscreen mode

Next, copy this into the users.ts file under the routes directory

Route.get('/verify-email/:email','users/EmailVerificationsController.confirm').as('verifyEmail')
Enter fullscreen modeExit fullscreen mode

We're mapping the controller to a route. In adonis, routes can be given custom names, by defining the named route to a function,as(). In our case, the route is calledverifyEmail. If you're keen enough, you'll notice that we passed this named route as a parameter in the model function we defined in the User model.

.makeSigned('verifyEmail',{expiresIn:'24hours'})})
Enter fullscreen modeExit fullscreen mode

From the email verification controller code, we can see we have theconfirm() function.
This block contains the user activation logic, that is, immediately the link is hit, we verify the user and activate his account. It also contains constraints that check whether the URL pattern matches the valid the signature, hence themakeSigned() andhasValidSignatureSections()

Finally, we modify the AuthController to send the email after a successful registration. Right after we save our user in the database,

constuser=awaitUser.create(data)// send verification emailuser?.sendVerificationEmail()returnresponse.status(201).send({success:'Registration successful, check your email inbox for a verification email'})
Enter fullscreen modeExit fullscreen mode

Testing

For testing open up your postman and repeat the registration steps we used in theprevious article. Create a new user, and head over to your mailtrap demo inbox.

If everything worked well, then the following images should be what you see.

tngeene events adonis
tngeene events adonis
tngeene events adonis

There's a lot of content to cover in events. The method covered in this piece is just one way to go about it. To keep the article short, I've decided to cover the next approach in the next piece.

If you have any comments, queries, don't hesitate to leave a comment or email.
Until then, stay Adonis. It is the way!

Top comments(1)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss
CollapseExpand
 
aliif profile image
Aliif
just newbie
  • Location
    Indonesia
  • Joined

you must runnode ace configure @adonisjs/view after installing adonisjs view

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Passionate about education, fintech, Python, Javascript, progressive growth, and full-stack development.Sometimes I write code, sometimes I just write.
  • Location
    Nairobi
  • Work
    Fullstack developer
  • Joined

More fromTed Ngeene

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp