I have several scripts in Google Docs spreadsheets that use MailApp.sendEmail to send e-mails incorporating data from the spreadsheets. They've all worked marvelously for years. About 2 weeks ago, they stopped sending the e-mails. The scripts still run and I don't get any errors. The e-mails just never come through. Nothing has changed, except that the e-mails aren't arriving anymore.
Any thoughts?
Thanks!
I think I have an answer to my own question, which may be helpful to anybody else who has this problem. MailApp.sendEmail DOES, indeed, still seem to be working. What has changed is the way Gmail is handling certain types of messages.
If I use MailApp.sendEmail to send an e-mail to a third party, it'll get through, no problem. As pointed out by Fashtas, if I use MailApp.sendEmail to send an e-mail to the Gmail account that the spreadsheet belongs to, no problem.
Here's the problem: if I use MailApp.sendEmail to send the message to a third party account that automatically forwards BACK to the Gmail account that the spreadsheet belongs to, those messages no longer get through.
Therefore, in the sample code I posted above, the matt#.com e-mail address automatically forwards back to my Gmail account. The messages sent by the MailApp.sendEmail make it through to the .com mail server, but for some reason, they don't get forwarded back to my Gmail inbox. They appear in the Gmail Sent Items folder (presumably because they were sent by the Gmail account that the spreadsheet belongs to), but they never hit the inbox.
That behavior is new. In the past, there has been no problem with those messages getting forwarded from the *.com server to my Gmail inbox. I don't know what changed to cause the problem. And I don't know how to fix it.
But I, therefore, think the answer to my question is that MailApp.sendEmail IS working as designed.
As explained by doebtown, MailApp.sendEmail() will refuse to send messages to any address that forwards to your account. For example, if you (the spreadsheet's owner) belong to a group, people#myorg.com, within your organization then mailApp.sendEmail() messages will not be delivered to people#myorg.com. That is, the following code will not send:
var email = 'people#myorg.com';
var subject = 'The Week Ahead';
var body = 'Hi there!';
var htmlbody = "<p>Hi there!</p>";
// this will not send
MailApp.sendEmail(email, subject, body,{
htmlBody : htmlbody
});
HOWEVER, you can work around this issue by appending your email to the addresses.
var email = 'myaddress#myorg.com, people#myorg.com';
var subject = 'The Week Ahead';
var body = 'Hi there!';
var htmlbody = "<p>Hi there!</p>";
// this will send to your address and the full list
MailApp.sendEmail(email, subject, body,{
htmlBody : htmlbody
});
This email will send to your address as well as to the list to which you belong. This is not a perfect solution, but is viable if you do not want to create a specific account for managing scripts.
You can apparently only send emails to the gmail/email account the spreadsheet belongs to.
There are multiple ways to send an email through Google App Scripts.
MailApp: Traditional method, however I could not get a single email to send. Introduction course here.
GmailApp: Same method as MailApp however using the below code worked to send emails.
GmailApp.sendEmail(emailList[index], "New email", "New email", {"cc":"XXXXXXX#gmail.com"});
Add a the Gmail API through Services. This options was not explored but documentation can be found here.
Conclusion: Don't use the MailApp, instead use GmailApp.
Related
As part of sending a bulk of emails on Gmail, I want to configure the Reply-To address depending on the recipient using Gmail's alias feature and Google Apps Script.
I've come across a problem that the reply-to settings in Gmail drafts created by the Google Apps Script is disabled (nullified) when attempting to send the created draft via the Gmail website, and wondered if anyone can help me with workarounds.
Reproducing
My script looks something like below. My Gmail account, for the sake of providing an example, is me#gmail.com:
var subject = 'An Eye-catching Email Subject';
var recipients = [{
email: 'mail1#sample.com',
replyTo: 'me+asia#gmail.com',
body: 'email text for mail1#sample.com'
},
{
email: 'mail2#example.com',
replyTo: 'me+europe#gmail.com'
body: 'email text for mail2#example.com'
}
// which goes on for an order of under 100 recipients
];
recipients.forEach(recipient => GmailApp.createDraft(recipient.email, subject, recipient.body, {
replyTo: recipient.replyTo
}));
When I open one of the created draft messages on the Gmail website, and then send the message by hitting the Send button, the sent email is set to reply to me#gmail.com and not the designated Reply-To aliases, like me+asia#gmail.com.
Alternatives
If I use the sendEmail() method instead of the createDraft() used above, everything works fine. The designated replyTo options are reflected in the actual emails sent.
The only reason that I use createDraft() instead of sendEmail() is that after the drafts are created, I want to make sure everything is alright before hitting the Send button, individually. I understand that I should probably just forget using createDraft(); I just can't figure out what Google intended to do with the replyTo option of createDraft(), and if anyone knows some other solution that I could take while sticking to createDraft(), I am more than grateful.
Issue and workaround:
In my environment, I have experienced the same situation. At that time, I confirmed the following situations.
When the draft mail is manually sent at the browser in Gmail UI, Reply-To is removed from the header of the draft message, the draft message is sent.
When I saw the draft message, Reply-To is included in the header.
When the draft message including Reply-To is sent using a script like GmailApp.getDraft(id).send(), the message is sent by including Reply-To in the header. This is the same situation with GmailApp.sendEmail().
From above situation, as a simple workaround, how about sending the draft messages using a script as follows?
Create the draft messages.
Confirm each draft messages.
This is from The only reason that I use createDraft() instead of sendEmail() is that after the drafts are created, I want to make sure everything is alright before hitting the Send button, individually. in your question.
When you found the modification points in the draft messages, please modify and/or remove them.
After you confirmed all draft messages, and when you want to send them, you can send them using a script.
When above workaround is reflected to the script, it becomes as follows.
Sample script:
function myFunction() {
GmailApp.getDrafts().forEach(e => e.send());
}
When this script is run, the current all draft mails are sent. Please be careful this.
Note:
When the draft messages include some draft messages you don't want to send, for example, I think that the filter using the star can be also achieved. When you want to send the draft messages which have the star, you can also use the following script.
GmailApp.getDrafts().forEach(e => {
if (e.getMessage().isStarred()) e.send();
});
Reference:
send() in Class GmailDraft
My Sheet-bound script is sending an email using MailApp.sendEmail.
The emails are always sent 'from' my own Gmail account. This project is for a customer, and I need his email to be the 'from' on these emails.
Reading similar questions I learn that the I only have flexibility in changing the name and replyTo address, using the advanced options of MailApp.sendEmail. However, the email address is still mine and Google doesn't offer any control over that.
I'm not familiar enough with all of the Google services and options to find the best way to do this. My customer does have a Google Apps for Business, but I don't.
Can I somehow create the email-sending function as a standalone script under his account, and somehow call it from the project under my account?
Any other ideas?
Thanks!
Emails are always sent from the account of the user that executes the script. In case the email is sent by a triggered function (installable triggers are the only ones that are able to send emails since it requires explicit authorization) then the email is sent from the account of the user that created the trigger (and authorized it).
In your case, it seems that the easier solution would be to ask your customer to execute the script himself and initiate all the triggers himself too.
If that should not be possible then you could indeed use a standalone script that would work as a kind of proxy, ie it would receive a request to send a message and actually send it from the customer account while returning an acknowledgement to your script.
But that's a bit tricky... the first solution is more elegant.
Edit :
I found the idea of sending emails through an independent script funny so I gave it a quick try and it seems to do the job pretty easily... test code below (this code should be deployed as a standalone app from your customer account) :
function doGet(e) {
Logger.log('e = e'+JSON.stringify(e));
if(e.parameter.recipient==null){return ContentService.createTextOutput("error, wrong request "+JSON.stringify(e)+"\n\n"+e.parameter.recipient+"\n\n"+e.parameter.subject+"\n\n"+e.parameter.body).setMimeType(ContentService.MimeType.TEXT)};
try{
MailApp.sendEmail(e.parameter.recipient, e.parameter.subject, e.parameter.body)
}catch(err){
return ContentService.createTextOutput('error : '+err).setMimeType(ContentService.MimeType.TEXT);
}
return ContentService.createTextOutput('mail successfully sent').setMimeType(ContentService.MimeType.TEXT);
}
note : the code below goes in your spreadsheet script, the doGet above is an standalone app running from your customer account.
function sendMail(recipient,subject,body){
var sent = UrlFetchApp.fetch("https://script.google.com/macros/s/---------------S381kO1Kqv61E/exec?recipient="+recipient+"&subject="+subject+"&body="+body);
Logger.log(sent);
}
function test(){
sendMail('recipient#gmail.com','test message','hello world')
}
I was able to send messages from my gmail account while being logged as a different user. (the url above is intentionally truncated, I don't want anyone to send email from my account ;-)
I just wanted to know if this behaviour is normal. Is it suppose to send a copy of the mail to me as the script owner, as well as the intended recipient? For example this code:
function emailTest(){
MailApp.sendEmail("someemail#gmail.com","test subject","test body");
}
Will send out an email to someemail#gmail.com. I will also get a copy in my inbox as the script owner. Can I shut this off somehow?
Regards,
Shumway
Because you're sending the mail from your account, you'll see the message in your 'Sent' box. If you're seeing it in your Inbox, it's not related to the script itself, as this is only sending to "someemail#gmail.com".
Things to check:
You don't have a forwarding rule from "someemail#gmail.com" to your account.
You don't have a filter/mail client/ other service accessing your inbox and placing your sent mail in the inbox.
You're not looking at 'All Mail'. Etc, etc.
You can probably get help for this at: https://productforums.google.com/forum/#!categories/apps/mail-settings.
Okay this is very strange. I have scripting in a spreadsheet to take information from the currently active sheet, creates a report using a template file and sends it as an attachment.
This all works perfectly, when I use my Google apps domain account email address as the recipient. It doesn't work when I send to any other email address, other than my own. It was working yesterday. No errors generated when the script runs
The only thing that I did was change the owner of the spreadsheet to another user in our domain. It was shared with the other user while I was testing the scripts. I've tried using other email addresses in our domain and created a new spreadsheet with the sendemail function, all with the same behavior.
// Email the specified report
function emailReport(file, recipients, emailSubject, emailMessage) {
MailApp.sendEmail("someone#example.com", emailSubject, emailMessage,
{attachments: file, mimetype: 'application/pdf'});
}
I've been able to reproduce the problem and to find a workaround.
As it's not posible to send email to recipients without google account, I add that kind of emails on a cc field.
// Email the specified report as cc
function emailReport(file, recipients, emailSubject, emailMessage) {
MailApp.sendEmail("my#gmail.com", emailSubject, emailMessage,
{attachments: file, mimetype: 'application/pdf', cc:"someone#example.com"});
}
I noticed this question a while back, and even referenced it in another one. Since then I've noticed no one responded to you so...
It appears as if Google has recently changed (though not documented anywhere I've found) the MailApp.sendEmail function so that it only works when you use the email address belonging to the owner of the spread sheet.
My guess is this is to prevent the system being used for unsolicited mass emailing.
The other question was here
(Sorry, not an answer as such :( more of a confirmation as to what you are seeing seems to be as expected)
For anyone having this issue, use the GmailApp class instead of the MailApp class.
It supports the same functions, for example: GmailApp.sendMail('recipient#gmail.com', 'Subject', 'Message').
https://developers.google.com/apps-script/reference/gmail/gmail-app#sendEmail(String,String,String)
Here's my Google App Script code:
var messages = threads[x].getMessages();
for (var y in messages)
{
messages[y].forward("someone#example.com");
}
This forwards fine, but it resets the from field of message to the email id of account which executes the script. This removes all credentials of the original sender of message. How to forward the email more elegantly such that all original headers (at least from and to) are retained? If the original message was sent to a list of people or a newsgroup, I need to retain it in the forwarded message.
In general a forwarded email does not retain the original from and to address. If you forward an email using GMail or Outlook you'll notice this. The GMailApp is behaving the same way.