せきやんのブログ

技術や趣味などについて書きたいことが思いついたら書いていきます。

EmailJSの体験が最高だった

はじめに

静的サイトを制作していて以下のように思ったことはありませんか?

  • 他にバックエンドを実装する気がないけど、お問い合わせは用意したい
  • でもGoogle Formを埋め込むのはなんかかっこ悪い
  • でも簡単に実装したい

僕もまさにそうでした。

そんな時に見つけたのが EmailJS というサービスです。

www.emailjs.com

なんとクライアントサイドだけで Email を送ることができるのです!
しかも JS で書けるし、React のライブラリも用意されている!!

もうこれは使うしかないでしょ!!ということで使ってみました。

開発環境

今回は TS + Next.js + Tailwind CSS で作ることにしました。実行環境は以下の通りです。

  • Node.js v15.14.0
  • yarn 1.22.10
  • typescript@3.9.3
  • next 12.0.3
  • tailwindcss ^2.2.19

実装

1. EmailJSのセットアップ

EmailJS からまずはサインアップしましょう。

f:id:sekiyan372:20211129153602p:plain
EmailJSのサイトのトップ画面

Service の設定

アカウントを作成して、ログインできたら次にどのメールサービスを使うかを登録しましょう。 「Add New Service」をクリックします。

f:id:sekiyan372:20211129154043p:plain
メールサービスの画面

使用するメールサービスを選択しましょう。今回はGmailを使用します。

f:id:sekiyan372:20211129155052p:plain
メールサービスの選択

Name と Service ID を設定しましょう。それぞれ自分が管理しやすいものを設定すれば良いです。
入力ができたら「Create Service」をクリックしましょう。サービスの認証画面にいくと思いますので、流れに沿って進めましょう。

f:id:sekiyan372:20211129155121p:plain
各値の設定

Template の設定

次にメールのテンプレートを用意しましょう。

左のメニューから 「Email Templates」を選択してください。
すでにデフォルトのテンプレートがあるので、それを編集しましょう。

f:id:sekiyan372:20211129160202p:plain
テンプレート選択画面

テンプレートは以下のようになっていると思いますので、好きなように編集しましょう!
編集をしたら「Save」ボタンで忘れずに保存をしましょう。

f:id:sekiyan372:20211129161027p:plain
テンプレート編集画面

2. 導入準備

ライブラリのインストール

以下のコマンドでライブラリを入れましょう。

$ yarn add emailjs-com

環境変数の導入

Next.jsであれば .env.local をルートディレクトリの直下作成し、3つの環境変数を設定します。
クライアント側で使用するので、先頭に NEXT_PUBLIC_をつけましょう。

Service IDは「Email Services」にて、User IDは「ntegration」にて、Template IDは「Email Templates」にて確認できます!

NEXT_PUBLIC_USER_ID=ユーザーのID
NEXT_PUBLIC_SERVICE_ID=サービスのID
NEXT_PUBLIC_TEMPLATE_ID=テンプレートのID

3. コンポーネントへ実装

フォームの作成

まずは基本的なフォームを作成しましょう。

import { ChangeEvent } from "react"
import type { NextPage } from 'next'

const Index: NextPage = () => {
  const onSubmit = (event: ChangeEvent<HTMLFormElement>) => {
    event.preventDefault()
    console.log(event)
  }

  return(
    <div className="m-8 flex justify-center items-center flex-col">
      <div className="text-5xl">Contact</div>

      <div className="md:m-10 md:w-3/4 w-11/12 ">
        <form onSubmit={onSubmit}>
          <div className="m-5">
            <label htmlFor="name" className="block">name</label>
            <input
              type="text"
              id="name"
              className="border-solid border border-black rounded w-full p-2"
            />
          </div>

          <div className="m-5">
            <label htmlFor="email" className="block">email</label>
            <input
              type="text"
              id="email"
              className="border-solid border border-black rounded w-full p-2"
            />
          </div>

          <div className="m-5">
            <label htmlFor="message" className="block">message</label>
            <textarea
              id="message"
              className="border-solid border border-black rounded w-full p-2"
              rows={5}
            />
          </div>

          <div className="text-center">
            <button
              className="border-solid border rounded p-2 bg-green-500 text-white text-xl hover:opacity-70"
            >
              送信
            </button>
          </div>
        </form>
      </div>
    </div>
  )
}

export default Index

以下のようになります!

f:id:sekiyan372:20211129171238p:plain
フォームの作成

フォームの値の State 設定する

次に、useState を使ってフォームの値を管理する State を設定します。

const [name, setName] = useState<string>('')
const [email, setEmail] = useState<string>('')
const [message, setMessage] = useState<string>('')

フォームの value に State を、onChange に setState を組み込んで、フォームの値が変わった時に State を更新するようにしましょう。

<input
  //省略
  value={name}
  onChange={(e) => setName(e.target.value)}
/>

メール送信実装

まず設定した環境変数を読み込む必要があります。
僕はこの環境変数の読み込みとその初期化を行う処理を設定ファイルを utils ディレクトリの配下に作成しました。

