Outlook 連携 - kintone から Outlook メールの送受信をしよう

目次

caution
警告

  • 2020年8月改訂のセキュアコーディング ガイドライン に抵触する内容が含まれています。
    認証情報が漏洩した場合の影響を考慮して慎重に検討してください。
    該当箇所:外部ライブラリ(MSAL.js)内のアクセストークン保存部分

  • このカスタマイズで利用している kintone JS SDK は現在推奨されていません。
    今後は kintone JavaScript Client を利用するように書き換えてください。

はじめに

Microsoft の Outlook といえばビジネス利用でお世話になっている方も多いはず。
その Outlook メールが kintone 上で送受信できるサンプルです。

メリットとしては、メールを kintone に取り込むことで、他の kintone アプリとの連携がしやすくなります。
また、kintone のプロセス管理機能を使用してステータスを管理できます。

Outlook 側への認証に OAuth2.0 を利用しています。
少し敷居が高く感じられるかもしれませんが、詳しい手順の解説とサンプルコードを公開していますのでぜひ参考にしてください。
詳しい手順の解説とサンプルコードを公開していますのでぜひ参考にしてください。

サンプルコードは GitHub上 (External link) に公開しています。

概要

今回の注目部分はなんといっても認証部分です!
Microsoft が提供している MSAL.js (外部サイト) (External link) を利用することで、Outlook(Microsoft アカウント)との OAuth2.0 を利用した認証を kintone 上で行うことができます。

連携の流れは以下となっています。

  • kintone から OAuth 認証を用いて Entra ID V2 Endpoint へサインインする。
  • kintone から Azure へアクセストークンを取得する。
  • アクセストークンを使って Graph API をたたく。
  • レスポンスを kintone のアプリに登録する。

Graph API は Microsoft Cloud サービスリソースへのアクセスを可能にする API です。

kintone アプリの作成

kintone アプリでは以下のフィールドを配置してください。

フィールド名 フィールドタイプ フィールドコード
subject 文字列(1行) subject
contents リッチエディター contents
from 文字列(1行) from
TO 文字列(1行) TO
CC 文字列(1行) CC
BCC 文字列(1行) BCC
messageId 文字列(1行) messageId
mailAccount 文字列(1行) mailAccount
attachFile 添付ファイル attachFile

こちらがアプリの配置したフィールドのフォーム画面です。

Microsoft Entra ID アプリケーションの登録

下準備

Outlook と kintone を連携させるため、Microsoft Entra ID へアプリケーションを登録する必要があります。
事前に以下を行ってください。

  1. Microsoft アカウントの取得
  2. 手順 1. で取得したアカウントで Azure Portal (External link) へログイン

アプリケーションの登録

  1. 左メニューの「Microsoft Entra ID」を選択します。

  2. 「アプリの登録」を選択します。

  3. 「アプリケーションの登録」ボタンをクリックします。

  4. 次のように入力します。入力が終わったら「登録」ボタンをクリックします。

    項目
    名前 任意のアプリ名(今回は kintone×Outlookとします)
    サポートされているアカウントの種類 必要に応じて、以下のいずれかを選択します。
    • 任意の施設ディレクトリー内のアカウント(任意の Entra ID ディレクトリー・マルチテナント)
    • 任意の施設ディレクトリー内のアカウント(任意の Entra ID ディレクトリー・マルチテナント)と個人の Microsoft アカウント
    リダイレクトURL
    • 「Web」
    • 先ほど作成した kintone アプリの URL
  5. 作成したアプリケーションで、「認証」メニューを選択します。
    「暗黙の付与」の「アクセストークン」と「ID トークン」にチェックを入れ、「保存」ボタンをクリックします。

  6. アプリケーション ID は、作成したアプリケーションの「概要」メニューで確認できます。
    kintone に適用するカスタマイズファイルで利用するので、メモしておいてください。

以上で登録は完了です。

認証時のリクエストにアクセス権のスコープを含めているため、アプリ登録画面での「Microsoft Graph のアクセス許可」の設定は不要です。

プログラムの説明

