SendGrid API を使ってメールを送信するプラグインを作ってみよう

著者名:門屋 亮(クローバ株式会社)

目次

こんにちは、クローバの門屋です。
kintone には通知機能が標準搭載されているので、普段メールを送信する機会はあまりありません。
それでもレコードが登録されたら kintone のユーザー以外に通知するなど、kintone からメールを送信したいという要望はあると思います。
今回はプラグインを使って、セキュアにメールを送信する方法について説明します。

SendGrid のアカウントを申し込む

kintone にはメールを送信する機能がありませんので、外部のサービスを利用してメールを送信する必要があります。
今回は SendGrid を使うことにしました。
SendGrid はアメリカの E メール配信に特化したクラウドサービスで、日本では構造計画研究所がローカライズを行っています。
国内でも有名なクラウドベンダーが SendGrid を利用していることで知られています。
基本的には有料のサービスですが、月に 12,000 通のメール送信までは無料で利用できます。

SendGrid (External link)

新規会員登録ページから、アカウントを作成します。
プランはまずは Free プランを選択してください。
2022 年 10 月時点で、登録には審査があるようです。情報は正確に入力してください。

API キーを取得する

登録が完了すると、ダッシュボードにログインできます。
「SETTING」メニューから、「API Keys」をクリックして API キーの設定画面を開きます。

Create API Key をクリックして新しい API キーを作成します。
名前はなんでもよいのですが、ここでは kintone としておきます。
生成された API キーはあとで使います。

これで SendGrid 側の準備は完了です。

プラグイン作成の準備

今回はプラグインを作成して kintone からメールを送信します。
なぜプラグインを作成するかというと、kintone のカスタマイズは JavaScript を使用するため、ブラウザーから SendGrid の API キーが見えてしまうからです。
プラグインを利用すると、ブラウザーと SendGrid との通信を kintone が中継する際に、kintone 側でヘッダーやデータに任意の情報を付加できます。
これにより、SendGrid の API キーを kintone の利用者に知られてしまうことがなくなります。

kintone プラグインの基本的な開発の手順については公開されているドキュメントを参照してください。
プラグイン 開発

ファイル構成

manifest.json

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
  "manifest_version": 1,
  "version": 1,
  "type": "APP",
  "name": {
    "ja": "SendGrid for kintone",
    "en": "SendGrid for kintone",
    "zh": "SendGrid for kintone"
  },
  "description": {
    "ja": "kintoneからSendGridを使用してメールを送信するためのプラグインです。",
    "en": "kintoneからSendGridを使用してメールを送信するためのプラグインです。",
    "zh": "kintoneからSendGridを使用してメールを送信するためのプラグインです。"
  },
  "icon": "image/image.png",
  "homepage_url": {
  },
  "desktop": {
    "js": [
      "js/desktop.js"
    ]
  },
  "config": {
    "html": "html/config.html",
    "js": [
      "js/config.js"
    ],
    "css": [
      "css/51-modern-default.css"
    ],
    "required_params": ["apiKey"]
  }
}

設定画面の実装

SendGrid の API キーを設定する設定画面を実装します。

config.html

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<div id="sendgrid-plugin-config">
  <div class="">
    <div class="kintoneplugin-row">
      <div class="kintoneplugin-label sendgrid-plugin-apikey">SendGridのAPIキー</div>
      <div class="kintoneplugin-input-outer">
        <input class="kintoneplugin-input-text" type="text" id="sendgrid-plugin-api-key">
      </div>
    </div>
    <div class="form-submit">
        <button id="sendgrid-plugin-submit" class="kintoneplugin-button-dialog-ok" type="button">     OK   </button>
        <button id="sendgrid-plugin-cancel" class="kintoneplugin-button-dialog-cancel" type="button">キャンセル</button>
    </div>
  </div>
</div>

config.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
 * SendGrid for kintone
 * Copyright (c) 2015 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */

((PLUGIN_ID) => {
  'use strict';

  const PREFIX = 'sendgrid-plugin-';
  const SENDGRID_URL = 'https://api.sendgrid.com/v3/';
  const el = function(name) {
    return document.getElementById(PREFIX + name);
  };
  // load configuration
  const proxyConfig = kintone.plugin.app.getProxyConfig(SENDGRID_URL, 'POST');

  if (proxyConfig && proxyConfig.headers.Authorization) {
    const bearer = proxyConfig.headers.Authorization;
    el('api-key').value = bearer.slice(7);
  }

  el('submit').addEventListener('click', () => {
    // save configuration
    const apiKey = el('api-key').value;
    if (!apiKey) {
      alert('APIキーを入力してください。');
      return;
    }
    const config = {apiKey: '1'};
    const headers = {};
    headers.Authorization = 'Bearer ' + apiKey;
    kintone.plugin.app.setProxyConfig(SENDGRID_URL, 'POST', headers, {}, () => {
      kintone.plugin.app.setConfig(config);
    });
  });
  el('cancel').addEventListener('click', () => {
    history.back();
  });

})(kintone.$PLUGIN_ID);

