この記事ではGmailに届いたメールの本文をDropboxフォルダにテキストファイルとして保存する方法をご紹介します。Google APP Script(GAS)からDropboxにアップロードする方法の情報があまり出てこなかったので、忘備録を兼ねて書くことにしました。
必要なこと
- Google App Script(GAS)のセットアップ
- Dropboxアプリの作成
- PostmanからDropbox APIの「リフレッシュトークン」の取得
- GASからDropbox APIリクエストを送る
順番に詳しく説明していきます。
Google App Script(GAS)のセットアップ
まず最初にGoogle Sheetを開きます。
そして、エクステンションメニューから「Apps Script」を選択します。
すると、以下の画面になりますのでプロジェクト名を「Untitled Project」から何か適当なものに変更します。
次に、Gmailを取得する関数を書きます。
function myFunction() {
// Gmailからメールを取得
const threads = GmailApp.search('in:inbox newer_than:1d');
// 取得したメールを処理
threads.forEach(thread => {
const messages = thread.getMessages();
messages.forEach(message => {
const subject = message.getSubject(); //メール題名
const body = message.getPlainBody(); //メール本文
const date = Utilities.formatDate(message.getDate(), "Tokyo/Japan", "yyyy-MM-dd") //メールの送信時間
console.log(subject, body, date) //実行ログを出力
});
});
}
Gmailの取得には「GmailApp.search」関数を使います。関数についての詳しい説明は公式ドキュメントを参照してください。この関数の引数はGmailアプリ共通のクエリ文法が使えます。(例:in:inbox label:my-label is:unread
)
ではここで一旦確認のために実行してみます。
右上の「Deploy(デプロイ)」ボタンを押し、「New Deployment(新規デプロイ)」を選択します。
タイプから「Web app(ウェブアプリ)」を選択し名前を適当につけて「Deploy(デプロイ)」ボタンをクリックします。
続いて「Authorize Access(アクセス許可する)」ボタンをクリックします。
画面のプロンプトに従って自分のGoogleアカウントを選択すると以下のワーニングメッセージが表示されます。
ここでは青いボタンでなく、「Advanced」オプションをクリックします。
さらに「Go to <アプリ名> (unsafe)」のオプションを選択します。
すると以下の確認画面が表示されるので「Allow(許可する)」をクリックします。
すると無事デプロイが行われ以下の画面が表示されるので、「Done(終了)」で画面を閉じます。
それでは、画面上部の「Run(実行)」ボタンをクリックしてコードを実行してみましょう。
画面下部のExecution Log(実行ログ)にログが表示され、メールを取得できていることが確認できます。
Dropboxアプリの作成
Dropboxの開発者ページにログインします。
アプリの作成メニューから新しくアプリの作成を行います。
画面に従って進むと以下のページが表示されます。
今回はPostmanを使ってリフレッシュトークン(詳しくは後述)を取得していくので、Redirect URIsにはhttps://oauth.pstmn.io/v1/browser-callback
と入力します。
あとはデフォルトのままでOKです。App keyとApp secretは後で使います。
数年前からDropbox APIのアクセストークンは"short-lived"(短時間でアクセス期限切れとなるトークン)のみのサポートとなりました。詳しくはこちらのページを参照してください。
このページを見ると、
We offer a long-lived refresh_token that can be used to request a new, short-lived access token.
と書かれています。つまり、長期利用可能なリフレッシュトークンを発行し、そのリフレッシュトークンを使って短時間アクセストークンを発行する流れのようです。またtoken_access_type
をoffline
オプションとすることで、ユーザーが再承認しなくても期限切れしないリフレッシュトークンを発行できるようです(参考)。
ちなみに上記アプリページの"Generate access token"では"Generate"ボタンから短時間アクセストークン(短時間アクセストークンはsl.
から始まります)を発行可能ですが、今回は以下のステップでリフレッシュトークンを使ってAPI経由でアクセストークンを自動発行するので使いません。
- Postmanアプリから認証リクエスト(
https://www.dropbox.com/oauth2/authorize
)を送ってリフレッシュトークン(長期利用可能)を取得 - リフレッシュトークンを使ってトークンリクエスト(
https://api.dropboxapi.com/oauth2/token
)を送ってアクセストークン(short-lived)を取得 - アクセストークンを使ってアップロードリクエストによりファイルアップロードする。
参照:https://developers.dropbox.com/ja-jp/oauth-guide
PostmanからDropbox APIの「リフレッシュトークン」の取得
Postmanの新規リクエストを開いて「認可」タブに以下のように入力します。
クライアントIDとクライアントシークレットにはそれぞれApp keyとApp secretをDropboxのアプリコンソールからコピーします。Scopeにはアプリコンソールで追加したScopeを入力します。
これで、画面下の「新しいアクセストークンを取得」をクリックするとDropboxのアカウント認証画面が表示され、リフレッシュトークンを取得できます。
注意:APIキーやトークンのセキュリティは非常に重要です。PostmanのVault機能やシークレットマネージャーを利用し管理することをお勧めします。
GASからDropbox APIリクエストを送る
ここでは以下のタスクを行います。
- リフレッシュトークンを使ってアクセストークンを発行する
- メールの文面をファイルアップロードする
まず1の関数をGASに追加します。
// Dropboxのアクセストークンを発行する関数
function getDropboxAccessToken(refresh, app_id, app_secret) {
const options = {
"method": "post",
"headers": {
"Content-Type" : "application/x-www-form-urlencoded"
},
"payload": {
"refresh_token": refresh,
"grant_type": "refresh_token" ,
"client_id": app_id,
"client_secret": app_secret,
},
"muteHttpExceptions" : true
}
const response = UrlFetchApp.fetch('https://api.dropbox.com/oauth2/token', options)
console.log(response.getResponseCode())
console.log(response.getContentText())
const access_token = JSON.parse(response.getContentText()).access_token
return access_token
}
APIリクエストはUrlFetchApp.fetch
関数を使います。詳しくは公式ドキュメントを参照してください。
次にファイルをアップロードする関数です。
// Dropboxにtxtファイルを保存する関数
function saveToDropbox(dest, content, access_token) {
const uploadEndpoint = 'https://content.dropboxapi.com/2/files/upload'
const dropbox_headers = {
"Authorization" :"Bearer " + access_token,
"Content-Type" : "application/octet-stream",
"Dropbox-API-Arg" : "{\"path\":\"" + dest + "\",\"mode\":{\".tag\":\"overwrite\"}}"
}
const options = {
"method" : "post",
"headers" : dropbox_headers,
'payload' : content,
"muteHttpExceptions" : true
}
const response = UrlFetchApp.fetch(uploadEndpoint, options)
console.log(response.getResponseCode())
console.log(response.getContentText())
return response
}
完成したGASがこちら。
function myFunction() {
// Gmailからメールを取得
const threads = GmailApp.search('in:inbox newer_than:1d');
// Dropbox アクセストークン取得
const refresh_token = 'your_refresh_token'
const app_id = 'your_app_id'
const app_secret = 'your_app_secret'
const access_token = getDropboxAccessToken(refresh_token, app_id, app_secret)
// 取得したメールを処理
threads.forEach(thread => {
const messages = thread.getMessages();
messages.forEach(message => {
const subject = message.getSubject(); //メール題名
const body = message.getPlainBody(); //メール本文
const date = Utilities.formatDate(message.getDate(), "Tokyo/Japan", "yyyy-MM-dd") //メールの送信時間
console.log(subject, body, date) //実行ログを出力
// Dropbox APIでtxtファイルに保存
const dest = "/" + subject + ".txt"
const upload = saveToDropbox(dest, body, access_token)
});
});
}
// Dropboxにtxtファイルを保存する関数
function saveToDropbox(dest, content, access_token) {
const uploadEndpoint = 'https://content.dropboxapi.com/2/files/upload'
const dropbox_headers = {
"Authorization" :"Bearer " + access_token,
"Content-Type" : "application/octet-stream",
"Dropbox-API-Arg" : "{\"path\":\"" + dest + "\",\"mode\":{\".tag\":\"overwrite\"}}"
}
const options = {
"method" : "post",
"headers" : dropbox_headers,
'payload' : content,
"muteHttpExceptions" : true
}
const response = UrlFetchApp.fetch(uploadEndpoint, options)
console.log(response.getResponseCode())
console.log(response.getContentText())
return response
}
// Dropboxのアクセストークンを再発行する関数
function getDropboxAccessToken(refresh, app_id, app_secret) {
const options = {
"method": "post",
"headers": {
"Content-Type" : "application/x-www-form-urlencoded"
},
"payload": {
"refresh_token": refresh,
"grant_type": "refresh_token" ,
"client_id": app_id,
"client_secret": app_secret,
},
"muteHttpExceptions" : true
}
const response = UrlFetchApp.fetch('https://api.dropbox.com/oauth2/token', options)
console.log(response.getResponseCode())
console.log(response.getContentText())
const access_token = JSON.parse(response.getContentText()).access_token
return access_token
}
このスクリプトを実行すると、Dropboxアプリコンソールで指定したフォルダにtxtファイルが保存されます。
おまけ
GASではトリガーを設定することで、スクリプトをスケジュール実行することができます。
詳しくはこの記事がわかりやすいです。