今回使用するプログラム

  • SAMPLE-kintone-connect-azure (External link)
    サンプルプログラム一式です。

  • 利用するプログラムファイル

    • common-js-functions.min.js
      • 共通処理を記述するプログラムです。
      • common ディレクトリー内にあります。
    • kintone-connect-outlook_mail_common.js
      • kintone アプリ/Microsoft アプリの設定を記述するプログラムです。
      • 環境に合わせて修正する部分があります(後述)
      • outlook-mail ディレクトリー内にあります。
    • OAuth.js
      • OAuth2.0 を利用して Azure への認証処理を行うプログラムです。
      • common ディレクトリー内にあります。
    • kintone-connect-outlook_mail.js
      • アクセストークンを用いて Outlook からメールデータを取得するプログラムです。
      • outlook-mail ディレクトリー内にあります。
  • kinotne JS SDK (External link) v0.7.0
    kintone REST API を便利に扱うことができるライブラリです。
    詳しくは kintone JS SDK を参照してください。

    • 入手方法
      1. https://github.com/kintone-labs/kintone-js-sdk (External link) にアクセスします。
      2. [Clone or download]ボタンをクリックし、zip ファイルをダウンロードします。
      3. ファイルを解凍し、「dist」下の「kintone-js-sdk.min.js」を利用します。
  • kintone UI Component (External link) v0.4.2
    kintone ライクな UI パーツを簡単に作成できるライブラリです。
    詳しくは、 「kintone UI Component v0」を使って簡単にkintoneライクなUIを設置する を参照してください。

また、今回は上記プログラム以外にライブラリとして以下を利用します。

  • MSAL.js
    Azure から OAuth 認証でアクセストークンを取得するプログラムです。
    • https://secure.aadcdn.microsoftonline-p.com/lib/1.0.0/js/msal.js
  • jQuery v3.4.1
    • https://js.cybozu.com/jquery/3.4.1/jquery.min.js
  • Sweet Alert2 v8.17.6
    • https://js.cybozu.com/sweetalert2/v8.17.6/sweetalert2.min.js
    • https://js.cybozu.com/sweetalert2/v8.17.6/sweetalert2.min.css

プログラムの修正

kintone-connect-outlook_mail_common.js を修正します。

  • アプリケーションの登録 の手順 6. でメモしておいたアプリケーション ID(7 行目)を変更してください。
  • kintone アプリのフィールドコードが kintone アプリの作成 に記載したフィールドコードと異なる場合には、28 行目〜53 行目を修正してください。
 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
// kintone-connect-outlook_mail_common.js

window.kintoneAzureConnect = {

  config: {
    auth: {
      clientId: '####################',
      authority: 'https://login.microsoftonline.com/common'
    },
    cache: {
      cacheLocation: 'localStorage',
      storeAuthStateInCookie: true
    }
  },

  graphApiScorp: {
    scopes: ['mail.read', 'mail.send']
  },

  mail: {
    mailGetUrl: 'https://graph.microsoft.com/v1.0/me/messages?$top=100',
    mailSendUrl: 'https://graph.microsoft.com/v1.0/me/sendmail'
  },

  kintone: {
    fieldCode: {

      // Field code of subject
      subject: 'subject',

      // Field code of content
      content: 'contents',

      // Field code of from
      from: 'from',

      // Field code of to
      to: 'TO',

      // Field code of cc
      cc: 'CC',

      // Field code of bcc
      bcc: 'BCC',

      // Field code of messageId
      messageId: 'messageId',

      // Field code of mailAccount
      mailAccount: 'mailAccount',

      // Field code of attachFile
      attachFile: 'attachFile'
    }
  }
};

プログラムの配置

これらのプログラムを「アプリの設定 > JavaScript/CSS でカスタマイズ」下に配置します。

プログラムの解説

kintoneイベントの処理(kintone-connect-outlook_mail.js)

kintone の各イベント処理は以下となっています。

レコード一覧画面表示イベント

 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
kintone.events.on('app.record.index.show', (event) => {

  kintoneMailService.init();

  /* create kintone ui */
  kintoneMailService.uiCreateForIndex(kintone.app.getHeaderSpaceElement());

  // 初期処理
  outlookAPI.init();

  // Singinボタン押下時
  kintoneMailService.data.ui.btnSignIn.on('click', () => {
    outlookAPI.signIn();
  });

  // Singoutボタン押下時
  kintoneMailService.data.ui.btnSignOut.on('click', () => {
    outlookAPI.signOut();
  });

  // GET MAILボタン押下時
  kintoneMailService.data.ui.btnGetmail.on('click', () => {
    outlookAPI.getMail();
  });
});

レコード詳細画面表示イベント

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
kintone.events.on('app.record.detail.show', (event) => {
  const record = event.record;

  kintoneMailService.init();

  /* create kintone ui */
  kintoneMailService.uicreateForDetail();

  // SEND MAILボタン押下時
  kintoneMailService.data.ui.btnSendmail.on('click', () => {
    outlookAPI.sendMailInit(record);
  });
});