ここで注目していただきたいのが、kintone.plugin.app.setProxyConfig() を呼び出している部分です。
SendGrid の API では Authorization ヘッダーに API キーを乗せて認証する仕様になっています。
kintone.plugin.app.setProxyConfig() を実行して、指定した SendGrid の URL と POST メソッドによるプロキシ通信で Authorization ヘッダーを付与しています。

kintone.plugin.app.setProxyConfig() の詳しい仕様については、公開されているドキュメントを参照してください。
外部 API の実行に必要な情報をプラグインへ保存する

ユーザー画面の実装

ユーザー画面では、SendGrid の API 呼び出しをラップした新しいメソッドを作成します。
SendGrid の API 仕様は以下のようになっています。

V3 Mail Send API 概要 (External link)

Request
1
POST https://api.sendgrid.com/v3/mail/send HTTP/1.1
Request Body
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "personalizations": [
    {
      "to": [
        {
          "email": "john@example.com"
        }
      ],
      "subject": "Hello, World!"
    }
  ],
  "from": {
    "email": "from_address@example.com"
  },
  "content": [
    {
      "type": "text/plain",
      "value": "Hello, World!"
    }
  ]
}

今回は API キーを使用するため、api_userapi_key を指定する必要はありません。

desktop.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
/*
 * SendGrid for kintone
 * Copyright (c) 2015 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */

((PLUGIN_ID) => {
  'use strict';

  window.kintonePlugin = {};
  window.kintonePlugin.sendgrid = {
    sendMail: (to, cc, bcc, mailFrom, subject, text, html) => {
      const data = {
        personalizations: [
          {
            to: [
              {
                email: to
              }
            ],
            subject: subject
          }
        ],
        from: {
          email: mailFrom
        },
        content: [
          {
            type: 'text/plain',
            value: text
          }
        ]
      };
      if (cc) {
        data.personalizations[0].cc = [({email: cc})];
      }
      if (bcc) {
        data.personalizations[0].bcc = [({email: bcc})];
      }
      if (html) {
        data.content.push({
          type: 'text/html',
          value: html
        });
      }

      const url = 'https://api.sendgrid.com/v3/mail/send';

      return kintone.plugin.app.proxy(PLUGIN_ID, url, 'POST', {'Content-Type': 'application/json'}, data)
        .then((args) => {
          const body = args[0];
          const status = args[1];

          if (status !== 202) {
            throw new Error();
          } else {
            return body;
          }
        }).catch((err) => {
          throw new Error('メール送信に失敗しました');
        });
    }
  };
})(kintone.$PLUGIN_ID);

パッケージング

plugin-packer の手順を参考にパッケージングを行ってください。

プラグインの実行

プラグインをアプリにインストールして設定画面を開くと、このようになります。

API キーを入力して OK ボタンをクリックすると、API キーが保存されます。
実際には、以下のようなカスタマイズ JS から利用することを想定しています。

カスタマイズJS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
 * SendGrid for kintone
 * Copyright (c) 2015 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */
/* global kintonePlugin */

(() => {
  'use strict';
  // レコード登録時にメールを送信
  kintone.events.on('app.record.create.submit', (event) => {
    return kintonePlugin.sendgrid.sendMail(
      'to@mydomain.com', null, null, 'from@mydomain.com',
      'subject', 'text', null)
      .then((resp) => {
        return event;
      }).catch((err) => {
        event.error = err.message;
        return event;
      });
  });
})();

レコードを保存すると、指定したアドレスにメールが送信されます。
kintone のレコードから送信先のアドレスを指定するといった応用が可能です。

まとめ

いかがでしたでしょうか。
プラグインの開発は敷居が高いように思われるかもしれませんが、一度やってみるとそれほど難しいものではありません。
プラグイン開発で不明な点がありましたら、cybozu developer network のコミュニティで質問してみてください!

information

この Tips は、2022 年 10 月版 kintone で動作を確認しています。