Gmail apps script edit body before forwarding - google-apps-script

I'm using Gmail apps script to forward emails with a certain label ... But I'd like to edit the body of the message prior to forwarding.
function fwdFB(){
var label = GmailApp.getUserLabelByName('fb');
var threads = label.getThreads();
for(var m in threads){
var messages = threads[m].getMessages();
for(var y in messages){ messages[y].forward('w#yahoo.com',{from:'webmaster#gmail.com'}) }
threads[m].moveToTrash();
}
}
I'm unclear as to how to insert the getBody() method to edit the message. (Specifically, I want to delete a certain HTML chunk from the message. It's the same chunk in each message.)

The options of forward(recipient, options) do not offer an endpoint to modify the message body. You'll have to do it instead manually, by sending a message after modifying the body as desired.
Sample:
function fwdFB(){
var label = GmailApp.getUserLabelByName('fb');
var threads = label.getThreads();
for(var m in threads){
var messages = threads[m].getMessages();
for(var y in messages){
var oldBody = messages[y].getBody();
var newBody = oldBody.substring(1, 10)+" PS: This is a modification."
var oldSubject = messages[y].getSubject();
var newSubject = "Fwd: "+ oldSubject;
GmailApp.sendEmail('w#yahoo.com', newSubject, newBody, {from:'webmaster#gmail.com'})
}
threads[m].moveToTrash();
}
}
UPDATE
If it is important for you to preserve the message history, you need to perform additional steps to thread the message.
#tehhowch provides a good example of how to do so.

Related

Extract Inline images from Gmail Body

I am trying to extract all the images store in Inline body of email, store it in drive folder.
I am tryin to use this code
function GETGMEmails(){
var label = GmailApp.getUserLabelByName ('WHOLESALE REP');
var threads = label.getThreads();
for(var i = threads.length - 1; i >= 0; i--){
var messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++){
var message = messages[j];
// extractDetails(message,folder)
fetchInlineImage(message)
}
}
}
function fetchInlineImage(message) {
var msg = message;
console.log(message)
var pattern = /<img.*src="([^"]*)"[^>]*>/;
var matches = pattern.exec(msg.getBody());
console.log(matches.length)
if(matches) {
var url = matches[1];
var urlPattern = /^https*\:\/\/.*$/;
// If this matches, that means this was copied and pasted from a browser and it's a
// standard URL that we can urlFetch
if(urlPattern.exec(url)) {
// NO OP!
} else {
// Else this means the user copied and pasted from an OS clipboard and the image
// exists on Google's servers. The image can only be retrieved when logged in. Fortunately,
// if we use URLFetchApp, this will act as a logged in user and be able to URLFetch the image.
// We'll need to prepend a Gmail URL (subject to change)
url = "https://mail.google.com/mail/u/0/" + url;
}
// TODO - there is one more case that we're not covering - embedded images that newsletters use
Logger.log("Fetching image from URL: " + url);
var response = UrlFetchApp.fetch(url);
Logger.log("Response status: " + Utilities.jsonStringify(response.getHeaders()));
var blob = response.getBlob();
Logger.log("Response blob: " + blob.getBytes().length);
Drivefolder.createFile(blob).setName('ss.jpeg')
}
};
Email look like this, with lot of images here and there, and I want to extract each one of them:-
enter image description here
You are trying to access inline images from a GMail message.
When GMail was first introduced there was no ability to access inline images.
In 2012 an Issue:Access to inline images was raised and the script shown in the question was proposed as a workaround. A question was also asked on StackOverflow Parsing inlineImages from Gmail raw content.
These (and some variants) worked for a few years until 2014 when a second Issue:GmailApp.getAttachments Issue was raised.
Workarounds were patchy until 2017 when it was announced that the Issue had been resolved.
In 2018, a new answer was added to the StackOverFlow question. and in 2022 a new StackOverflow question How can I extract inline images from a Gmail email? (all available workarounds do not work anymore) was asked and answered.
In short, the script that you are using is redundant. However, the process to access inline images is simple and straightforward. The key is to examine the body by Regex.
The following script provides a basis for you to identify and log inline images.
Put headers in row 1 of sheet="Images".
A1="ID", B1="Subject", C1="Image"
function so75327302() {
var label = GmailApp.getUserLabelByName ('WHOLESALE REP');
var threads = label.getThreads();
for (var i=0;i<threads.length;i++){
var messages = threads[i].getMessages()
for (m=0;m<messages.length;m++){
// Logger.log("DEBUG: i:"+i+",m:"+m+", subject:"+messages[m].getSubject()+", message ID:"+messages[m].getId())
var body = messages[m].getBody()
var regex1 = RegExp('<img src="([^"]*)"[^>]*>', 'g')
var array1 = new Array
var images = new Array
while ((array1 = regex1.exec(body)) !== null) {
Logger.log("message ID:"+messages[m].getId()+", Subject: "+messages[m].getSubject()+" contains inline images."+ `Found ${array1[0]}`);
images.push([array1[0]])
}
if (images.length > 0){
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheetName = "Images"
var sheet = ss.getSheetByName(sheetName)
var imageLR = sheet.getLastRow()
sheet.getRange(imageLR+1,1).setValue(messages[m].getId())
sheet.getRange(imageLR+1,2).setValue(messages[m].getSubject())
sheet.getRange(imageLR+1,3,images.length).setValues(images)
}
}
}
}

