Google Apps Script Why it only searches for one (first) attachment - google-apps-script

I have two codes, the first of which works and shows all attachments and the second shows only the first. "getAttachmentAndMessage" is used by several of my scripts so I need to have it in a separate function in order not to duplicate my configuration. Please help.
//this function get me all attachments
//this function is just an example of how I built my code below;
function searchEmailsData(){
var search = GmailApp.search('in:inbox newer_than:3d');
var threads = GmailApp.getMessagesForThreads(search);
for (var i = 0 ; i < threads.length; i++) {
var thread = threads[i];
for (var j = 0; j < thread.length; j++) {
var message = thread[j];
var attachments = message.getAttachments();
for (var k = 0; k < attachments.length; k++) {
var attachment = attachments[k];
Logger.log(attachment.getName());
}
}
}
}
//this functions get me only first attachment but I need all of them;
function searchEmailsData2(){
var search = GmailApp.search('in:inbox newer_than:3d');
var threads = GmailApp.getMessagesForThreads(search);
for (var i = 0 ; i < threads.length; i++) {
var thread = threads[i];
var obj = getAttachmentAndMessage(thread);
Logger.log(obj[1].getName())
}
}
function getAttachmentAndMessage(thread){
for (var j = 0; j < thread.length; j++) {
var message = thread[j];
var attachments = message.getAttachments();
for (var k = 0; k < attachments.length; k++) {
var attachment = attachments[k];
var obj = [message, attachment];
return obj;
}
}
}

In order to return not the first attachment but rather all of them, you can modify the getAttachmentAndMessage() function as follows:
function getAttachmentAndMessage(thread) {
var results = [];
for (var j = 0; j < thread.length; j++) {
var message = thread[j];
var attachments = message.getAttachments();
var obj = {'message': message, 'attachments': attachments};
results.push(obj);
}
return results;
}
The above will return a list of objects, in which each objects contains a property message, and a property attachments (which is a list of attachments).
In order to return a list containing only the attachments in the thread, you can use the following variation of the code above:
function getAttachmentAndMessage(thread) {
var results = [];
for (var j = 0; j < thread.length; j++) {
var message = thread[j];
var attachments = message.getAttachments();
results = results.concat(attachments);
}
return results;
}
Your original code
In your original getAttachmentAndMessage() code, you were using a return statement inside of the for loop. That means that upon finding the first message (first iteration of the outer loop) and upon finding its first attachment (first iteration of the inner loop) the function would simply return one value, which is a list containing the first message and its first attachment.

Related

I want to make an script to move messages to a label

`
`function moveEmailsToLabel() {
var labelName = "My Label"; // Replace with the name of the label you want to move the messages to
var label = GmailApp.createLabel(labelName);
var threads = GmailApp.search("subject:My Subject"); // Replace with the search query that returns the threads you want to move to the label
for (var i = 0; i < threads.length; i++) {
var thread = threads[i];
var messages = thread.getMessages();
for (var j = 0; j < messages.length; j++) {
var message = messages[j];
GmailApp.moveMessageToLabel(message, label); // it seems like this does not work
}
}
}``
Hello,
With app script I want to move all open threads to a label ( folder) not just mark them.
but I am not getting it right.

Google-script GmailApp search for label or nouserlabels

