Published on

Nest.jsでEJSテンプレートエンジンを使いメール送信する方法

Authors

Nest.js で EJS テンプレートエンジンを使い、メール送信を行う方法

この記事では、Nest.js を使ってメール送信を行う方法について、EJS をテンプレートエンジンとして使用する方法を解説します。ここでは、メール送信には一例として、 SendGrid を使用していますが、別の方法でも問題ないと思います。

1. パッケージのインストール

まずは必要なパッケージをインストールします。以下のコマンドを実行して、必要なパッケージをインストールします。

yarn add ejs @sendgrid/mail
yarn add @types/ejs -D

2. テンプレートの読み込み

mailerディレクトリ内にtemplates.tsファイルを作成します。ここでは EJS テンプレートを読み込み、すぐにそのテンプレートを読み込めるようにエクスポートします。

// src/mailer/templates.ts
import { readFileSync } from 'fs'
import { join } from 'path'
import * as ejs from 'ejs'

const loadTemplate = (templatePath: string) => {
  const templateString = readFileSync(join(__dirname, templatePath), 'utf-8')
  return ejs.compile(templateString)
}

export const welcomeTemplate = loadTemplate('templates/welcome.ejs')

上記のコードでは、loadTemplate関数を用いて、ファイルパスからテンプレートを読み込み、EJS でコンパイルしています。結果として得られる関数は、テンプレートに挿入するデータを引数として取り、完成した文字列を返します。この関数を利用して、welcome.ejsテンプレートをロードします。

このようにすると、EJS テンプレートの読み込みとコンパイルの処理を一元化できます。例えば、新しく問い合わせメールを作る場合、contactTemplate = loadTemplate("templates/contact.ejs")とするだけで新たなテンプレートを追加することができます。これにより、コードの重複を避けつつメンテナンス性も向上します。

3. メールテンプレートの作成

mailer/templatesディレクトリ内にwelcome.ejsというファイルを作成します。このファイルにはメールのテンプレートが含まれます。

<!-- src/mailer/templates/welcome.ejs -->
<p>Hello, <%= name %>!</p>
<p>Welcome to our platform.</p>

このテンプレートは非常にシンプルで、name変数を用いてメッセージを出力するだけです。

4. nest-cli.json の設定

Nest.js の CLI 設定を変更します。nest-cli.jsonに以下の設定を追加します。

// nest-cli.json
{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "assets": ["mailer/templates/*"],
    "watchAssets": true
  }
}

ここで"assets": ["mailer/templates/*"]の設定は、mailer/templatesディレクトリ内の全てのファイルをコンパイル時にコピーします。これは、Nest.js がテンプレートエンジンを用いる場合に重要な設定で、テンプレートファイルが Nest.js のビルドフォルダ(通常はdist)にコピーされることを保証します。これにより、ビルド後もテンプレートファイルへのパス解決が正しく機能します。

また、"watchAssets": trueの設定は、アセット(ここでは EJS テンプレート)の変更を監視し、変更があった場合に自動的に再ビルドを行います。これにより、テンプレートを修正した際に毎回手動で再ビルドする手間が省けます。

5. Mailer Service の作成

次に、メール送信を担当する Service を作成します。mailerディレクトリ内にmailer.service.tsファイルを作成します。

// src/mailer/mailer.service.ts
import { Injectable, InternalServerErrorException } from '@nestjs/common'
import * as SendGrid from '@sendgrid/mail'
import { ConfigService } from '@nestjs/config'
import { welcomeTemplate } from './templates'

@Injectable()
export class MailerService {
  constructor(private readonly config: ConfigService) {
    const apiKey = this.config.get<string>('SENDGRID_ACCESS_KEY')
    if (!apiKey) {
      throw new Error('SENDGRID_ACCESS_KEY is not defined')
    }
    SendGrid.setApiKey(apiKey)
  }

  async send(mail: SendGrid.MailDataRequired) {
    try {
      await SendGrid.send(mail)
    } catch (error: any) {
      throw new InternalServerErrorException('SendGrid Error')
    }
  }

  async sendWelcome() {
    const name = 'iwata'
    const text = welcomeTemplate({ name })
    const msg = {
      to: 'iwata@example.com',
      from: 'noreply@example.com',
      subject: 'Welcome Mail',
      text,
    }
    this.send(msg)
  }
}

6. Mailer コントローラの作成

最後に、メール送信をトリガーするエンドポイントを作成します。mailerディレクトリ内にmailer.controller.tsを作成します。

// src/mailer/mailer.controller.ts
import { Post, Controller } from '@nestjs/common'
import { MailerService } from './mailer.service'

@Controller('mailer')
export class MailerController {
  constructor(private readonly mailerService: MailerService) {}

  @Post('/welcome')
  async sendWelcome() {
    return this.mailerService.sendWelcome()
  }
}

まとめ

以上が、Nest.js を用いて EJS テンプレートエンジンを使用し、メール送信を行う方法です。テンプレートエンジンを用いることで、メール本文の生成を柔軟かつ効率的に行うことができます。また、Nest.js の依存性注入システムを活用することで、コードの見通しも良く、メンテナンスも容易です。最後に、テスト可能な設計を心がけることで、より品質の高いシステムを構築することができます。