質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

3回答

1196閲覧

gasを使ってgmailから添付ファイルを解凍したうえで、googledriveに保存したい

pawapuro

総合スコア2

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

0クリップ

投稿2024/02/07 05:46

実現したいこと

gasを使ってgmailから添付ファイルを解凍したうえで、googledriveに保存したい

前提

gasを使って、DMARCレポートの添付ファイルを解凍したうえで、googledriveに保存できるようにしたいです。

私がプログラミングに関する知識が薄いため、様々なサイトを参考にして、試行錯誤しているのですが、うまく実現できません。

そのため、有識者の方にお力添えをいただきたく、こちらに投稿しました。
厚かましいお願いですが、よろしくお願いいたします。

参考にしたサイト
https://for-dummies.net/gas-noobs/how-to-unzip-and-save-email-attatchments-onto-drives-by-gas/
https://qiita.com/a_eau_/items/01bc14bfc5cb5ef12e64
https://sites.google.com/site/appsmatome/home/fileman/zipmelt

発生している問題・エラーメッセージ

エラー TypeError: attachments.getBlob is not a function (匿名) @ ダウンロード&解凍.gs:29 (匿名) @ ダウンロード&解凍.gs:22 downloads @ ダウンロード&解凍.gs:16

該当のソースコード

// gmailから添付ファイルのダウンロード、ドライブに保存 function downloads() { var unzipFile; //添付ファイルを保存するフォルダを取得 var folder = DriveApp.getFolderById("フォルダID"); //検索クエリを生成 var query = "is:unread Report Newer_than:1m"; //検索queryに一致するスレッドを取得 var threads = GmailApp.search(query); //各スレッド情報を取得 threads.forEach(function(thread){ //スレッド内の全てのメッセージを取得 var messages = thread.getMessages(); //各メッセージ情報を取得 messages.forEach(function(message){ //メッセージ内の全ての添付ファイルを取得 var attachments = message.getAttachments(); let date = Utilities.formatDate(message.getDate(), 'Asia/Tokyo', 'yyyyMMdd'); ########おそらくこの2行に問題あり######## var zipblob = attachments.getBlob(); unzipFile = Utilities.unzip(zipblob); ####################################### let fileName = date +'_'+ unzipFile.getName(); unzipFile.setName(fileName); //添付ファイルを指定フォルダに格納 folder.createFile(unzipFile); }); }); }

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

.getAttachmentsメソッドの戻り値のattachmentsは配列です。
.unzipメソッドは、引数に.setContentTypeFromExtension()がないとエラーになりますし、
.unzipメソッドの戻り値もunzipfileの配列です。

なので、次のようになるのではないでしょうか。
なお、圧縮されているファイル名がshift-JISだと.unzipメソッドで
予期せぬエラーが発生しますのでご注意を。

JavaScript

1 // ########おそらくこの2行に問題あり######## 2 3 // var zipblob = attachments.getBlob(); 4 attachments.forEach(function (attachment) { 5 6 // unzipFile = Utilities.unzip(zipblob); 7 unzipFiles = Utilities.unzip(attachment.setContentTypeFromExtension()); 8 9 unzipFiles.forEach(function (unzipFile) { 10 let fileName = date + '_' + unzipFile.getName(); 11 12 unzipFile.setName(fileName); 13 14 //添付ファイルを指定フォルダに格納 15 folder.createFile(unzipFile); 16 17 }); 18 }); 19 // ########修正は2行より多くなりました########

投稿2024/02/07 07:06

編集2024/02/07 07:08
YellowGreen

総合スコア868

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YellowGreen

2024/02/07 07:12

.setContentTypeFromExtension() は、 .setContentType('application/zip') とすることもできます。
pawapuro

2024/02/07 07:44

貴重なご意見ありがとうございます! いただいたコードを試してみた結果、解凍に成功しておりました!ありがとうございます! ただ、複数の添付ファイルを解凍したいのですが、解凍してダウンロードできたのは1つだけでした。 どうすれば、複数の添付ファイルを解凍できるのでしょうか? 厚かましいお願いで申し訳ありません。もう少しお付き合いいただけると、非常に助かります。
YellowGreen

2024/02/07 07:49 編集

上のコードが複数の添付ファイル対応になっていますし、 当方ではそのように動作します。(ファイル2つで確認しています。) 考えられるのは、 それぞれのforEachの範囲...});の閉じる位置が違っているとかでしょうか。 エディタで、shift + alt(option) + F でインデントを再整形してからご確認を。
pawapuro

2024/02/07 07:56

// gmailから添付ファイルのダウンロード、ドライブに保存 function downloads() { var unzipFile; //添付ファイルを保存するフォルダを取得 var folder = DriveApp.getFolderById("フォルダID"); //検索クエリを生成 var query = "is:unread Report Newer_than:1m"; //検索queryに一致するスレッドを取得 var threads = GmailApp.search(query); //各スレッド情報を取得 threads.forEach(function(thread){ //スレッド内の全てのメッセージを取得 var messages = thread.getMessages(); //各メッセージ情報を取得 messages.forEach(function(message){ //メッセージ内の全ての添付ファイルを取得 var attachments = message.getAttachments(); let date = Utilities.formatDate(message.getDate(), 'Asia/Tokyo', 'yyyyMMdd'); // var zipblob = attachments.getBlob(); attachments.forEach(function (attachment) { // unzipFile = Utilities.unzip(zipblob); unzipFiles = Utilities.unzip(attachment.setContentType('application/zip')); unzipFiles.forEach(function (unzipFile) { let fileName = date + '_' + unzipFile.getName(); unzipFile.setName(fileName); //添付ファイルを指定フォルダに格納 folder.createFile(unzipFile); }); }); }); }); } 何度もすみません。色々見なおしてみたのですが、わからず... どこか間違っているでしょうか?
pawapuro