Recent email of the thread - Gmail

Can anyone help me with a query that I can use to extract data from my Gmail?
Here are the requirements,
Date range, so I can select a specific date
Subject of the email
Date of the email
Body of recent email of the thread
Sender of the recent email of the thread
Receiver of the recent email of the thread
var ui = SpreadsheetApp.getUi();
function onOpen(e) {
ui.createMenu("Gmail Manager").addItem("Get Emails", "getEmails").addToUi();
}
function getEmails() {
const threads = GmailApp.getInboxThreads();
for (let i = 0; i < threads.length; i++) {
const msgs = threads[i].getMessages();
const lastmsg = msgs[msgs.length - 1];
var firstmessage = thread.getMessages()[0];
var recentmessagesender = firstmessage.getFrom();
var recentMessageSubject = thread.getFirstMessageSubject();
}
}
If you want to retrieve the recent message of each thread, you can try this:
Code
function getEmails() {
let threads = GmailApp.getInboxThreads();
for (let i=0; i< threads.length; i++) {
let thread = threads[0];
let messages = thread.getMessages();
let recentMessage = messages[0];
let recentMessageSender = recentMessage.getFrom();
let recentMessageReceiver = recentMessage.getTo();
let recentMessageSubject = recentMessage.getSubject();
let recentMessageDate = recentMessage.getDate();
let recentMessageBody = recentMessage.getPlainBody();
}
}
Explanation
The above snippet gathers all the threads and then for each thread it retrieves the first message, this being denoted by the messages[0]. Afterwards, the sender, received, subject, date and body are retrieved using the specific methods for the GmailMessage object.
However, depending on what exactly you plan on doing with the information obtained, you can either use :
console.log in order to display it to the logger
OR if you want to write it to the spreadsheet, you will have to
use the SpreadsheetApp service, something similar to this:
// add this outside the `for` loop
let activeSheet = SpreadsheetApp.getActiveSheet();
// add this inside the `for` loop
activeSheet.getRange(i+1,1).setValue(recentMessageSender);
activeSheet.getRange(i+1,2).setValue(recentMessageReceiver);
When writing to the spreadsheet, you will have to take into account the range you want to paste the date onto. In the above example, the first row will correspond to the first message of the first thread, the second row will correspond to the first message of the second thread and so on.
Reference
Apps Script GmailMessage Class;
Apps Script Sheet Class - getRange();
Apps Script Range Class - setValue().

Fill Google form using Google Apps Script

I just tried my coding below...but the problem is, my google apps script just submit the form with blank value for both "short answer" field. Can someone show me somelight how i can solve my problem. TQ.
function myFunction() {
var dapatkanForm = FormApp.openByUrl('https://docs.google.com/forms/d/1S1F3cKMwkXm3gVt00RegQ-GCzRfELOq74IH9WEk8SlU/edit?usp=sharing');
var nama = dapatkanForm.getTitle();
var listIsiText = dapatkanForm.getItems(FormApp.ItemType.TEXT);
var panjangArray = listIsiText.length;
for(var i=0; i<panjangArray; i++)
{
var textTemp = listIsiText[i];
var nakSet = textTemp.asTextItem();
var response = nakSet.createResponse('MOHD ANIS BIN AZINAN');
}
var formResponse = dapatkanForm.createResponse();
formResponse.submit();
Logger.log(nama);
}
Your code is very close to the solution. You just need one additional method. The following line…:
var formResponse = dapatkanForm.createResponse();
…should end up looking like:
var formResponse = dapatkanForm.createResponse().withItemResponse(response);
By using .withItemResponse() the form submit will upload your responses instead of being void. Please, ask me for more clarifications if you still need help.

Getting the body of individual emails from gmail to google sheets

