0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ReScriptでEmailJSからメールを出す

Last updated at Posted at 2024-06-27

EmailJSの準備

以下を参考にアカウントを作成し、mail serviceとmail templateを設定します。

今回はemail_templateを

email_template
{{message}}
{{user_name}} ({{user_email}})

としています。

npmパッケージのインストール

ReScriptのインストール
npm create rescript-app@latest
EmailJSのインストール
cd emailjs-test
npm install --save-dev @emailjs/browser

ReScriptをインストールするときのプロジェクト名をemailjs-testにしたので、そのディレクトリに移動してからEmailJSをインストールします。

作成するファイル

emailjs_test.html
<!DOCTYPE html>
<html>
<head>
    <title>Contact Form</title>
</head>
<body>
    <form id="contact-form">
        <label> 名 前 </label>
        <input id="user_name" type="text" name="user_name">
        <br><br>
        <label> メール </label>
        <input id="user_email" type="email" name="user_email">
        <br><br>
        <label>メッセージ</label>
        <textarea id="message" name="message"></textarea>
        <br><br>
        <input type="submit" value=" 送 信 ">
    </form>
    <script type="module" src="EmailJsTest.res.mjs"></script>
</body>
</html>
EmailJsTest.res
type publicKey = { publicKey: string }
type sendObject = {
  user_name: string,
  user_email: string,
  message: string
}
@module("@emailjs/browser") external init: publicKey => unit = "init"
@module("@emailjs/browser") external send: (string, string, sendObject) => promise<'a> = "send"

@send external getElementById: (Dom.document, string) => Dom.element = "getElementById"
@send external addEventListener: (Dom.element, string, Dom.event => unit) => unit = "addEventListener"
@get external getValue: Dom.element => string = "value"
@send external preventDefault: Dom.event => unit = "preventDefault"

let onBtnClick = (event) => {
  event->preventDefault

  let user_name = document->getElementById("user_name")->getValue
  let user_email = document->getElementById("user_email")->getValue
  let message = document->getElementById("message")->getValue
  let send_object = {
    user_name: user_name,
    user_email: user_email,
    message: message
  }

  // these IDs from the previous steps
  send("service_id", "template_id", send_object)
    ->Promise.thenResolve(() => { Console.log("SUCCESS!") })
    ->Promise.catch((error) => {
      Console.log2("FAILED...", error)
      Promise.resolve()
    }
  )->ignore
}

// https://dashboard.emailjs.com/admin/account
init({ publicKey: "YOUR_PUBLIC_KEY" });
document->getElementById("contact-form")->addEventListener("submit", onBtnClick)
ディレクトリ構成
emailjs-test/
└── src/
    ├── emailjs_test.html
    └── EmailJsTest.res

ビルドして実行

ビルド
npm run res:build

ブラウザで確認するとエラーが出ます

TypeError: Failed to resolve module specifier "@rescript/core/src/Core__Promise.res.mjs". Relative references must start with either "/", "./", or "../".Understand this error

モジュールが見つけられないようです。

Parcelでバンドル

Parcelのインストール
npm install --save-dev parcel
Parcelでバンドル
npx parcel build src/EmailJsTest.res.mjs
ディレクトリ構成
emailjs-test/
├── dist/
│   ├── EmailJsTest.res.mjs
│   └── EmailJsTest.res.mjs.map
└── src/
    ├── emailjs_test.html
    ├── EmailJsTest.res
    └── EmailJsTest.res.mjs

再実行

読み込むJSファイルを変更します。

emailjs_test.html
<script type="module" src="../dist/EmailJsTest.res.js"></script>

下のようなページが表示され、入力して「送信」を押すとメールが送られます。

See the Pen Untitled by sgigagaeru (@sgigagaeru) on CodePen.

EmailJsTest.resでやっていること

@emailjs/browswerのバインド

@emailjs/browserinitsendを用いたので、それをバインドします。
initObjectを引数に取って、unitを返します。
ここではObject{ publicKey: "YOUR_PUBLIC_KEY" }に決まっているので、それを型にしました。

EmailJsTest.res
type publicKey = { publicKey: string }
@module("@emailjs/browser") external init: publicKey => unit = "init"

send(string, string, Object)を引数にとって、promiseを返します。
Objectはここでは固定なので型にしました。

EmailTestJs.res
type sendObject = {
  user_name: string,
  user_email: string,
  message: string
}
@module("@emailjs/browser") external send: (string, string, sendObject) => promise<'a> = "send"

onBtnClickの処理

「送信」ボタンが押されるとonBtnClickが呼び出されます。
まずデフォルトの処理を無効化します。これでページの遷移も防がれます。

EmailTestJs.res
event->preventDefault

インプットフォームの値を読み取って、送信するオブジェクトを作ります。

EmailTestJs.res
let user_name = document->getElementById("user_name")->getValue
let user_email = document->getElementById("user_email")->getValue
let message = document->getElementById("message")->getValue
let send_object = {
  user_name: user_name,
  user_email: user_email,
  message: message
}

sendで送ります。

EmailTestJS.res
send("service_id", "template_id", send_object)
  ->Promise.thenResolve(() => { Console.log("SUCCESS!") })
  ->Promise.catch((error) => {
    Console.log2("FAILED...", error)
    Promise.resolve()
  }
)->ignore

ReScriptのPromise.catchcatch(promise, errorCallback)の形になります。そしてerrorCallbackcatchの第一引数と同じ型のpromiseを返さないといけません。なので最後にPromise.resolve()を付けてpromiseを返しています。
Promise.thenも同様で、then(promise, callback)の形で、callbackpromiseを返します。なのでcallbackの最後にPromise.resolve()を付けます。
thenResolveを用いると余計なPromise.resolve()を書かなくて良いので、そちらを用いています。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?