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で動作を確認しています。