Search code examples
javascriptgoogle-apps-scriptgoogle-drive-apigmail-api

Save Gmail attachments with specific subject line in GAS/Javascript


I need help to save pdf attachments from my Gmail inbox with the specific subject line "Invoice".

I have scouted for the code online and came to the following but am having challenges in modifying it. Ideally, th code should be able to parse the email subjects looking for the word "Invoice" from any sender download attachment to specific folder to Gdrive.

I will appreciate any help in modifying the code.

function GmailToDrive(){
  var query = '';
  //filename:jpg OR filename:tif OR filename:gif OR fileName:png OR filename:bmp OR filename:svg'; //'after:'+formattedDate+
  for(var i in fileTypesToExtract){
    query += (query === '' ?('filename:'+fileTypesToExtract[i]) : (' OR filename:'+fileTypesToExtract[i]));
  }

  //ADD the only email adress you want to check + EDIT : only last 24h emails
  query = 'in:inbox has:nouserlabels ' + query + ' AND from:sender@sender AND newer_than:1d';

  var threads = GmailApp.search(query);
  var label = getGmailLabel_(labelName);
  var parentFolder;
  if(threads.length > 0){
    parentFolder = getFolder_(folderName);
  }
  var root = DriveApp.getRootFolder();
  for(var i in threads){
    var mesgs = threads[i].getMessages();
    for(var j in mesgs){

      //ADD: check if the mail is unread:
      if (mesgs[j].isUnread()) {

        var attachments = mesgs[j].getAttachments();
        for(var k in attachments){
          var attachment = attachments[k];
          var isDefinedType = checkIfDefinedType_(attachment);
          if(!isDefinedType) continue;
            var attachmentBlob = attachment.copyBlob();
            var file = DriveApp.createFile(attachmentBlob);
            parentFolder.addFile(file);
            root.removeFile(file);
          }
        }

      } // close if unread
    } // close for msg loop

    //ADD: Set thread (all mail included) as read
    GmailApp.markThreadRead(threads[i]);

    threads[i].addLabel(label);
  }
}

Solution

  • You can use search() to look for emails that are retrieved by a given query. This query follows the same format of queries done using Gmail's interface, so you can use the search options on Gmail's search bar to create the appropriate query. For example, in:inbox subject:Invoice has:attachment label:unread returns unread emails from the inbox that have attachments and the word Invoice in their subject.

    After that, you go through email threads returned by the search and by messages in each thread. Then, you get the attachments and create a file in the destination folder for each one of them. Optionally, in the end, you can mark the message as read so it doesn't get processed again if you run the script multiple times.

    function saveAttachmentsTest() {
      const destinationFolderId = 'ABC123';
      const folder = DriveApp.getFolderById(destinationFolderId);
      const emails = GmailApp.search('in:inbox subject:Invoice has:attachment label:unread');
      for (const email of emails) {
        for (const message of email.getMessages()) {
          for (const attachment of message.getAttachments()) {
            folder.createFile(attachment);
          }
          message.markRead();
        }
      }
    }