# Sending emails

When a user creates an account, we could send an email to him confirming that his account has been successfully created.

> This solution was inspired by this [article](https://notiz.dev/blog/send-emails-with-nestjs) from **Marc Stammerjohann** (blog).

First, we should install **handlebars**. It is a **template engine**, capable of generating an HTML template dynamically. It allows for holding the email structure while also receiving data.

```sh
yarn add hbs
```

After that, install the dependencies required for email handling.

```sh
yarn add @nestjs-modules/mailer nodemailer
yarn add -D @types/nodemailer
```

{% hint style="info" %}
Note that, in this case, we use a **community** package instead of an official one.
{% endhint %}

We should then create an account with an **email provider**, so that we can send emails through the system by using its credentials. Here, we'll use [MailTrap](https://mailtrap.io/) due to its simple setup. Create a free account and go to the **Email Testing** section, in order to obtain the credentials. Due to its testing nature, we won't be sending an actual email, but we'll be able to see if it succeeded on the dashboard. That is, if an actual email **would** be sent in a real case.

Now, create a module and a service for **mailing**. Also export the service.

```sh
nest g mo mail
nest g s mail
```

In the same directory, create the folder <mark style="color:purple;">templates</mark>, for holding the **handlebars templates**.

Then, define the environment variables for the **email server**, Use your actual credentials here, but set this sample data in the **example** file.

```properties
MAIL_PROTOCOL = smtp
MAIL_HOST = smtp.example.com
MAIL_USER = username
MAIL_PASSWORD = pass123
MAIL_FROM = noreply@mail.com
```

Also update the <mark style="color:blue;">`ENV_VALIDATION_SCHEMA`</mark>, and break a line for better readability. Note the new validation rules.

```typescript
MAIL_PROTOCOL: Joi.valid('smtp', 'smtps').required(),
MAIL_HOST: Joi.string().hostname().required(),
MAIL_USER: Joi.required(),
MAIL_PASSWORD: Joi.required(),
MAIL_FROM: Joi.string().email().required(),
```

As we are used to, the next step is to create a configuration namespace. We may do so in <mark style="color:purple;">mail</mark>/<mark style="color:purple;">config</mark>/<mark style="color:purple;">mail.config</mark>. We use the credentials to create the <mark style="color:blue;">`transport`</mark> url, very similarly to the database configuration. Also, a **default** is used for the <mark style="color:blue;">`from`</mark> email, and the template engine is also configured.

```typescript
export default registerAs('mail', () => {
  const protocol = process.env.MAIL_PROTOCOL;
  const host = process.env.MAIL_HOST;
  const user = process.env.MAIL_USER;
  const password = process.env.MAIL_PASSWORD;
  const from = process.env.MAIL_FROM;

  const transport = `${protocol}://${user}:${password}@${host}`;

  const config = {
    transport,
    defaults: {
      from: `No Reply <${from}>`,
    },
    template: {
      dir: resolve(__dirname, '..', 'templates'),
      adapter: new HandlebarsAdapter(),
      options: { strict: true },
    },
  } as const satisfies MailerOptions;
  return config;
});
```

{% hint style="info" %}
Note the following about the <mark style="color:blue;">`template`</mark>:

* The <mark style="color:blue;">`dir`</mark> location is resolved from <mark style="color:blue;">\_\_dirname</mark>, which is the current folder
* The <mark style="color:blue;">`HandlebarsAdapter`</mark> should be imported manually from <mark style="color:blue;">`@nestjs-modules/mailer/dist/adapters/handlebars.adapter`</mark>
* The <mark style="color:blue;">`strict`</mark> option enforces that all fields are passed to the template
  {% endhint %}

In the <mark style="color:blue;">`MailModule`</mark>, import the <mark style="color:blue;">`MailerModule`</mark>, passing this configuration.

```typescript
MailerModule.forRootAsync(mailConfig.asProvider())
```

Then, inside the <mark style="color:purple;">templates</mark> folder, we may create the template <mark style="color:purple;">account-confirmation.hbs</mark>.

```handlebars
<p>Hello {{name}},</p>

<p>Your account has been successfully created!</p>

<p><strong>The Conrod Shop</strong></p>
```

However, the templates are not included in the **build** by default. Due to this, let's go to the <mark style="color:purple;">nest-cli.json</mark> file and add the following inside the <mark style="color:blue;">`compilerOptions`</mark>. We also enable **watch mode** for them.

```json
"assets": ["**/*.hbs"],
"watchAssets": true
```

In the <mark style="color:blue;">`MailService`</mark>, we may now inject the <mark style="color:blue;">`MailerService`</mark>. Finally, let's create a method for sending an "account created" confirmation email to the user. We also pass the <mark style="color:blue;">`context`</mark> with the data for the template. And return the result just in case we may want to inspect it.

```typescript
sendAccountConfirmation(user: User) {
  const { name, email } = user;

  const mailData = {
    to: email,
    subject: 'Conrod Shop - Account created',
    template: './account-confirmation',
    context: { name },
  } as const satisfies ISendMailOptions;

  return this.mailerService.sendMail(mailData);
}
```

Now, we should import the <mark style="color:blue;">`MailModule`</mark> in the <mark style="color:blue;">`UsersModule`</mark>, and inject the <mark style="color:blue;">`MailService`</mark> in the <mark style="color:blue;">`UsersSubscriber`</mark>. It is here that we'll send the email after the account is created, in order to prevent bloating the <mark style="color:blue;">`UsersService`</mark>. Lastly, to only send this email after the user is successfully created, this will be done in the <mark style="color:blue;">`afterInsert()`</mark> listener.

```typescript
async afterInsert(event: InsertEvent<User>) {
  const { entity: user } = event;

  await this.mailService.sendAccountConfirmation(user);
}
```

{% hint style="info" %}
To avoid adding a delay to the user creation, we could simply <mark style="color:red;">not</mark> <mark style="color:blue;">await</mark> the email to be sent. But then, we would <mark style="color:red;">not</mark> be sure if this operation was <mark style="color:green;">successful</mark>.
{% endhint %}

<mark style="color:green;">**Commit**</mark> - Sending email when user is created


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kinesis-school-of-programming.gitbook.io/nestjs-unleashed/further-improvements/sending-emails.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