import { init } from 'emailjs-com'

const config = {
  userId: process.env.NEXT_PUBLIC_USER_ID,
  serviceId: process.env.NEXT_PUBLIC_SERVICE_ID,
  templateId: process.env.NEXT_PUBLIC_TEMPLATE_ID
}

if (
  config.userId !== undefined &&
  config.serviceId !== undefined &&
  config.templateId !== undefined
) {
  init(config.userId)
}

export const emailjsConfig = config

そうしたら、実際にフォームの方に送信処理を書いていきます。 まずはメール送信をする send メソッドと先程の設定ファイルをインポートしましょう。

import { send } from 'emailjs-com'
import { emailjsConfig } from '~/utils/Emailjs'

sendMail メソッドを作成し、メール送信の処理を書いていきます。
初めのif文は undefined でのエラーを解消するための処理になっています。
そして、template_param ではメールに送信される値を設定されています。この値がそのまま EmailJS のメール側に反映されるので注意しましょう。
そして、send メソッドに値を渡して送信します。この時、Stateの値をリセットするようにしています。

const sendMail = () => {
  if (
    emailjsConfig.serviceId !== undefined &&
    emailjsConfig.templateId !== undefined
  ) {
    const template_param = {
      to_name: name,
      from_email: email,
      message: message,
    }

    send(
      emailjsConfig.serviceId,
      emailjsConfig.templateId,
      template_param
    ).then(() => {
      window.alert('お問い合わせを送信致しました。')
      setName('')
      setEmail('')
      setMessage('')
    })
  }
}

上記で作成した sendMail メソッドを onSubmit の中に追加しましょう。

const onSubmit = (event: ChangeEvent<HTMLFormElement>) => {
  event.preventDefault()
  sendMail()
}

これで、送信はできるはずなので、実際にフォームに入力をしてテスト送信をしてみましょう!

実装まとめ

最後に今までのコードをまとめたものを載せておきます。

import { init } from 'emailjs-com'

const config = {
  userId: process.env.NEXT_PUBLIC_USER_ID,
  serviceId: process.env.NEXT_PUBLIC_SERVICE_ID,
  templateId: process.env.NEXT_PUBLIC_TEMPLATE_ID
}

if (
  config.userId !== undefined &&
  config.serviceId !== undefined &&
  config.templateId !== undefined
) {
  init(config.userId)
}

export const emailjsConfig = config

import { ChangeEvent, useState } from "react"
import type { NextPage } from 'next'
import { emailjsConfig } from '~/utils/Emailjs'
import { send } from 'emailjs-com'

const Index: NextPage = () => {
  const [name, setName] = useState<string>('')
  const [email, setEmail] = useState<string>('')
  const [message, setMessage] = useState<string>('')

  const sendMail = () => {
    if (
      emailjsConfig.serviceId !== undefined &&
      emailjsConfig.templateId !== undefined
    ) {
      const template_param = {
        to_name: name,
        from_email: email,
        message: message,
      }

      send(
        emailjsConfig.serviceId,
        emailjsConfig.templateId,
        template_param
      ).then(() => {
        window.alert('お問い合わせを送信致しました。')
        setName('')
        setEmail('')
        setMessage('')
      })
    }
  }

  const onSubmit = (event: ChangeEvent<HTMLFormElement>) => {
    event.preventDefault()
    sendMail()
  }

  return(
    <div className="m-8 flex justify-center items-center flex-col">
      <div className="text-5xl">Contact</div>

      <div className="md:m-10 md:w-3/4 w-11/12 ">
        <form onSubmit={onSubmit}>
          <div className="m-5">
            <label htmlFor="name" className="block">name</label>
            <input
              type="text"
              id="name"
              className="border-solid border border-black rounded w-full p-2"
              value={name}
              onChange={(e) => setName(e.target.value)}
            />
          </div>

          <div className="m-5">
            <label htmlFor="email" className="block">email</label>
            <input
              type="text"
              id="email"
              className="border-solid border border-black rounded w-full p-2"
              value={email}
              onChange={(e) => setEmail(e.target.value)}
            />
          </div>

          <div className="m-5">
            <label htmlFor="message" className="block">message</label>
            <textarea
              id="message"
              className="border-solid border border-black rounded w-full p-2"
              rows={5}
              value={message}
              onChange={(e) => setMessage(e.target.value)}
            />
          </div>

          <div className="text-center">
            <button
              className="border-solid border rounded p-2 bg-green-500 text-white text-xl hover:opacity-70"
            >
              送信
            </button>
          </div>
        </form>
      </div>
    </div>
  )
}

export default Index

まとめ

こんなに簡単にお問い合わせの実装がクライアント側のコードを少し書いただけでできるというのは本当にすごいので、ぜひ使ってみて欲しいです! 面倒なメール周りの処理を自分でやらなくていいので、爆速でメールフォームを実装しちゃいましょう!!

参考記事

zenn.dev