レコード作成/編集画面表示イベント

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
kintone.events.on('app.record.create.show', (event) => {
  const record = event.record;
  kintone.app.record.setFieldShown(MESSAGE_ID_FIELD_CODE, false);
  kintone.app.record.setFieldShown(MAIL_ACCOUNT_FIELD_CODE, false);
  record[FROM_FIELD_CODE].disabled = true;
  record[FROM_FIELD_CODE].value = storage.getItem('SIGN_USER_MAILACCOUNT');
  return event;
});

// レコード編集画面の表示時
kintone.events.on('app.record.edit.show', (event) => {
  const record = event.record;
  kintone.app.record.setFieldShown(MESSAGE_ID_FIELD_CODE, false);
  kintone.app.record.setFieldShown(MAIL_ACCOUNT_FIELD_CODE, false);
  record[FROM_FIELD_CODE].disabled = true;
  return event;
});
Outlookモジュール ( kintone-connect-outlook_mail.js )

kintone と Outlook のコネクション部分を一部抜粋して説明します。

MSAL.jsのインスタンス化

userAgentApplication としてインスタンス化し、以降の処理に利用します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
const outlookAPI = {

  // 初期処理
  init: function() {

    AO.init();
    if (!kintoneMailService.isExpireAccessToken() || !kintoneMailService.isSignUserDispInfo()) {
      kintoneMailService.data.ui.kintoneCustomizeOutlookHeaderNotSigned.style.display = 'inline-block';
      kintoneMailService.data.ui.kintoneCustomizeOutlookHeaderSigned.style.display = 'none';
    } else {
      kintoneMailService.data.ui.kintoneCustomizeOutlookHeaderNotSigned.style.display = 'none';
      kintoneMailService.data.ui.kintoneCustomizeOutlookHeaderSigned.style.display = 'inline-block';
      kintoneMailService.data.ui.kintoneCustomizeOutlookUserInfo.setText(storage.getItem('SIGN_USER_MAILACCOUNT'));
      kintoneMailService.data.mail.profile.emailAddress = storage.getItem('SIGN_USER_MAILACCOUNT');
      kintoneMailService.data.isLoginOutlook = true;
    }
  }
};

Azureからトークンを取得する

サインイン処理では、まず Azure から ID トークンを取得します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    signIn: function() {
      var self = this;
      KC.ui.loading.show();

      AO.signIn().then(function(id_token) {
        self.callGraphApi();
        KC.ui.loading.hide();
      }, function(error) {
        Swal.fire({
          title: 'Error!',
          type: 'error',
          text: kintoneMailService.setting.i18n.message.error.signInFailure,
          allowOutsideClick: false
        });
        KC.ui.loading.hide();
      });
    },

    signOut: function() {
      KC.ui.loading.show();
      storage.clear();
      AO.signOut();
      KC.ui.loading.hide();
    },

そして取得した ID トークンを用いてアクセストークンを取得します。

 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
    callGraphApi: function() {
      var self = this;

      AO.callGraphApi().then(function(token) {

        var userInfo = AO.getUserInfo();

        // 「getMail」「signout」ボタンを表示
        kintoneMailService.data.ui.kintoneCustomizeOutlookHeaderNotSigned.style.display = 'none';
        kintoneMailService.data.ui.kintoneCustomizeOutlookHeaderSigned.style.display = 'inline-block';
        kintoneMailService.data.ui.kintoneCustomizeOutlookUserInfo.setText(userInfo);
        kintoneMailService.data.mail.profile.emailAddress = userInfo;
        kintoneMailService.data.isLoginOutlook = true;

        // セッションに入れておく
        storage.setItem('SESSION_KEY_TO_ACCESS_TOKEN', token.accessToken);
        storage.setItem('SIGN_USER_MAILACCOUNT', userInfo);

        KC.ui.loading.hide();

      }, function(error) {
        if (error) {
          Swal.fire({
            title: 'Error!',
            type: 'error',
            text: kintoneMailService.setting.i18n.message.error.getAccessTokenFailure,
            allowOutsideClick: false
          });
          self.userAgentApplication = null;
          KC.ui.loading.hide();
        }
      }).catch(function() {
        KC.ui.loading.hide();
      });
    },

取得したアクセストークンを用いてメールデータを取得する

