MicrosoftのOutlookといえばビジネス利用でお世話になっている方も多いはず。
そのOutlookメールがkintone上で送受信できるサンプルです。
メリットとしては、メールをkintoneに取り込むことで、他のkintoneアプリとの連携がしやすくなります。
また、kintoneのプロセス管理機能を使用してステータスを管理できます。
Outlook側への認証にOAuth2.0を利用しています。
少し敷居が高く感じられるかもしれませんが、詳しい手順の解説とサンプルコードを公開していますのでぜひ参考にしてください。
詳しい手順の解説とサンプルコードを公開していますのでぜひ参考にしてください。
サンプルコードは
GitHub上
に公開しています。
今回の注目部分はなんといっても認証部分です!
Microsoftが提供している
MSAL.js (外部サイト)
を利用することで、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へアプリケーションを登録する必要があります。
事前に以下を行ってください。
Microsoftアカウントの取得
手順1. で取得したアカウントで
Azure Portal
へログイン
アプリケーションの登録
固定リンクがコピーされました
左メニューの「Microsoft Entra ID」を選択します。
「アプリの登録」を選択します。
「アプリケーションの登録」ボタンまたは、「新規登録」をクリックします。
次のように入力します。入力が終わったら「登録」ボタンをクリックします。
項目
値
名前
任意のアプリ名(今回は kintone×Outlook とします)
サポートされているアカウントの種類
必要に応じて、以下のいずれかを選択します。任意の施設ディレクトリ内のアカウント(任意のEntra IDディレクトリ・マルチテナント) 任意の施設ディレクトリ内のアカウント(任意のEntra IDディレクトリ・マルチテナント)と個人のMicrosoftアカウント
リダイレクトURL
「Web」 先ほど作成したkintoneアプリのURL
作成したアプリケーションで、「認証」メニューを選択します。
「暗黙の付与」の「アクセストークン」と「IDトークン」にチェックを入れ、「保存」ボタンをクリックします。
アプリケーションIDは、作成したアプリケーションの「概要」メニューで確認できます。
kintoneに適用するカスタマイズファイルで利用するので、メモしておいてください。
以上で登録は完了です。
認証時のリクエストにアクセス権のスコープを含めているため、アプリ登録画面での「Microsoft Graphのアクセス許可」の設定は不要です。
今回使用するプログラム
固定リンクがコピーされました
SAMPLE-kintone-connect-azure
サンプルプログラム一式です。
利用するプログラムファイル
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
v0.7.0
kintone REST APIを便利に扱うことができるライブラリです。
詳しくは
kintone JS SDK
を参照してください。
kintone UI Component
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』というボタンが表示されるので、ボタンをクリックします。
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に変更