(Author : Fuji Business International Mamoru Fujinoki)
はじめに
外部からの問い合わせメールをkintoneに記録して管理するには、こちらの記事にあるようにZapier等のサービスを利用すれば、コードなしでも実現できます。
しかしながら、添付ファイルが送られて来た場合に、そういったサービスだけでは添付ファイルをkintoneにアップロードする機能はサポートされておらず、対処しきれません。
今回は、Google Apps Script (以下GAS)を使って、定期的にGmailに送られて来たメールの内容と添付ファイルをkintoneに記録するアプリの作成をします。
この方法を用いれば、例えば、ウェブサイトの問い合わせフォームの送信先をGmailに設定すれば、問い合わせの内容を添付ファイルも含め自動的にkintoneへ記録管理することが可能になります。
1. 事前に必要なもの
- Googleアカウント
- kintoneアカウント ※開発者ライセンスの取得方法はこちら
2. 開発の流れ
以上の手順で開発して行きます。
3. kintoneアプリの作成
ステップ1
kintoneでメール問い合わせのアプリを作成します。
以下のテーブルおよび画像を参照して、新規アプリを作成します。
フィールドの種類 | フィールド名 | フィールドコード |
---|---|---|
文字列(1行) | 氏名 | name |
文字列(1行) | Eメール | |
文字列(1行) | 件名 | subject |
文字列(複数行) | 内容 | message |
添付ファイル | 添付ファイル | Attachment |
ステップ2
フォーム保存後、「アプリの設定」タブに移動し、「APIトークン」をクリックします。
「生成する」ボタンをクリックして、APIトークンを生成し、「レコード追加」オプションをチェックした後、「保存」ボタンをクリックして設定を保存します。
最後に「アプリの設定」画面に戻り、「アプリを更新」ボタンをクリックして、設定を有効にします。
生成した「APIトークン」、「アプリID」(URI記載の番号)、「アプリ名」は後々コード内で使用しますので、メモしておいてください。
4. Gmail APIのGASエディタの設定
ステップ1
Google.comにてログインし、Googleアプリアイコンより、Googleドライブを選択します。
次に左上の「新規」メニューより、「その他」→「Google Apps Script」を選択します。
「Google Apps Script」がメニューにない場合、「アプリを追加」より、「Google Apps Script」を追加します。
GASのエディタが表示されますので、適当なプロジェクト名を入力します。
ステップ2
kintone APIの呼び出しには、GitHubに公開されているGoogle Apps Script Library for kintone (KintoneManager)のライブラリを使用します。
エディタのメニューより、「ライブラリ」の横の「+」ボタンを選択します。
Google Apps Script Library for kintone (KintoneManager) のREADME.mdに記載されている、「Script ID (For New editor)」の値を「スクリプト ID」欄に入力し、「検索」ボタンでライブラリを検索します。
ライブラリが表示されたら、最新のバージョンを選択し、「追加」をクリックします。
これでライブラリがプロジェクトに追加されました。
ステップ3
Gmail APIを有効にします。
「リソース」メニューより、「サービス」を選択します。
一覧より、「Gmail API」を探し、サービスを追加します。
5. GASのコーディング
以下を参考にGASスクリプトエディタにコードを書き込みます。
コードの解説
変数の定義
複数の関数で使用する変数を最初に定義します。
domainには、下記のようにご使用のアカウントのフルドメイン名を指定します。(海外アカウントの場合、例えばUSだと{サブドメイン名}.kintone.comのように指定します。)
また、上記で作成したアプリID、APIトークン、アプリ名を指定します。
sendToKintone 関数
Google Apps Script Library for kintone (KintoneManager) を使って、kintone API でレコードの生成を行います。
getGmailMessage関数
Gmailのメッセージデータを取得し、kintoneへ送信するレコードを生成します。
指定した件名で添付ファイル付の未読のすべてのメッセージのスレッドを取得します。
検索の条件のクエリーは、画面のようにGmailの検索画面にて検索オプション表示し、条件設定した後、検索すると表示されるので、これをコピーしてコード内に設定します。
取得したスレッドの全てのメッセージを取得します。
次に個々のメッセージをループし、送信するレコードのデータを取得してJSON形式のレコードを生成します。
※未読を含むスレッド内のメールすべてを取得しているため、個々のメッセージが未読であるかのチェックを行います。
添付ファイルを取得します。
「uploadAttachment」関数でファイルをkintoneにアップロードし、その際に返される「FileKey」をfileKeysArrayにpushします。
メッセージ処理後は既読に設定します。
uploadAttachment関数
Gmailから取得した添付ファイルをkintoneにアップロードします。返り値として「fileKey」が返されます。
ファイルのデータはblob形式でコピーし、XMLHttpRequestを使ってmultipart/form-data形式でPOSTします。また、ヘッダーにkintoneアプリで生成したAPIトークンを設定します。
動作確認
ステップ1
画面のようにお使いのEメールクライアントより、Gmail宛先、返信先、件名、メッセージを入力し、添付ファイルを添えて、送信します。(「返信先」を指定しないとEメール欄が空欄となります。)
宛先のGmailアカウントにメールが受信されました。(送信後、未読の状態を保つため、該当のGmailメッセージは開かないでください。)
ステップ2
次にエディタの上部のメニューより、「sendToKintone」を選択し「実行」をクリックすると、作成したプログラムが実行されます。
初めて実行するとGmailへの承認が要求されますので、許可し、該当のGmailアカウントを選択します。
以下のような警告が表示される場合がありますので、「cybozu.com(安全ではないページ)に移動」を選択してください。
さらにアクセスするスコープを許可します。
するとプログラムが実行され、エラーが無く、「Gメール問い合わせ」アプリに添付ファイル付でレコードが追加されていれば成功です。
トリガーの設定
最後にプログラムを定期的に実行するためにトリガーを設定します。
エディタのメニューより、「トリガー」を選択します。
トリガーを新規に追加し、「sendToKintone」関数を指定し、1分毎にプログラムを実行します。
設定後、保存します。
注意事項
- 添付ファイル名に日本語が含まれている場合、kintone側で文字化けしてしまうことがあります。
- 上記サンプルコード内の検索クエリーをそのままお使いいただくとGmailのメッセージを複数返信した場合、添付ファイルがなくても、kintoneにレコード登録されてしまう場合がございますのでご注意ください。
まとめ
外部サービスからレコードを追加するには、kintone APIで比較的容易に実現できますが、添付ファイルの追加には一工夫必要となります。今回のようにGmailを介して添付ファイルをkintoneにアップロードすれば、外部からメールで送られて来た添付ファイルも容易に管理できるようになるのではないでしょうか。
今回の方法を応用すれば、メール添付ファイル以外にも様々なケースで外部からkintoneへファイルをアップロードできるようになると思います。
参照
Google Apps Script Library for kintone (KintoneManager)
Advanced Google Services
Google Apps Script Gmail Service
URL Fetch Service
ファイルアップロード
ファイルアップロードで必須となる3つの手順
このTipsは、2023年4月版 kintoneで確認したものになります。
青山昌司様
お世話になっております。
cybozu developer network 運営局です。
Google Apps Script のエディタを以前のエディタにして、ライブラリの追加をお試しいただけないでしょうか。
Google Apps Script の新しいエディタでは、ライブラリを Project Key ではなく Script IDで検索する必要があるようです。
https://developers.google.com/apps-script/guides/libraries
Legacy editor:
You also need the project key of the library you are including. If you have access to the library, you can find the project key under File > Project Properties... Otherwise, you need to ask the author of the library to give you the project key.
New editor:
You need the script ID of the library you want to include. When you have access to the library, you can find the script ID on the Project Settings settings page.
お世話になります。
ついひと月前くらいからGASを使いだしたニワカですが、こちらの記事を拝見して、現在コードを書いております。
概ね完成し、メールの内容、添付ファイルはKintone上に反映することができました。
ですが、対象になるメールが受信ボックスに複数あった場合に、そのうちの一件しか反映しません。
例えば、3件あれば、1件が反映し、2件は反映が無いまま3件とも既読になってしまうという状況です。
実行間隔を1分に設定したとしても、1分の間に複数の対象メールを受信する確立は高いと想定しておりまして、対応に苦慮している状況でご質問させて頂きました。
私なりに自環境に合うようにカスタマイズしておりますので、すでに対応できていたにも関わらず、コードを消してしまったのかもしれません。
もし、上記コードにすでにそのような複数のメールを反映させるためのコードが含まれているのであればその箇所をご教示頂きたいです。
よろしくお願いいたします。
F.T 様
お世話になっております。cybozu developer network 運営でございます。
こちらで本サンプルコードの動作確認をしたところ、
対象となるメールすべてが処理されることが確認できました。getGmailMessage()関数に未読の添付ファイル付きメールをすべて取得する処理が記述されておりますので、
お手数ですがF.T様のコードを再度確認していただけますでしょうか。
また、こちらのコメント欄は記事内容のフィードバック目的となっており、
技術的なご質問は cybozu developer コミュニティをご活用ください。
cybozu Development team様
早速のご返信ありがとうございます。
やはりgetGmailMessage()関数にそういった部分も含まれているのですね。
承知いたしました。
今一度確認してみて不明点がありましたらコミュニティの方で質問させて頂きます。
ありがとうございます。
当記事の内容は、無料のGoogleアカウントでも設定可能でしょうか?
function sendtokintoneの部分(手順のsendtokintone関数)で、APItokenを入力する所がありますが、毎回ReferenceError:apitoken is not definedのエラーが出てきてしまいます。
解決方法を教えていただきたいです。
nk 様
お世話になっております。cybozu developer network 事務局です。
当記事の内容は、無料のGoogleアカウントでも設定可能です。
sendToKintone関数のAPIトークン部分は、11行目で定義した変数が記載されているかいま一度ご確認いただけますでしょうか。
apiToken と定義した変数を apitoken と記載している場合、JavaScript は大文字小文字も識別するため、エラーになっている可能性があります。
また、恐れ入りますが、こちらのコメント欄は記事内容のフィードバック目的となっております。
記事から派生した技術的なご質問は cybozu developer コミュニティをご活用ください。
よろしくお願いいたします。
matsu 様
お世話になっております。cybozu develoepr network です。
恐れ入りますが、こちらのコメント欄は記事内容のフィードバック目的となっております。
記事から派生した技術的なご質問は cybozu developer コミュニティをご活用ください。
よろしくお願いいたします。
このコードだと件名などに奇数個のbackslash \ があると JSON.parse() が失敗します。
https://cybozudev.zendesk.com/hc/ja/community/posts/15988589780377 から来ました。
私自身はGAS知らないのですが、可能なら JSON を自前で文字列加工で組み立てず、 JSON.stringify() など既製品を使うのがよいと思います。あれ、でもその後 JSON.parse() していますね。なんで苦労してJSON文字列作って JSON.parse() しているんですか?
❤ 様
お世話になっております。cybozu developer network 運営でございます。
フィードバックをいただき、ありがとうございます。
replaceCharacters 関数は、JSON 文字列を組み立てるために必要なエスケープ処理をしています。
おっしゃるとおり、自前で組み立てるよりオブジェクトを直接作るほうが効率が良さそうです。
チーム内へフィードバックし、記事の修正を検討いたします。
どうぞよろしくお願いいたします。