受信メールをGASでPDF出力する方法

この記事には広告を含む場合があります。記事内で紹介する商品を購入することで、当サイトに売り上げの一部が還元されることがあります。

この記事で解決できるお悩み
  • GASでPDF出力(保存)するプログラムが知りたい
  • Gmailで受信したメール内容をPDFへ出力して保存したい
  • PDFファイルをGmailに添付して送信したい
  • 上記のすべてを自動化させたい

今回は上記の課題をGoogle Apps Script(GAS)で自動化していきます。

今回実現したいこと

Gmailで受信したメール本文をPDFに出力していきます。そして、作成したPDFをメールに添付して送信します。

想定ニーズ

ではどんな時にこんなニーズがあるか。

Webサイトでお客様が入力したお問い合わせの内容をPDFにして保存しておくようなケースです。

PDFにした後はドライブに保存するなり、担当者へ添付メール送信するなり、業務フローに従って自動化させればよいです。

例えば企業サイトをwordpressで構築し、お問い合わせページにContact Form 7を使っているとします。お問合せ内容はメールで送られてきますが、それを保存しておくためにExcelやPDFに手作業で保存していたということです。その作業を自動化するといった感じです。

実際に私のクライアント企業様でこのようなニーズがあり、GASで自動化して納品しました。

それでは次項からその手順を説明していきます。

PDF出力対象のメール特定処理

PDF化するメールの抽出条件を事前に整理しておきましょう。

受信メールのすべてをPDFにすることはないと思います。

例えば、受信したメールのうち特定の件名が付いたメールをPDF化の対象にするっといった使い方が普通なはずです。

今回のサンプルでは「新規セミナー申込書の受付」という件名が付いたメールをPDF化対象としたいと思います。

