Google App Script(GAS)로 이메일을 추출하여 SpreadSheet으로 내보내기

하고 싶은 일



Gmail에서 'ML/alert'라는 라벨이 붙은 어제의 메일을 추출하고, From과 To에서 제외하고 싶은 것과 중복을 제외하고, SpreadSheet에 From, To, Subject의 일람을 내보내고 싶다.

준비



'제외'라는 이름의 시트를 만들고 제외하고 싶은 From과 To의 쌍을 쓴다.
(To가 비어 있으면 To에 관계없이 제외)


코드


function getMail() {
  var label = 'ml-alert';
  var fromDate = getDate(1);
  var toDate = getDate(0);
  var query = 'label:' + label + ' after:' + (fromDate.getTime() / 1000) + 'before:' + (toDate.getTime() / 1000);

  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var exceptionSheet = ss.getSheetByName('除外');
  var exceptions = exceptionSheet.getRange(1, 1, exceptionSheet.getLastRow(), 2).getValues();

  var threads = GmailApp.search(query);
  var data = [];
  threads.forEach(function(thread) {
    var messages = thread.getMessages();
    messages.forEach(function(message) {
      var date = message.getDate();
      if (date < fromDate || toDate < date) {
        // 対象の日付じゃないのでスルー
        return;
      }
      var from = message.getFrom().replace(/^.*<(.*?)>.*$/, '$1');
      var toArr = message.getTo().split(/,\s*/);
      // 除外シートから除外対象を探す
      var fromFinder = exceptionSheet.createTextFinder(from);
      block_check: {
        while (range = fromFinder.findNext()) {
          if (range.getColumn() != 1) {
            // 1列目じゃないので次へ
            continue;
          }
          var foundRow = exceptions[range.getRow() - 1];
          if (foundRow[1] == '') {
            // Toが指定されていないのでそのまま除外
            break block_check;
          }
          for (var i = 0; i < toArr.length; i++) {
            if (toArr[i] === foundRow[1]) {
              // Toが一致するので除外
              break block_check;
            }
          }
        }
        // 除外対象ではないのでdata配列に保存
        var subject = message.getSubject();
        data.push([from, toArr.join(), subject]);
      }
    });
  });

  if (data.length) {
    // 対象のメールがあったら日付のシートに書き出す
    var ymd = fromDate.getFullYear() + '/' + (fromDate.getMonth() + 1) + '/' + fromDate.getDate();
    var sheet = ss.getSheetByName(ymd);
    if (sheet) {
      // すでにシートがある場合は内容を削除
      sheet.clearContents();
    } else {
      // シートを新規作成
      sheet = ss.insertSheet(ymd, 0);
      sheet.setColumnWidths(1, 2, 190).setColumnWidth(3, 500);
      sheet.setFrozenRows(1);
    }
    sheet.getRange("A1:C1").setValues([['From', 'To', 'Subject']]);
    var range = sheet.getRange(2, 1, data.length, 3);
    range.setValues(data);
    range.removeDuplicates();
    range.sort([1, 2, 3]);
  }
}

/* days日前の午前0時のDateオブジェクトを返す */
function getDate(days) {
  var date = new Date();
  date.setDate(date.getDate() - days);
  date.setHours(0, 0, 0, 0);
  return date;
}

포인트


  • GmailApp.search(query)의 query에서 중첩 된 레이블은 "-"로 연결됩니다.
  • GmailApp.search(query)는 스레드를 검색하므로 날짜를 지정해도 대상이 아닌 항목이 포함되므로 메시지 단위로 날짜를 확인합니다.
  • 중복은 모두 시트에 내 보낸 후 removeDuplicates() 에서 제거한다
  • createTextFinder() 를 사용했지만 exceptions 배열을 차례로 보는 것도 처리할 수 있습니다. (그리고, 그쪽이 간단한 생각이 듭니다만, 모처럼이므로 사용예라고 하는 것으로…)

    좋은 웹페이지 즐겨찾기