2024/02/07 08:11

丁寧に教えていただきありがとうございました。 試したところ問題が解決しました! ベストアンサーに選ばせていただきました。
YellowGreen

2024/02/07 08:11

違いはないと思うので、 上のコードを改めてコピペして関数名を download2に変更し、 フォルダIDを書き換えて クエリを未読だけにして 圧縮ファイルを2つ(1つは中に3つのファイルを圧縮)添付した未読メールで試してみました。 フォルダには4つのファイルが解凍されましたので、 スクリプトは正常に動作していると思います。 ZIPファイルに何かあるのでしょうか。
guest

0

エラーメッセージから、Utilities.unzip() メソッドが無効な引数を受け取っていることがわかります。これは、添付ファイルのBlobをそのまま Utilities.unzip() に渡すことができないためです。
添付ファイルを解凍するためには、一時的なファイルに添付ファイルを保存し、そのファイルを解凍する必要があります。

function downloads() { var unzipFile; // 添付ファイルを保存するフォルダを取得 var folder = DriveApp.getFolderById("フォルダID"); // 検索クエリを生成 var query = "is:unread Report Newer_than:1m"; // 検索queryに一致するスレッドを取得 var threads = GmailApp.search(query); // 各スレッド情報を取得 threads.forEach(function(thread){ // スレッド内の全てのメッセージを取得 var messages = thread.getMessages(); // 各メッセージ情報を取得 messages.forEach(function(message){ // メッセージ内の全ての添付ファイルを取得 var attachments = message.getAttachments(); // 添付ファイルごとに処理 attachments.forEach(function(attachment) { // 添付ファイルを一時的に保存 var tempFile = DriveApp.createFile(attachment); // 添付ファイルを解凍 unzipFile = Utilities.unzip(tempFile.getBlob())[0]; // 最初のファイルのみを解凍すると仮定しています // 解凍後のファイル名を設定 let date = Utilities.formatDate(message.getDate(), 'Asia/Tokyo', 'yyyyMMdd'); let fileName = date +'_'+ attachment.getName(); unzipFile.setName(fileName); // 解凍したファイルを指定フォルダに格納 folder.createFile(unzipFile); // 一時的に作成したファイルを削除 tempFile.setTrashed(true); }); }); }); }

検証していませんので、エラーが出るかもしれません。

投稿2024/02/07 07:50

shoshinsha123

総合スコア215

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pawapuro

2024/02/07 08:12

ご回答していただきありがとうございました!
YellowGreen

2024/02/07 08:19

> 添付ファイルのBlobをそのまま Utilities.unzip() に渡すことができない contentTypeがapplication/x-zip-compressedになっているので application/zipにする必要があるだけです。 適切なContentTypeを設定すればattachmentをそのまま渡すことは可能ですよ。
guest

0

attachments は配列なので、それを直接 getBlob() を呼び出すことはできません。適切な添付ファイルを選択する必要があります。
Utilities.unzip() は Blob のリストを受け取りますが、ここでは Blob を直接与える必要があります。
解凍後のファイル名を設定する前に、解凍したファイルの Blob からファイル名を取得する必要があります。

// gmailから添付ファイルのダウンロード、ドライブに保存 function downloads() { var unzipFile; //添付ファイルを保存するフォルダを取得 var folder = DriveApp.getFolderById("フォルダID"); //検索クエリを生成 var query = "is:unread Report Newer_than:1m"; //検索queryに一致するスレッドを取得 var threads = GmailApp.search(query); //各スレッド情報を取得 threads.forEach(function(thread){ //スレッド内の全てのメッセージを取得 var messages = thread.getMessages(); //各メッセージ情報を取得 messages.forEach(function(message){ //メッセージ内の全ての添付ファイルを取得 var attachments = message.getAttachments(); // 添付ファイルごとに処理 attachments.forEach(function(attachment) { // 添付ファイルのBlobを取得 var zipblob = attachment.copyBlob(); // 添付ファイルを解凍 unzipFile = Utilities.unzip(zipblob)[0]; // 最初のファイルのみを解凍すると仮定しています // 解凍後のファイル名を設定 let date = Utilities.formatDate(message.getDate(), 'Asia/Tokyo', 'yyyyMMdd'); let fileName = date +'_'+ attachment.getName(); unzipFile.setName(fileName); // 解凍したファイルを指定フォルダに格納 folder.createFile(unzipFile); }); }); }); }

投稿2024/02/07 07:13

shoshinsha123

総合スコア215

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pawapuro

2024/02/07 07:40

貴重なご意見ありがとうございます! いただいたコードを試してみたのですが、以下のエラーが出てしまいました。 ちなみに矢印の右側は対象の行です。 エラー Exception: Invalid argument (匿名) @ 無題.gs:34 →unzipFile = Utilities.unzip(zipblob)[0]; // 最初のファイルのみを解凍すると仮定しています (匿名) @ 無題.gs:28 → attachments.forEach(function(attachment) { (匿名) @ 無題.gs:22 →messages.forEach(function(message){ downloads1 @ 無題.gs:16 →threads.forEach(function(thread){
pawapuro

2024/02/07 07:45

厚かましいお願いにはなりますが、なにか改善点がありましたら、教えていただけると非常に助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問