MENU

GASでDrive添付ファイルを日付フォルダへ保存する方法

当ページのリンクには広告(PR)が含まれていることがあります。
GASでDrive添付ファイルを日付フォルダへ保存する方法のアイキャッチ

メールの添付ファイルをGoogle Driveの日付フォルダへ保存する場合は、対象メール、日付の基準、保存名、再実行時の重複を決めます。ここでは、GASでGmailの添付をDriveへ保存する流れを例にします。

受信箱全体を対象にせず、まずはテスト用のメールと専用フォルダへ範囲を絞ります。本文や添付に含まれる情報を、その保存先へ置いてよいかも確認します。

目次

対象と日付の基準を決める

対象は送信元、ラベル、期間などで限定します。スレッドには複数のメッセージがあるため、どのメッセージの添付を扱うかを確認します。

GmailMessageの資料では、getId、getDate、getAttachmentsを確認できます。日付フォルダをメッセージの日付の基準で作るのか、処理した日の基準で作るのかを統一します。

たとえばメッセージの日付をAsia/Tokyoで年月日へ整えるなら、Utilities.formatDateを使う方法があります。スクリプトの既定の時刻設定へ任せず、採用したタイムゾーンを記録します。

添付の種類を限定する

getAttachmentsには、本文内の画像と通常の添付を含める設定があります。署名の画像まで保存したくない場合は、includeInlineImagesをfalse、includeAttachmentsをtrueとする設計を検討します。

ファイル名だけで種類を信用せず、必要な形式とサイズを確認します。対象外の添付は勝手に削除せず、保留や対象外の記録を残します。

保存名を作る小さな例

次はファイル名の候補を作るローカル処理です。メールの取得やDriveへの書込は行いません。

function attachmentFileName(sourceId, order, originalName) {
  if (typeof sourceId !== "string" || !/^[A-Za-z0-9_-]+$/.test(sourceId) ||
      !Number.isInteger(order) || order < 1) {
    throw new Error("添付の識別情報を確認してください");
  }
  const safe = String(originalName ?? "")
    .replace(/[\\/:*?"<>|\u0000-\u001f]/g, "_").trim();
  if (!safe) throw new Error("ファイル名が空です");
  return sourceId + "_" + order + "_" + safe;
}

例として、sourceIdがDEMO01、順番が1、元の名前がreport.pdfなら、DEMO01_1_report.pdfを作ります。これは架空の命名例です。長い名前をどう扱うか、社名などを名前へ含めてよいかは、運用に合わせて決めます。

取得から保存までの最小例

次は対象のメッセージIDと、保存先フォルダIDを渡す主処理です。第3引数を省略するとGmailの読取と保存予定の確認までで返り、Driveへは書き込みません。trueを指定すると保存します。

function saveMessageAttachments(messageId, rootFolderId, write = false) {
  if (typeof write !== "boolean") throw new Error("保存の指定を確認してください");
  const message = GmailApp.getMessageById(messageId);
  const day = Utilities.formatDate(message.getDate(), "Asia/Tokyo", "yyyy-MM-dd");
  const plan = message.getAttachments({
    includeInlineImages: false, includeAttachments: true
  }).map((attachment, index) => ({
    attachment,
    name: attachmentFileName(message.getId(), index + 1, attachment.getName())
  }));
  if (!write) return { day, files: plan.map(item => item.name) };
  if (plan.length === 0) return { day, saved: [] };
  const root = DriveApp.getFolderById(rootFolderId);
  const folders = root.getFoldersByName(day);
  let folder;
  if (folders.hasNext()) {
    folder = folders.next();
    if (folders.hasNext()) throw new Error("同名の日付フォルダが複数あります");
  } else {
    folder = root.createFolder(day);
  }
  const saved = [];
  for (const item of plan) {
    const file = folder.createFile(item.attachment.copyBlob().setName(item.name));
    saved.push({ fileId: file.getId(), name: item.name });
  }
  return { day, saved };
}

GmailApp.getMessageByIdへ渡すのはスレッドIDではなくメッセージIDです。GmailAppはGmailMessageを返し、そのgetAttachmentsはGmailAttachmentの配列を返します。copyBlobで複製したBlobに保存名を付け、Folder.createFileへ渡すと、作成されたDriveのFileを受け取れます。戻り値のfileIdを保存記録へ対応させます。

この例は基準フォルダの直下にyyyy-MM-ddの日付フォルダを使います。複数一致なら保存を止めます。保存は一括で取り消せる処理ではないため、途中で失敗した場合は、既にできたファイルを確認してから再実行してください。この例には保存済み台帳の自動照合を含めていません。

原稿作成時は取得・フォルダ検索と作成・Blobの複製・保存を偽物のサービスで確認しました。実際のメール読取やDrive書込は行っていません。

日付フォルダを特定する

基準となる保存先フォルダは名前だけでなくIDで指定します。Folderの資料にあるgetFoldersByNameは、同名フォルダがないという保証ではありません。

日付フォルダが一つならそのIDを使い、なければ作成し、複数なら人が確認する設計にします。作成したフォルダIDを記録し、次回も同じ場所を参照します。

保存と完了の記録を分ける

添付を保存したら、メッセージID、添付の識別情報、保存先、作成したファイルID、確認状態を残します。ファイルができたことを確認してから完了へ進めます。

ファイル名が同じだから保存済み、と決めつけないようにします。同じ名前の異なる添付や、再送されたファイルがあるためです。添付の順番、名前、サイズ、必要に応じて内容のハッシュなど、重複を判断する基準を決めます。

時間切れで保存結果が分からない場合は、未保存と決めつけて再作成せず、Driveの結果と照合します。複数実行を使うなら、対象取得と状態の変更も管理します。

権限と再開を確認する

Gmailを読む権限とDriveへ保存する権限、定期実行の作成者を確認します。保存先の共有範囲が、元のメールより広くなっていないかも点検します。

GASの基本はGAS入門、ファイル名の扱いはファイル名をまとめて変更する考え方も参考になります。

この記事を書いた人

Watanabeのアバター Watanabe サイト運営者

2020年よりブログ開始。
SEOが思いのほか性にあっていたようで現在に至る。
モットーは「勝率の高い選択をする」
AIは活用するが吉、最後は人間が息を吹き込む。
アートと科学を追求し、日々精進。
―――
収益:6~7桁をウゴウゴ。
サイト:ペラサイト~中規模サイトまで運営中。
案件:1000円以上の案件をメインに取組中。
打ち手:ブラックSEO~ホワイトSEOまで
―――

目次