GoogleAppsScriptを使ってGmailをSpreadSheetにエクスポートする
2020/09/07
目次
GoogleAppsScriptを使ってGmailをSpreadSheetにエクスポートする
そのまんまですが、Google Siteから実行出来るようにしました。
https://sites.google.com/site/yamamanx/tools/gmailexporter
動作仕様
- 受信トレイのメール全てを対象に送信アドレス,受信日時,件名,本文(50,000文字まで)をSpreadSheetに出力します
- SpreadSheetは[GmailExport_YYYYMMDDhhmmss]というファイル名でGoogle Driveに新規作成します
- 出力したメールには[GmailExported]というラベルが作成されて付与されます
コード
もっとこうしたらいい、こうするべきってご意見があるとすごく嬉しく思います。
メイン処理
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 |
function gmailExport(){ var rowNumber = 2; var processedLabelName = 'GmailExported'; var subjectString = 'GmailExport'; try{ var threads = GmailApp.getInboxThreads(); if (threads.length == 0){ Browser.msgBox('処理終了', '対象のメールがありませんでした。\n終了します。', Browser.Buttons.OK); return; } var mailExportSheet = SpreadsheetApp.create(subjectString + '_' + toOriginalDateString(new Date())); var mailSheet = createMailSheet(mailExportSheet,subjectString); var processedLabel; processedLabel = createProcessedLabel(processedLabelName); for (var threadIndex in threads){ var thread = threads[threadIndex]; var messages = thread.getMessages(); for (var messageIndex in messages){ maxRateAvoid(rowNumber); var message = messages[messageIndex]; var from = message.getFrom(); var date = message.getDate(); var subject = message.getSubject(); var nbsp = String.fromCharCode(160); var body = message.getBody().replace(/<("[^"]*"|'[^']*'|[^'">])*>|nbsp/g,'').replace(/&; | /g,'').substring(1,50000); mailSheet.getRange(rowNumber,1).setValue(from); mailSheet.getRange(rowNumber,2).setValue(date); mailSheet.getRange(rowNumber,3).setValue(subject); mailSheet.getRange(rowNumber,4).setValue(body); rowNumber++; } processedLabel.addToThread(thread); } mailSending((rowNumber - 2) + "通のGmailExportが完了しました。\n" + mailExportSheet.getUrl(),subjectString); }catch(e){ mailSending((rowNumber - 1) + "通目のメールで次のエラーが発生しました。\n" + e.message,subjectString); } }; |
処理済ラベルの作成
1 2 3 4 5 6 7 8 |
function createProcessedLabel(processedLabelName){ var processedLabel = GmailApp.getUserLabelByName(processedLabelName); if (!processedLabel){ processedLabel = GmailApp.createLabel(processedLabelName); } return processedLabel; }; |
SpreadSheetの作成
1 2 3 4 5 6 7 8 9 10 11 |
function createMailSheet(mailExportSheet,subjectString){ var mailSheet = mailExportSheet.getSheets()[0]; mailSheet.setName(subjectString); mailSheet.getRange(1,1).setValue("From"); mailSheet.getRange(1,2).setValue("DateTime"); mailSheet.getRange(1,3).setValue("Subject"); mailSheet.getRange(1,4).setValue("Body"); return mailSheet; }; |
Gmailのmax rate対応
1 2 3 4 5 6 7 8 |
function maxRateAvoid(rowNumber){ if (rowNumber >= 90 && rowNumber%90 == 0){ Utilities.sleep(100000); }else{ Utilities.sleep(1000); } }; |
結果のメール送信
1 2 3 4 5 6 7 8 9 10 11 |
function mailSending(messageString,subjectString){ var user = Session.getActiveUser(); if (user){ try{ MailApp.sendEmail(user.getEmail(),subjectString,messageString); }catch(e){ Logger.log(e.message); } } }; |
ブラウザ非依存日付文字列生成
1 2 3 4 5 6 7 8 9 |
function toOriginalDateString(date){ return date.getFullYear().toString() + date.getMonth().toString() + date.getDate().toString() + date.getHours().toString() + date.getMinutes().toString() + date.getSeconds().toString(); }; |
コード解説
gmailExport
1 2 3 4 5 6 |
var threads = GmailApp.getInboxThreads(); if (threads.length == 0){ Browser.msgBox('処理終了', '対象のメールがありませんでした。\n終了します。', Browser.Buttons.OK); return; } |
GmailAppのgetInboxThreads()メソッドでメールスレッドを取得。
0件の場合スレッド配列オブジェクトは出来るのでlengthプロパティで確認。
1 2 |
var mailExportSheet = SpreadsheetApp.create(subjectString + '_' + toOriginalDateString(new Date())); |
SpreadSheetAppクラスのcreate(ファイル名)メソッドで新規SpreadSheetを作成。
1 2 3 4 5 6 7 8 9 10 |
for (var threadIndex in threads){ var thread = threads[threadIndex]; var messages = thread.getMessages(); for (var messageIndex in messages){ maxRateAvoid(rowNumber); var message = messages[messageIndex]; |
スレッド配列のループでスレッドメッセージ配列を取得。
スレッドメッセージ配列のループでメッセージオブジェクトを取得。
maxRateAvoidは後述。
1 2 3 4 5 6 |
var from = message.getFrom(); var date = message.getDate(); var subject = message.getSubject(); var nbsp = String.fromCharCode(160); var body = message.getBody().replace(/<("[^"]*"|'[^']*'|[^'">])*>|nbsp/g,'').replace(/&; | /g,'').substring(1,50000); |
MessageクラスのgetFrom(),getDate(),getSubject(),getBody()で各要素にアクセス。
除去のためString.fromCharCode(160)でreplace対象を生成。
あわせてreplace(/<(“[^”]“|'[^’]‘|[^'”>])*>|nbsp/g,”)でHTMLタグも除去。
SpreadSheetのセルの限界文字列数50,000文字に切り取り。
1 2 3 4 5 |
mailSheet.getRange(rowNumber,1).setValue(from); mailSheet.getRange(rowNumber,2).setValue(date); mailSheet.getRange(rowNumber,3).setValue(subject); mailSheet.getRange(rowNumber,4).setValue(body); |
各変数に入れたメール要素の文字列をセルに格納。
1 2 |
processedLabel.addToThread(thread); |
処理済のメールにラベルを付与する。
createProcessedLabel
1 2 3 4 5 |
var processedLabel = GmailApp.getUserLabelByName(processedLabelName); if (!processedLabel){ processedLabel = GmailApp.createLabel(processedLabelName); } |
GmailAppクラスのgetUserLabelByName(ラベル名)メソッドでラベルの有無を判定。
なければGmailAppクラスのcreateLabel(ラベル名)メソッドでラベルを作成。
createMailSheet(の作成
1 2 3 4 5 6 7 |
var mailSheet = mailExportSheet.getSheets()[0]; mailSheet.setName(subjectString); mailSheet.getRange(1,1).setValue("From"); mailSheet.getRange(1,2).setValue("DateTime"); mailSheet.getRange(1,3).setValue("Subject"); mailSheet.getRange(1,4).setValue("Body"); |
1つ目のシートにシート名を設定して1列目にタイトル行を作成。
maxRateAvoid
1 2 3 4 5 6 |
if (rowNumber >= 90 && rowNumber%90 == 0){ Utilities.sleep(100000); }else{ Utilities.sleep(1000); } |
max rateにひっかかるからsleepしなさいってエラーが発生するので、ループ1回につき1秒待つ。
それでも90メールを超えるとエラーが発生するので90メールごとに100秒待つ。
mailSending
1 2 3 4 5 6 7 8 9 |
var user = Session.getActiveUser(); if (user){ try{ MailApp.sendEmail(user.getEmail(),subjectString,messageString); }catch(e){ Logger.log(e.message); } } |
ログインユーザのオブジェクトをSessionクラスのgetActiveUser()メソッドで取得。
MailAppクラスのsendEmail(宛先,件名,本文)メソッドで送信。
スクリプトを作成したユーザと別ドメインのユーザではgetActiveUser()で何も帰らないようです。
メールアドレスとかを悪用出来ないようにしているのでしょうね。
今回はこのスクリプトをgmail.comユーザで作成しているのですが、
という事は同じAppsドメインなら同じ組織だからいいけど、
gmail.com同士はきっと他人だからだめなんでしょうね。
toOriginalDateString
1 2 3 4 5 6 7 |
return date.getFullYear().toString() + date.getMonth().toString() + date.getDate().toString() + date.getHours().toString() + date.getMinutes().toString() + date.getSeconds().toString(); |
YYYYMMDDhhmmss文字列をブラウザに依存せずに生成。
以上です。
最後までお読みいただきましてありがとうございました!
「AWS認定資格試験テキスト&問題集 AWS認定ソリューションアーキテクト - プロフェッショナル 改訂第2版」という本を書きました。
「AWS認定資格試験テキスト AWS認定クラウドプラクティショナー 改訂第3版」という本を書きました。
「ポケットスタディ AWS認定 デベロッパーアソシエイト [DVA-C02対応] 」という本を書きました。
「要点整理から攻略するAWS認定ソリューションアーキテクト-アソシエイト」という本を書きました。
「AWSではじめるLinux入門ガイド」という本を書きました。
開発ベンダー5年、ユーザ企業システム部門通算9年、ITインストラクター5年目でプロトタイプビルダーもやりだしたSoftware Engineerです。
質問はコメントかSNSなどからお気軽にどうぞ。
出来る限りなるべく答えます。
このブログの内容/発言の一切は個人の見解であり、所属する組織とは関係ありません。
このブログは経験したことなどの共有を目的としており、手順や結果などを保証するものではありません。
ご参考にされる際は、読者様自身のご判断にてご対応をお願いいたします。
また、勉強会やイベントのレポートは自分が気になったことをメモしたり、聞いて思ったことを書いていますので、登壇者の意見や発表内容ではありません。
ad
ad
関連記事
-
GoogleAppsScriptを使ってGmailの本文を解析してSpreadSheetにエクスポートする
GoogleAppsScriptを使ってGmailの本文を解析してSpreadS …
-
TikTok向けのお知らせ動画をGoogleスライドで作ってみました
2022/1/28(金)のJAWS-UG 名古屋 あけましておめでとう! セキュ …
-
自転車でナビ+記録出来るアプリ+ホルダー+バッテリー試してみた
目的 記録を蓄積して振り返りやる気を継続する 飽きないように単調にならないように …
-
共有Googleカレンダーを自分のカレンダーに追加してiPhoneに同期する
配信ライブカレンダーという共有カレンダーを作りました。 このようなGoogleの …
-
Googleナレッジパネルの認証を受けるために申請してみた
Googleでエゴサーチしていると、ナレッジパネルなるものがあることに気づきまし …
-
Google関連のAPIを試すためのGoogleSiteを作ってみました
組み込み機能で出来る事は組み込み機能で と思いまして、Googleサイトを試験的 …
-
chromium OS をインストールするためのUSBをMacで作る
別にChromeBookを購入するお金をけちるわけではないのですが。 chrom …
-
RedmineにGoogleAppsアカウントでログイン出来るようにする
RedmineのログインをGoogleアカウントで出来るように[redmine_ …
-
YoutubeチャンネルにカスタムURLを設定しました
YoutubeチャンネルのURLは初期状態では、https://www.yout …
-
redmine_omniauth_googleプラグインをRedmine3.0.0で動くようにする
redmine_omniauth_googleプラグインをインストールしたところ …