I'm trying to create a script that will allow me to search for e-mails and their attachments by label name or no user labels. If in searchForLabels is more than one entry, the script does not work.
function searchLabels(){
//if there is more than one entry here, the script does not work
var searchForLabels =
[
'has:nouserlabels',
'label:Test1'
];
for (var l = 0; l < searchForLabels.length; l++) {
var threads = GmailApp.search('in:inbox newer_than:4d' + searchForLabels);
var msgs = GmailApp.getMessagesForThreads(threads);
Logger.log(searchForLabels)
if (searchForLabels == 'has:nouserlabels'){
for (var i = 0 ; i < msgs.length; i++) {
for (var j = 0; j < msgs[i].length; j++) {
var message = msgs[i][j];
var from = message.getFrom();
var subject = message.getSubject();
var getAttachments = message.getAttachments();
var body = message.getPlainBody();
var getTo = message.getTo();
Logger.log(subject)
for (var k = 0; k < getAttachments.length; k++) {
var attachment = getAttachments[k];
var content = attachment.getContentType();
//rest of my code
}
}
}
}
}
}
I made two little changes over your code. After testing it, it works as you requested.
The first one is on the var threads = GmailApp.search('in:inbox newer_than:4d ' + searchForLabels[l]); line. I used the l iterator on the searchForLabels array. I used it because, reading the context of the line, it seems appropriate. This change will iterate over the tags. Forgive me if this was not your original intention.
The second change is required for the script to work. I commented out the if (searchForLabels == 'has:nouserlabels') {, because it will never be true if the searchForLabels array has more than one element. This is the error that you detected. Please, notice how the correspondent } is commented out too.
This is the final and working version of the script:
function searchLabels() {
//if there is more than one entry here, the script does not work
var searchForLabels = [
'has:nouserlabels',
'label:Test1'
];
for (var l = 0; l < searchForLabels.length; l++) {
var threads = GmailApp.search('in:inbox newer_than:4d ' + searchForLabels[l]);
var msgs = GmailApp.getMessagesForThreads(threads);
Logger.log(searchForLabels)
//if (searchForLabels == 'has:nouserlabels') {
for (var i = 0; i < msgs.length; i++) {
for (var j = 0; j < msgs[i].length; j++) {
var message = msgs[i][j];
var from = message.getFrom();
var subject = message.getSubject();
var getAttachments = message.getAttachments();
var body = message.getPlainBody();
var getTo = message.getTo();
Logger.log(subject)
for (var k = 0; k < getAttachments.length; k++) {
var attachment = getAttachments[k];
var content = attachment.getContentType();
//rest of my code
}
}
}
//}
}
}
I want to add that you can use the Gmail API on Apps Script to accomplish your request in a simple way. In particular, you can use Users.messages LIST to list all the mails with your selected tags. There you can see an example (click over JavaScript) where a function is ready to make a search. To enable this API you shall follow the guide for activating advanced services. Do not hesitate to ask for more clarifications or any question.
function searchLabels() {
var searchForLabels = [
'has:nouserlabels',
'label:Test1'
];
for (var l = 0; l < searchForLabels.length; l++) {
var threads = GmailApp.search('in:inbox newer_than:4d ' + searchForLabels[l]);
var msgs = GmailApp.getMessagesForThreads(threads);
Logger.log(searchForLabels)
if (searchForLabels[l] == 'has:nouserlabels') { //limits emails to those without tag
//if (searchForLabels[l] == 'label:Test1') { //or to those with tag
for (var i = 0; i < msgs.length; i++) {
for (var j = 0; j < msgs[i].length; j++) {
var message = msgs[i][j];
var from = message.getFrom();
var subject = message.getSubject();
var getAttachments = message.getAttachments();
var body = message.getPlainBody();
var getTo = message.getTo();
Logger.log(subject)
for (var k = 0; k < getAttachments.length; k++) {
var attachment = getAttachments[k];
var content = attachment.getContentType();
//rest of my code
}
}
}
}
}
}

Gmail App: Find threads which have a calendar entry

Some messages have calendar entries at the top of them like this:
In GScript, is there any way to find messages which have these calendar entries? If so, how does one extract the information from it?
Update
I took a lucky shot and found that it's classed as an attachment (of type ics), but there still remains the issue of extracting the data from this file...
Try this:
function getIcs(){
var threads = GmailApp.getInboxThreads();
var thread, messages, message, attachments, attachment;
var result = [];
for (var i = 0; i < threads.length; i++){
messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++){
message = messages[j];
attachments = message.getAttachments();
for (var k = 0; k < attachments.length; k++){
attachment = attachments[k];
if(attachment){
if (attachment.getContentType() == "application/ics"){
Logger.log("found ics");//continue;
result.push(message);
}
}
}
}
}
return result;
}
This method will view every thread, every message in it and every attachment in each message, and returns a list of the message objects that have an attachment of type application/ics.
UPDATE
In addition to my previous code, the following function will return an array of event objects based on the attachments found in the other method:
function getSutff(){
var msgs = getIcs();
var ics;
var position;
var eventId;
var event = [];
for (var i = 0; i < msgs.length; i++){
ics = msgs[i].getAttachments()[0].getDataAsString();
position = (ics.search("UID:")) + 4;
eventId = ics.substr(position,26);
event.push(CalendarApp.getEventById(eventId));
}
Logger.log(event)
return event;
}

Why doesn't this script collect all gmails?