I'm really new at using Google Apps Script, so if what I'm trying doesn't make sense, or just isn't possible please let me know.
Everyday I get several emails that look like the following:
Your Name: FirstName LastName
Phone Number: 555 867 5309
Email Address: FakeEmail#email.com
What do you need help with? Request someone makes.
I'm attempting to automatically send the body of these emails to a new line in a Google Sheet when they come in.
As of right now I have every email get the label "myLabel" when it comes in. I then run the following script, which is a slightly modified version of something I found here:
function myFunction() {
var ss = SpreadsheetApp.getActiveSheet();
var label = GmailApp.getUserLabelByName("MyLabel");
var threads = label.getThreads();
for (var i=0; i<threads.length; i++)
{
var messages = threads[i].getMessages();
for (var j=0; j<messages.length; j++)
{
var msg = messages[j].getBody();
ss.appendRow([msg])
}
threads[i].removeLabel(label);
}
}
I'm attempting to run this code with a timer trigger every 15 minutes. The issue I've run into is that every time the code runs it pulls from every email in the thread. I would like it to just pull from the emails that are new since the last time it ran. Any advice would be greatly appreciated.
Why not mark the messages as read when you finish processing them? Here is a sample from one of my scripts.
var pendingEmailLabel = "MyLabel";
var threads = GmailApp.getUserLabelByName(pendingEmailLabel).getThreads();
for (var t = 0; t < threads.length; ++t) {
var thread = threads[t];
var messages = thread.getMessages();
for (var m = 0; m < messages.length; ++m) {
var message = messages[m];
if (message.isUnread()) {
// INSERT YOUR CODE HERE THAT TAKES ACTION ON THE MESSAGE
message.markRead();
}
}
}
}

GmailApp and forward/reply Invoked too many times - Not clear why (plus movetoarchive not working)

I am using the following two scripts to either reply to or forward emails when certain labels are applied. I have two sheets (replySheet and forwardSheet) that hold label names in the first column. replySheet then has the email reply text in the next cell, while forwardSheet has the email address to forward the message to.
Two questions:
I have received the error message "Service invoked too many times for one day" for GmailApp.getUserLabelByName. I understand that the limit for Google Apps for Education is 10,000 per day, but this code should just run every five minutes, or 288 times every day for each label. What am I misunderstanding? Any thoughts for re-writing the code to avoid this?
.moveToArchive() doesn't seem to do anything in replyLabel(). I've tried moving it to different points in the code (before and after sending the reply), but it doesn't archive the thread.
Thank you for any suggestions to either issue. Please let me know if I can make my question any clearer.
var thisSS = SpreadsheetApp.getActiveSpreadsheet();
var forwardSheet = thisSS.getSheetByName('Forwards');
var emailSheet = thisSS.getSheetByName('Email');
var alias = emailSheet.getRange(3, 2).getValue();
var replyTo = emailSheet.getRange(2, 2).getValue();
var fromName = emailSheet.getRange(1, 2).getValue();
var replySheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Replies');
function forwardLabel() {
var data = forwardSheet.getRange(2, 1, forwardSheet.getLastRow(), 2).getValues();
for (i in data) {
var row = data[i];
var name = row[0].toString();
var email = row[1].toString();
if (name && (email != "")) {
var label = GmailApp.getUserLabelByName(name);
var threads = label.getThreads(0, 100);
for (i in threads) {
var messages = threads[i].getMessages();
for (j in messages) {
Logger.log(messages[j].getSubject());
messages[j].forward(email, {bcc:alias, from:alias, name:fromName}).markRead();
label.removeFromThread(threads[i]);
}
Utilities.sleep(1000);
}
}
}
}
function replyLabel() {
var data = replySheet.getRange(2, 1, replySheet.getLastRow(), 2).getValues();
var signature = emailSheet.getRange(4, 2).getValue().toString();
var alias = emailSheet.getRange(3, 2).getValue();
for (i in data) {
var labelName = data[i][0].toString();
var label = GmailApp.getUserLabelByName(labelName);
var replyText = data[i][1].toString();
replyText = replyText + signature;
if (label && (replyText !== "")) {
var labeledEmails = label.getThreads(0, 100);
for (j in labeledEmails) {
labeledEmails[j].moveToArchive();
label.removeFromThread(labeledEmails[j]);
var messages = labeledEmails[j].getMessages();
var message = messages[0];
message.reply(replyText,{htmlBody:replyText, bcc:alias, from:alias, name:fromName});
Utilities.sleep(2000);
}
}
}
}
How many labels do you have ? You have nested loops and the 288 gets multiplied by each loop and you could quickly be hitting the 10,000.
Also, note that you are not counting other GMail Read operations like getTHreads() and getMessages().
If you factor in all these, you could have a number exceeding 10,000.