GraphAPI を kintone 上で叩いて Outlook のメールデータを取得しています。
外部 API を kintone 上でたたく方法は 外部の API を実行する を確認してください。

 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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    getMail: function() {
      var self = this;
      var accessToken;
      var header;
      KC.ui.loading.show();

      if (kintoneMailService.isExpireAccessToken()) {
        accessToken = storage.getItem('SESSION_KEY_TO_ACCESS_TOKEN');
      } else {
        KC.ui.loading.hide();
        return;
      }

      header = {
        'Authorization': 'Bearer ' + accessToken,
        'Content-Type': 'application/json',
        'outlook.body-content-type': 'html'
      };

      // OutlookのINBOXからメール取得
      kintone.proxy(MAIL_GET_URL, 'GET', header, {}).then(function(res) {
        var data = JSON.parse(res[0]).value;
        if (data === undefined) {
          Swal.fire({
            title: 'ERROR!',
            type: 'error',
            text: kintoneMailService.setting.i18n.message.error.accessOutlookFailure,
            allowOutsideClick: false
          });
          KC.ui.loading.hide();
          return;
        }

        // 受信箱にメールが存在しない場合
        if (data.length === 0) {
          Swal.fire({
            title: 'WARN!',
            type: 'warning',
            text: kintoneMailService.setting.i18n.message.warning.noMail,
            allowOutsideClick: false
          });
          KC.ui.loading.hide();
          return;
        }

        // 取得したメールをkintoneへ登録
        self.putMailToKintoneApp(0, data, accessToken).catch(function(err) {
          Swal.fire({
            title: 'ERROR!',
            type: 'error',
            text: kintoneMailService.setting.i18n.message.error.addKintoneRecordFailure,
            allowOutsideClick: false
          });
          KC.ui.loading.hide();
        });
      }, function(err) {
        Swal.fire({
          title: 'ERROR!',
          type: 'error',
          text: kintoneMailService.setting.i18n.message.error.getOutlookMailFailure,
          allowOutsideClick: false
        });
        KC.ui.loading.hide();
      });
    },

    // 取得したメールをkintoneへ登録
    putMailToKintoneApp: function(index, data, accessToken) {
      var self = this;

      return this.getMessageIDIndexIsNotRetrived(index, data).then(function(indexMessage) {

        if (indexMessage === null) {
          return indexMessage;
        }
        // まだ未取得のメールを登録
        return self.addMailIntoKintone(data[indexMessage], accessToken).then(function(result) {
          // Process next mail
          if (indexMessage + 1 < data.length) {
            return self.putMailToKintoneApp(indexMessage + 1, data, accessToken);
          }
          return null;
        });
      }).then(function(resp) {
        window.location.reload();
        KC.ui.loading.hide();
      });
    }

動作確認

kintone アプリのレコード一覧画面に『Sign In Outlook』というボタンが表示されるので、ボタンをクリックします。

OAuth 認証画面が表示されるので、 Microsoft Entra ID アプリケーションの登録録 で準備した Microsoft アカウントでログインします。

メールアドレスを入力したあとにエラーが表示される場合、Microsoft アプリの設定が間違っている可能性はあります。
もう一度設定内容を確認してください。

ログインに成功した場合、先ほどまで『Sign In Outlook』だったボタンが『Receive Mail』『Sign out』に変わります。

『Receive Mail』ボタンをクリックすることで、Graph API にリクエストを投げてレスポンス(メールデータ)を kintone のレコードに登録します。

無事、Outlook のメールが kintone に登録されました。

すでに取得済み(kintone に登録済み)のメールは登録されません。

次に、送信の確認をします。

kintone のレコード追加を選択し、必要な部分を記入します。

本文は kintone のリッチエディターフィールドを利用しているので、文字色や文字サイズの変更などもできます。

レコードを保存すると、レコード詳細画面の上部に『Send Mail』というボタンが表示されるので、ボタンをクリックすればメールを送信できます。

きちんとメールが送信できたことを確認できます。

おわりに

いかがでしょうか。

Microsoft アプリの設定を事前にしておけば、kintone 上だけで Outlook のメール確認ができてしまいます!

今回は Outlook メールのみの紹介でしたが、Graph API の項目によってスケジュールやその他の機能と連携できます。

変更履歴

  • 2019/11/18
    • 以下の変更に伴い、ソースコードを修正しました。
      • 利用ライブラリの変更
        • kintone Utility Library for JavaScript → kintone JS SDK
        • kintone UI Component を追加
      • jQuery v3.2.1 から v3.4.1 に変更
      • SweetAlert2 v6.10.1 から v8.17.6 に変更
      • Microsoft Graph v1 から v2 に変更
information

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