googleAppsScript
function myFunction() {
  // 検索条件に該当するスレッド一覧を取得
  // 最大で50スレッドとする(スレッド内にメッセージが複数あっても1スレッド扱い。スレッド内のメールはすべて処理される)
  // 処理済みLabelが付いてないメールを対象とする
  var threads = GmailApp.search('in:inbox subject:’新規セミナー申込書の受付’ -label:処理済み',0,50);
  
  // スレッドを一つずつ取り出す
  threads.forEach(function(thread) {
    // スレッド内のメール一覧を取得
    var messages = thread.getMessages();
    
    // メールを一つずつ取り出す
    messages.forEach(function(message) {
     
       // ★このブロックにPDF化の処理を実装する
    }

  }

}

メール内容をGoogleドキュメントに出力する

メールをそのままPDFにするのではなく、googleドキュメントに一時保存してからPDFに出力します。

そうすることで任意の文字追記も可能となりますし、見栄えも変わります。

googleドキュメントをPDF化するプログラムは以下となります。

googleAppsScript
// メール本文を取得
var plainBody = message.getPlainBody();
var receiveDate = Utilities.formatDate(message.getDate(), "Asia/Tokyo", "yyyy/MM/dd HH:mm:ss");

// 本文に受信日時を追記する
var outputMes = '新規セミナー申込書の受付 / 受付日時 : '+ receiveDate + '\n\n';
outputMes += plainBody;

//Google Document へ一時ファイルとして保存
var filenameWithoutExtension = message.getSubject();
const document = DocumentApp.create(filenameWithoutExtension);
const documentId = document.getId();
document.getBody().setText(outputMes);
document.saveAndClose();

GoogleドキュメントをPDF出力する

前項で出力したgoogleドキュメントをPDFに変換します。

googleAppsScript
//Google Document から PDF としてエクスポート
const options = {
      exportFormat: "pdf",
      format: "pdf",
};
const parameters = Object.keys(options)
     .map(key => `${key}=${options[key]}`)
      .join("&");

const url = `https://docs.google.com/document/d/${documentId}/export?${parameters}`;
const response = UrlFetchApp.fetch(url, {
      "headers": {
          Authorization: `Bearer ${ScriptApp.getOAuthToken()}`,
      },
      "method": "GET",
      "Content-Type": "application/pdf",
});

const blob = response.getBlob().setName(filenameWithoutExtension + ".pdf");

//一時ファイルのgoogleドキュメントを削除
const docFile = DriveApp.getFileById(documentId);
docFile.setTrashed(true);//ゴミ箱へ
ごみ掃除を忘れずに

PDF出力のために出力したgoogleドキュメントは削除してドライブ容量を圧迫しないようにしています。

PDFをメール送信する

PDFファイルをメールに添付して担当者へ送付します。

googleAppsScript
// PDFをメールへ添付し送信する
var to = "担当者のメールアドレス";
// メールを送る
GmailApp.sendEmail(to,
       message.getSubject(), // 送信メールの件名は抽出したメール件名と同じにする
       outputMes,
       {attachments: [blob],replyTo: message.getReplyTo(), name: '送信元の表示名'})

処理したメールに処理済みフラグを立てる

最後にPDF化が成功した対象メールに処理済みフラグのタグを付与してプログラムを終わらせます。

このタグを付与しないと、何度も同じメールをPDFにしてしまいます。

googleAppsScript
// メールスレッドに処理済みラベルを付ける
var label = GmailApp.getUserLabelByName('処理済み');
thread.addLabel(label);
// 既読にする
thread.markRead();

ソースコード全容

HTML
function myFunction() {
  // 検索条件に該当するスレッド一覧を取得
  // 最大で50スレッドとする(スレッド内にメッセージが複数あっても1スレッド扱い。スレッド内のメールはすべて処理される)
  // 処理済みLabelが付いてないメールを対象とする
  var threads = GmailApp.search('in:inbox subject:’新規セミナー申込書の受付’ -label:処理済み',0,50);
  
  // スレッドを一つずつ取り出す
  threads.forEach(function(thread) {
    // スレッド内のメール一覧を取得
    var messages = thread.getMessages();
    
    // メールを一つずつ取り出す
    messages.forEach(function(message) {
      // メール本文を取得
      var plainBody = message.getPlainBody();
      var receiveDate = Utilities.formatDate(message.getDate(), "Asia/Tokyo", "yyyy/MM/dd HH:mm:ss");

      // 本文に受信日時を追記する
      var outputMes = '新規セミナー申込書の受付 / 受付日時 : '+ receiveDate + '\n\n';
      outputMes += plainBody;


      //Google Document へ一時ファイルとして保存
      var filenameWithoutExtension = message.getSubject();
      const document = DocumentApp.create(filenameWithoutExtension);
      const documentId = document.getId();
      document.getBody().setText(outputMes);
      document.saveAndClose();

      //Google Document から PDF としてエクスポート
      const options = {
            exportFormat: "pdf",
            format: "pdf",
      };
      const parameters = Object.keys(options)
           .map(key => `${key}=${options[key]}`)
            .join("&");

      const url = `https://docs.google.com/document/d/${documentId}/export?${parameters}`;
      const response = UrlFetchApp.fetch(url, {
            "headers": {
                Authorization: `Bearer ${ScriptApp.getOAuthToken()}`,
            },
            "method": "GET",
            "Content-Type": "application/pdf",
      });

      const blob = response.getBlob().setName(filenameWithoutExtension + ".pdf");

      //一時ファイルのgoogleドキュメントを削除
      const docFile = DriveApp.getFileById(documentId);
      docFile.setTrashed(true);//ゴミ箱へ
      
   // PDFをメールへ添付し送信する
      var to = "担当者のメールアドレス";
      // メールを送る
      GmailApp.sendEmail(to,
                        message.getSubject(), // 送信メールの件名は抽出したメール件名と同じにする
                        outputMes,
                        {attachments: [blob],replyTo: message.getReplyTo(), name: '送信元の表示名'})


    });
    
    // スレッドに処理済みラベルを付ける
    var label = GmailApp.getUserLabelByName('処理済み');
    thread.addLabel(label);
    // 既読にする
    thread.markRead();
  });
}

定期実行のトリガー設定

最後に作成したGASを時間ベースのトリガーに定義します。こうすることで、すべてが自動化されます。

サンプルでは1時間おきに定期実行してスクリプトを実行しています。

どのくらいの周期で実行するかは各々が定義してください。

まとめ

クライアント企業様の目視・手作業だった仕事がこのGASでフル自動化となりました。

ITを使って業務効率化を図れたのでとても喜んでいただけました。