[技術分享] 分享 Gmail 筆記 #3

繼上次的突發奇想: 分享Gmail 筆記
將這份工作分成兩個部分


1. Google script: 將 Gmail 轉 PDF 並儲存到 Google drive
2. Chrome extension: 在 Gmail 頁面放 icon 並且 post 到 script 做轉換 


首先是 Google Apps script 實做

參考了這幾篇文章


有幾個點需要注意
1. 將 Your mail subject 帶入你的標題並且在前後要加上雙引號
2. Google drive save folder 是想儲存的位置
3. Gmail 中的圖片 (inline image) 處理有點麻煩,目前的做法是從 raw 取出轉換取代進 HTML, 可以看看上面第一篇文章說明
4. 圖片上傳順序如果不是由上到下,例如打到一半回去補上圖片,轉出來的檔案會亂掉
5. 圖片太大會被截掉

function test() {
  saveGmailAsPDF('"Your mail subject"')
}

function saveGmailAsPDF(gmailSubject) {
  var driveFolder  = "Google drive save folder";
  var threads = GmailApp.search(gmailSubject, 0, 1);
  if (threads.length > 0) {
    /* Google Drive folder where the Files would be saved */
    var folders = DriveApp.getFoldersByName(driveFolder);
    var folder = folders.hasNext() ?
        folders.next() : DriveApp.createFolder(driveFolder);

    for (var t=0; t<threads.length; t++) {
      var msgs = threads[t].getMessages();
      var html = "";
      var subject = threads[t].getFirstMessageSubject();

      /* Append all the threads in a message in an HTML document */
      for (var m=0; m<msgs.length; m++) {
        var msg = msgs[m];
        html += msg.getBody();
        var attachments = msg.getAttachments();
        for (var a=0; a < attachments.length; a++) {
          var imageData;
          if (imageData = renderDataUri_(attachments[a])) {
            var re = new RegExp('src\="cid\:.*?"', 'i');
            html = html.replace(re, 'src\="' + imageData + '"');
          }
        }
      }
      /* Conver the Email Thread into a PDF File */
      var tempFile = DriveApp.createFile("temp.html", html, "text/html");
      folder.createFile(tempFile.getAs("application/pdf")).setName(subject + ".pdf");
      tempFile.setTrashed(true);
     
    }
  }
}

function renderDataUri_(image) {
  if (typeof image == 'string' && !(isValidUrl_(image) && (image = fetchRemoteFile_(image)))) {
    return null;
  }
  if (isa_(image, 'Blob') || isa_(image, 'GmailAttachment')) {
    if (image.getContentType() != null) {
      var type = image.getContentType().toLowerCase();
      var data = Utilities.base64Encode(image.getBytes());
      if (type.indexOf('image') == 0) {
        return 'data:' + type + ';base64,' + data;
      }
    }
  }
  return null;
}

function fetchRemoteFile_(url) {
  try {
    var response = UrlFetchApp.fetch(url, {'muteHttpExceptions': true});
    return response.getResponseCode() == 200 ? response.getBlob() : null;
  } catch (e) {
    return null;
  }
}

function isValidUrl_(url) {
  return /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(url);
}

function isa_(obj, class) {
  return typeof obj == 'object' && typeof obj.constructor == 'undefined' && obj.toString() == class;
}

讓大家參考看看
有需要大家可以自行取用修改

實際 export 會長這樣

























下一篇來看看 Chrome extension 怎麼做

改造 Google 服務 系列文:

留言

這個網誌中的熱門文章