I have a google app script that collects information about Gmail messages and then pastes it into a google sheet. Trouble is it doesn't get ALL of the messages. It only picks up the first one of each thread. I feel like I am missing something to loop through each thread? Any suggestions?
function getMail(){
var myspreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var mysheet = myspreadsheet.getSheetByName("Sheet3");
var start = 0;
var max = 99;
var count =0;
var row = mysheet.getLastRow()+1
var maxDate = mysheet.getRange("B1").getValue()
while(count < 4)
{
var threads = GmailApp.getInboxThreads(start , max);
var messages = GmailApp.getMessagesForThreads(threads);
var froms = [];
messages.get
for(var i = 0; i < threads.length; i++)
{
var msgDate = messages[i][0].getDate();
if(msgDate>maxDate){
froms.push([messages[i][0].getDate(),messages[i][0].getFrom(),messages[i][0].getSubject(),messages[i][0].getPlainBody()]);
}
}
if(froms.length>0){
mysheet.insertRows(2, froms.length)
mysheet.getRange(2,1,froms.length,4).setValues(froms);
}
start = start + 100;
count++;
}
}
Your current script is only grabbing messages[i][0], the first message in that group for the thread. Instead you need to loop through all of the messages using two for loops, as you can see in the script below I use messages[i][j].
function getMail() {
var mySpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var mySheet = mySpreadsheet.getSheetByName("Sheet3");
var start = 0;
var max = 99;
var count = 0;
var maxDate = mySheet.getRange("B1").getValue();
while(count < 4) {
var threads = GmailApp.getInboxThreads(start, max);
var messages = GmailApp.getMessagesForThreads(threads);
var froms = [];
for(var i = 0; i < messages.length; i++) {
for(var j = 0; j < messages[i].length; j++) {
var msgDate = messages[i][j].getDate();
if(msgDate > maxDate) {
froms.push([msgDate,messages[i][j].getFrom(),messages[i][j].getSubject(),messages[i][j].getPlainBody()]);
}
}
}
if(froms.length > 0) {
mySheet.insertRows(2, froms.length);
mySheet.getRange(2, 1, froms.length, 4).setValues(froms);
}
start = start + 100;
count++;
}
}
Notable changes:
removed var rows because it wasn't used anywhere in the script.
changed first for loop to run for messages.length rather than
threads.
added another for loop to loop through every message in
messages[i].
you were getting messages[i][0].getDate() twice, so I just used the variable already defined for adding to the array.
minor grammatical/spacing changes for consistency across script.

Gmail apps script reading mailer-daemon messages

I would like to scan all my emails in Gmail, and extract only the mailer-daemon messages (to identify rejected email addresses).
When I'm using these methods, None of the mailer-daemon messages are returned - only the "valid" messages:
var ss = SpreadsheetApp.openById("1e29xgV1UU63SJEwF2aWQpWpcXMxyiylwEMGbuvbwADw");
var sheet = ss.getSheetByName("Email Addresses");
var row = 1;
sheet.getRange(row,1).setValue("Email Addresses");
row++;
var threads = GmailApp.getInboxThreads();
for (var i = 0; i < threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
for (var j = 0 ; j < messages.length; j++) {
var txtBody = messages[i].getPlainBody();
var txtSender = messages[i].getFrom();
sheet.getRange(row,1).setValue(txtBody);
sheet.getRange(row,2).setValue(txtSender);
row++;
}
}
What can I use to process the mailer-daemon messages from the Mail Delivery Subsystem?
Thanks!
You should match the FROM: field of the message, something like:
var txtSender = messages[i].getFrom();
if (txtSender.indexOf("mailer-daemon") !== -1) {
// Log the entry in the spreadsheet
}
You should be filtering threads from the query itself, its more optimal (also paged).
function getBounced() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Bounced Addresses");
var row = 1;
var regExp = /[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,}/i // "i" is for case insensitive
var threads = GmailApp.search('from:"mailer-daemon" subject:(failure|undeliverable)', 0, 50);
for (var i = 0; i < threads.length; i++) {
var messages = GmailApp.getMessagesForThread(threads[i]);
for (var j = 0 ; j < messages.length; j++) {
var txtSubject = messages[j].getSubject();
var txtBody = messages[j].getBody();
var bouncedEmail = regExp.exec(txtBody)[0];
sheet.getRange(row,1).setValue(bouncedEmail);
sheet.getRange(row,2).setValue(txtSubject);
row++;
}
}
}
I also added a little code to extract the bounced/rejected email with a RegExp