
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:00 In this lesson, I'll teach you how to use NodeMailer, a free module for Node.js applications that allows for easy email sending.
00:00:08 And of course, we'll integrate it with our workflows.
00:00:11 So, let's run npm install nodemailer.
00:00:14 I'll put that straight within our terminal.
00:00:16 And to make NodeMailer work, we'll use our Gmail account as our email transporter.
00:00:21 So, head over to your Gmail account, go to Settings in your profile, and for this to work, if you haven't already, you'll have to turn on the two-step
00:00:30 verification for your email.
00:00:31 It's like an extra layer of security, it's good to have it anyway, but in this case you'll have to have it for NodeMailer to work.
00:00:38 so just follow the steps to turn it on, but if you're a good developer that cares about security, I believe it's already on for you.
00:00:44 Then, once you enable it, you select your account and click Manage Your Account.
00:00:49 Right here on the homepage, search for App Passwords and click the first link under Security.
00:00:56 Then, enter the app name.
00:00:58 In this case, I'll choose Subscription Tracker.
00:01:01 and click create, and then just copy the password you were given.
00:01:04 Back within your editor, head over to .env.development.local, and at the bottom, add a new node mailer comment, and here we can say email password is equal to,
00:01:18 and then you can paste the password that you just got.
00:01:21 And here you can also export the email password.
00:01:24 Then let's create a new configuration file.
00:01:27 I think you can see how useful having this structure is.
00:01:30 And I'll call it node-mailer.js Here we can configure a transporter using Gmail as a service by saying const transporter is equal to node-mailer.createTransport
00:01:51 And make sure to import node-mailer right at the top from node mailer, like this.
00:02:00 Next, we can define service as Gmail and then auth equal to user will be equal to your account email.
00:02:09 In my case, it'll be javascriptmastery00atgmail.com.
00:02:14 Choose the Gmail account that you enabled your two-step verification on and through which you created your app password.
00:02:22 It has to be the same one.
00:02:24 And then right here, we can put the pass, which will be equal to email underscore password coming from dot slash env.js.
00:02:33 Now, we can create a common reusable HTML templates for all different kinds of reminders.
00:02:39 To create it, create a new folder called utils, like utility functions, and within utils, create a new file called email dash template dot js.
00:02:52 I've just used v0 to quickly generate a template, it's basic HTML and CSS, and I told it to include all the important things,
00:03:00 such as username, email, subscription date, and all that good stuff.
00:03:04 So I'll leave it either below this lesson, or within the assets part of the GitHub Readme of this project.
00:03:10 So just copy from there and then paste it here.
00:03:14 You'll notice that it is a single function called the generateEmailTemplate, which is basically just a div with a lot of CSS styles,
00:03:21 but then it mentions the subscription name, the plan name, the user name, and all the important stuff that we pass through it.
00:03:29 We also have different templates like 7 days before, 5 days before, 2 days before, and then we call the actual function and generate the subject and the
00:03:38 body of that specific email.
00:03:40 Once again, nothing special is happening here, we're just returning HTML.
00:03:44 Now, let's put it to use.
00:03:45 Let's write the actual logic that'll send the reminder email.
00:03:49 We can do it within a new file within the utils folder, and let's call it send-email.
00:03:55 email.js.
00:03:57 Within here, we can export const sendReminderEmail, which will be equal to an async function, it'll look something like this,
00:04:07 and as the first and only parameter, it'll accept an object, so we can destructure it, and it'll have the to property, who we're sending the email to,
00:04:16 the type property, and the subscription.
00:04:22 So now that we have destructured those, we can say if there is no to, or if there is no type, we can simply throw a new error and say something like missing
00:04:35 required parameters.
00:04:39 If it exists, we can create a new template by calling the email templates.
00:04:47 and calling the find() method on it, where we're going to look into the type that we have, and then based on the t.label,
00:04:56 we'll compare it with the type that we have, And that'll be the template we'll use for this specific reminder.
00:05:03 If it's five days until, we'll find that in the email templates and we'll save five days reminder.
00:05:09 If it's seven days, it'll be seven.
00:05:10 If it's one, it'll be one.
00:05:12 Once we have the template, we can check if we have it.
00:05:15 If we don't, we can say invalid email type.
00:05:20 And finally, we can form an object containing the full user info.
00:05:25 I'll call it mail info, username, is subscription.user.name.
00:05:36 Next, we're going to have a subscription name, which will be equal to subscription.name.
00:05:44 Let's spell it properly.
00:05:47 After that, we're going to have the renewal date, which will be equal to dayjs subscription.renewaldate And I'm gonna even format it to MMM DYYYY.
00:06:08 This is just a format where it'll say something like January 1st, 2030, or something like that.
00:06:14 We're gonna also have a plan name, so that'll be the subscription.name.
00:06:20 We also have the price, and it'll be equal to, let's format it, subscription, dot currency, after that, subscription dot price,
00:06:35 and then finally, in parentheses, we can render the subscription dot frequency.
00:06:44 So it's going to say something like USD 10 monthly.
00:06:51 And we can also render a payment method, which will be equal to subscription dot payment method.
00:07:00 Perfect.
00:07:02 Finally, let's form the actual message by saying const message is equal to template dot generate body, and we'll generate the mail info.
00:07:15 And finally, there is the subject of that email, which will be equal to template.generateSubject.
00:07:23 We'll pass the mail info.
00:07:25 And finally, we can form the final mail options by saying const mailOptions is equal to, from will be equal to the account email,
00:07:37 to will be equal to to, subject will be equal to subject, And finally, HTML will be equal to the message that is coming from the template.
00:07:51 Oh, and let's make sure that we know where this account email is coming from.
00:07:55 It has to be the same as the one that we have chosen right here in node mailer config.
00:08:00 So we could actually separate it from here and export it by saying export const account email is equal to, and now I can copy this string,
00:08:12 put it here.
00:08:14 So I can refer to the account email and then we're exporting it.
00:08:22 And back in the send email, we can import this account email coming from config-node-mailer.js.
00:08:30 Finally, from the node mailer, we'll also import our instance of the transporter with our configuration.
00:08:40 And now that we have all the information, we can say transporter.sendmail with all the mail options.
00:08:50 And as the second parameter, we're going to get access to the error or the information for that email.
00:08:56 And if there is an error, we will simply return a console log.
00:09:04 and say error, as well as error sending email.
00:09:08 Else, we will simply console log email sent, and I'll also add the info response of that email.
00:09:16 Now, where are we gonna call this send reminder email function from?
00:09:21 Well, we're gonna call it from the workflow controller.
00:09:24 So head over into the workflow controller, and remember this comment.
00:09:28 We're finally back right here.
00:09:31 I'll simply say await send reminder email make sure to import it from utils sendemail.js and to it we have to pass a couple of things it'll be an object
00:09:46 of the to property and we want to send it to subscription.user.email so whoever created that subscription And we have to pass the type of the subscription,
00:09:57 which will be equal to reminder.label.subscription.
00:10:01 So either five days until, seven days until, three days until, and so on.
00:10:06 Let's open up our terminal to see if we have any errors, because we have modified a lot of code.
00:10:11 Looks like we have one error in workflow controller line 49. And that is right here where I added a weight.
00:10:20 To be able to add a weight right here, I have to make the function I'm calling the weight within async.
00:10:27 So let me add it there.
00:10:31 And that fixed the error.
00:10:32 Now we have another error in sendEmail.js.
00:10:36 So if I head over here, we're importing the transporter.
00:10:41 But are we actually exporting it?
00:10:44 Oh, looks like we're not.
00:10:45 So let's run export default transporter.
00:10:49 And with that, that second error is now gone.
00:10:52 Subscription Tracker API is running and we're connected to the database.
00:10:57 So, back in our HTTP client, let's try to create a new subscription.
00:11:02 This time, I'll do it for Amazon Prime in a currency of USD, category entertainment, and feel free to test it with different days right here.
00:11:12 I'll choose a date that is 7 days from my current date.
00:11:17 You can of course choose a date that is 7 days from your date.
00:11:21 And if I now click Send, of course we get a 201. We've gotten good at getting those and not errors.
00:11:27 We get back the subscription that we created with automatically calculated renewal date.
00:11:33 And we got a new workflow that we ran.
00:11:36 Oh, it looks like I have another reference error.
00:11:39 It is happening within the workflow controller.
00:11:41 I haven't defined a subscription.
00:11:44 So let me quickly head over into the workflow controller.
00:11:47 And here, it looks like I'm referring to a subscription, but I don't really have access to it within this trigger reminder function.
00:11:55 So when we're calling this trigger reminder, and we're calling it right here, Maybe as the third parameter I need to pass the actual subscription.
00:12:05 Here we do have it, as you can see.
00:12:10 Then I can accept it as the third parameter, subscription, and now we should have access to it.
00:12:17 What about the reminder?
00:12:18 I don't think we have that either, and it's not like we can very easily pass it.
00:12:23 But this reminder label is basically just this label, which we're already passing through.
00:12:29 And this label has to exactly match the one within email templates, where it says seven days before reminder, five days before reminder,
00:12:39 two days before reminder, and one day before reminder.
00:12:42 So that's 7521, and then we have the final.
00:12:45 I think I can even get rid of this final.
00:12:47 We can just keep it 7521. And it has to match exactly.
00:12:52 So let's copy it and let's compare it.
00:12:55 Here I have reminder, days before days before, but actually we have to start with the number, then days before, and then finally reminder like this.
00:13:07 So that's gonna then look something like this, two days before reminder.
00:13:13 Perfect.
00:13:14 So now we're passing that as a label.
00:13:16 So the type can be just label, and then we can pass the entire subscription equal to subscription.
00:13:23 We need it to send that email reminder.
00:13:25 So, let's test it once again by creating another subscription.
00:13:29 And take a look at this.
00:13:31 Sleeping until reminder five days before.
00:13:35 Email sent.
00:13:38 Okay.
00:13:38 And we get the ID of the email.
00:13:41 Beautiful.
00:13:42 Now, of course, this email will get to the email of the user that created the subscription.
00:13:48 So if you want to know which one is that, you can copy the ID of the user that created the subscription, and then go to get localhost api v1 users,
00:13:59 and then paste over that user ID, and you'll get your email right here.
00:14:04 And check this out.
00:14:05 What a nice caption right here.
00:14:07 Reminder, your Amazon Prime subscription renews in 7 days.
00:14:11 Hello Adrian, your Amazon Prime subscription is set to renew.
00:14:15 Plan, price, payment method.
00:14:18 If you'd like to make changes or cancel the subscription, visit your account settings before the renewal date or contact our team.
00:14:26 Of course, none of these links are real, but you get the idea of what is possible by creating your own API, now with workflows allowing you to trigger
00:14:36 and send emails to people that want to get reminded.
00:14:40 Now, let's try to make another subscription, but this one will have a closer renewal date.
00:14:46 so we're not looking to trigger the seven-day reminder, but maybe the two-day or one-day reminder.
00:14:51 Right now, it's February 7th for me, so I'm gonna make it seem like I subscribed on the 9th of January, which means that there should only be two days
00:15:02 left until the renewal on February 9th.
00:15:04 You can change it depending on your current date and time.
00:15:07 But before we trigger it, there's just one fix that we have to add in our workflow controller, and that is right here where we're triggering the reminder.
00:15:17 Currently, if we're only two days away, what would happen is we're gonna go into this for loop, and we're gonna trigger all of the reminders in the row,
00:15:27 7, 5, 3, 2, 1. But instead, if we're already so close to the renewal date, we have to have an if statement right here, and check.
00:15:36 If now is same, reminderDate day.
00:15:41 Only if that is the case, then trigger this reminder.
00:15:45 Oh, and if I'm not mistaken, instead of using the word now, we can just call the day.js as a function, because that will render the current date and time.
00:15:54 and then we're checking whether currently is the same as the reminder date.
00:15:59 Only then send it.
00:16:00 Now, let's trigger that new subscription that has a renewal date that is only two days away.
00:16:06 There we go, we get a 201 created with new subscription data and a new workflow run ID.
00:16:13 Back in the terminal, we now only see one email sent instead of like seven.
00:16:18 And most importantly, take a look at this.
00:16:21 Email caption changed to a bold saying, final reminder, Amazon Prime renews tomorrow.
00:16:29 Hey Adrian, your subscription is set to renew on February 8th, one days from today.
00:16:35 Beautiful.
00:16:37 So now that we know that our workflows are flowing, emails are sending, and subscriptions are getting created and tracked,
00:16:45 ready for us to cancel them if we don't want to keep paying.
00:16:48 Which means that our app has done its job.
00:16:52 In the next lesson, let's deploy and host it to your own virtual private server, so you have complete flexibility over how you want to host it and how
00:17:02 you want to let other people access it.
00:17:04 Who knows, maybe even put it behind the paywall and start making some money from it.
00:17:09 The possibilities are endless.
00:17:12 But enough talking, let's deploy it on a VPS.