Sending multiple emails in a row in GAE - google-app-engine

I have a GAE based app (python) and I'm trying to implement automatic email sending. When only one email is sent it works fine (both local and deployed). However, when I try to send two emails in a row the script only works on my local dev server. If the application is deployed to Google a strange mixup occurs. It seems like the body of the first email is sent to the recipient of the second one and then the application throws an internal server error.
Here's my code:
class MailSender(webapp.RequestHandler):
def get(self):
firstname=self.request.get('firstname')
lastname=self.request.get('lastname')
email=self.request.get('email')
city=self.request.get('city')
state=self.request.get('state')
country=self.request.get('country')
sender_address = firstname+" "+lastname+" <"+users.get_current_user().email()+">"
subject = "Subject 1"
body = "Name: "+firstname+"\nLast name: "+lastname+"\nEmail: "+email+"\nCity: "+city+"\nState: "+state+"\nCountry: "+country
mail.send_mail(sender_address, "address1#ourdomain.com", subject, body)
sender_address1="address1#ourdomain.com"
subject1="Subject 2"
body2="message"
mail.send_mail(sender_address1, email, subject1, body1)
self.response.out.write('{"status":"true"}')

It seems you didn't set a valid sender address in second mail.
https://cloud.google.com/appengine/docs/python/mail/sendingmail
The sender address must be one of the following types:
The address of a registered administrator for the application. You can add administrators to an application using the Administration Console.
The address of the user for the current request signed in with a Google Account. You can determine the current user's email address with the Users API. The user's account must be a Gmail account, or be on a domain managed by Google Apps.
Any valid email receiving address for the app (such as xxx#APP-ID.appspotmail.com).
Any valid email receiving address of a domain account, such as support#example.com. Domain accounts are accounts outside of the Google domain with email addresses that do not end in #gmail.com or #APP-ID.appspotmail.com.

You might need to use the EmailMessage object the way you see here. Did you try using a loop to send emails? The following works for me.
for detail in details:
subject = detail.title or 'Reminder'
message = mail.EmailMessage(sender='Business <info#business.com>', subject=subject)
message.body = """
Hello!
"""
message.to = detail.email
message.send()

Related

Emails sent using Gmail API are being flagged as phishy by Gmail

When I send an email using the Gmail API, recipients that are using the Gmail web interface are getting a phishing warning when they open the email.
However, when I send the exact same email content through the same Gmail account but using the web UI, the recipients do not get the phishing warning.
The only difference I can find between the two received emails, is that the one sent using the API has this additional header:
Received: from 114692869688 named unknown by gmailapi.google.com with HTTPREST; Tue, 11 Jun 2019 11:37:51 -0500
Does anyone know how to resolve this problem?
I have the same problem.
When defining your message does not define the from parameter :
def create_message(sender, to, subject, message_text):
message = MIMEText(message_text)
message['to'] = to
#message['from'] = sender
message['subject'] = subject
encoded_message = urlsafe_b64encode(message.as_bytes())
return {'raw': encoded_message.decode()}
In fact, this parameter is also defined when giving the user_id to the send method.
message = (service.users().messages().send(userId=user_id, body=message)
.execute())
In my case recipients get the emails ok, but senders got their own messages flagged as phishing in their sent messages tray.
After some time struggling with this, it seems a case-sensitive issue.
Once I capitalized the f in the "from" header the problem went away.
So:
# sender something like "John Doe <johndoe#gmail.com>"
message['From'] = sender
Make sure your from-header is ['From'], and not ['from'] (like Google's guide shows).
This one-line diff:
## -129,7 +129,7 ## def create_message(sender, to, subject, message_text):
"""
message = MIMEText(message_text)
message["To"] = to
- message["from"] = sender
+ message["From"] = sender
message["Subject"] = subject
return {"raw": base64.urlsafe_b64encode(message.as_bytes()).decode("ascii")}
Is the difference between getting this failure:
and this success:
There are two options:
Send an email through Gmail SMTP (Simple Mail Transfer Protocol, a protocol for sending e-mail messages between servers)
Authorizing Your App with Gmail - All requests to the Gmail API must be authorized by an authenticated user. Gmail uses the OAuth 2.0 protocol for authenticating a Google account and authorizing access to user data.
When you get an email that looks suspicious, here are a few things to check for:
Check that the email address and the sender name match.
Check if the email is authenticated.
Hover over any links before you click on them. If the URL of the link doesn't match the description of the link, it might be leading you to a phishing site.
Check the message headers to make sure the "from" header isn't showing an incorrect name.**
Yes, the message header is important when sending an email using Gmail API. You will need to trace an email with its full headers.

how does get_current_user work

I'm really confused how Google App Engine's User's get_current_user() works. I've looked around the internet at a bunch of different guides and tutorials about login and authentication, and many of them mention similar methods.
If there are a million users logged in to my application at the same time, how can that method possibly work? Does each user get their own instance of the server? How does the server know which client it is talking to?
It doesn't make sense to me at all.
When logging in (by clicking on the URL generated by create_login_url()) a cookie containing user identifying information is prepared and pushed on the client side, then used in subsequent requests until the user logs out or the cookie expires. Calling get_current_user() simply checks the cookie existance/information and responds accordingly.
On the development server the cookie is named dev_appserver_login. I can no longer check the cookie name on GAE as I switched away from the Users API.
The actual handling of the cookie seems to happen somewhere on the Users service backend, for example, by looking at the google/appengine/api/users.py file in the python SDK:
def create_login_url(dest_url=None, _auth_domain=None,
federated_identity=None):
...
req = user_service_pb.CreateLoginURLRequest()
resp = user_service_pb.CreateLoginURLResponse()
try:
apiproxy_stub_map.MakeSyncCall('user', 'CreateLoginURL', req, resp)
...
The end point (at least for the development server) seems to somehow land somewhere in google/appengine/tools/appengine_rpc.py, for example:
#staticmethod
def _CreateDevAppServerCookieData(email, admin):
"""Creates cookie payload data.
Args:
email: The user's email address.
admin: True if the user is an admin; False otherwise.
Returns:
String containing the cookie payload.
"""
if email:
user_id_digest = hashlib.md5(email.lower()).digest()
user_id = "1" + "".join(["%02d" % ord(x) for x in user_id_digest])[:20]
else:
user_id = ""
return "%s:%s:%s" % (email, bool(admin), user_id)
def _DevAppServerAuthenticate(self):
"""Authenticates the user on the dev_appserver."""
credentials = self.auth_function()
value = self._CreateDevAppServerCookieData(credentials[0], True)
self.extra_headers["Cookie"] = ('dev_appserver_login="%s"; Path=/;' % value)

Is there a way to change from address/email id on email sent from Google App engine Mail

Is there a way to change "from address" or email-id on email sent from Google App engine Code ? I am able to change the reply-to address but send-from mail address is only taking Administrator email id. Is there an application setting through which i can change the sent from email id ?
Message msg = new MimeMessage(session11);
msg.setFrom(new InternetAddress(Constants.DB.Connection.ADMINEMAIL, "TEST MAIL"));
msg.addRecipient(Message.RecipientType.TO, new InternetAddress(useremail, " TEST MAIL"));
msg.setReplyTo(new javax.mail.Address[]
{
new javax.mail.internet.InternetAddress(" testemail#xyz.com")
});
msg.setSubject(subject);
msg.setContent(message,"text/html");
Transport.send(msg);
Any suggestion or help would be appreciated
Yes, you can change the sender. But, that email must be listed as an administrator (developer). Your app can have more than one administrator.

Change Recipient Address Google Apps Script

Is it possible to change the recipient address when using the reply function in Google Apps Script?
I want to receive an email from a random email account, mark it with a label and when scheduled, run the following code to reply to a desired email address rather than the original sender. The reason I want to reply is to keep it in the same thread. I have tried nearly all variations of the following code and can't get it to work the way I want it to:
thread.reply("This is a message.", {
htmlBody: "This is a message.",
name: "My Name",
recipient: "DESIRED#EMAIL.com",
replyTo: "DESIRED#EMAIL.com",
to: "DESIRED#EMAIL.com"
});
If you're asking to generate a random email address and send a real email from that address... that's not possible.
However... you could set the replyTo optional parameter as a random address - though when users would try to reply to that thread they would get a bounce-back notification that the address could not be reached. However, the original sender (the non-random address) would still be visible in the original message.
If you look at the GmailApp docs (replying)/(sending), you'll notice a few limitations. The sender's address (from) must be a valid Alias, if you're sending mail from MailApp (Google Apps Script).
However, there are plenty of methods in the GmailMessage class such as getFrom() and getReplyTo() that would allow you to get/set the message's from/replyTo parameters and have them be the same value. That way, when you reply to a message you will always be in the same thread.

How do I send email from Google App Engine with a random, non-app admin sender?

Google App Engine has a rule of only allowing app admins to send email.
Is there a workaround that anyone out there is using to send emails from non-admin addresses?
I'm building a B2B white-label platform, and being able to mask the "FROM" address is very important without giving my customers admin access.
The docs also state:
Any valid email receiving address for the app (such as xxx#APP-ID.appspotmail.com).
So you can make up an sender address based on that, and even correctly route that email back into your app if anyone replies to it.
It is also possible to send email on behalf of a logged in user, assuming that user is using a Google Account.
user = users.get_current_user()
message = mail.EmailMessage(sender=user.email())
#Set other message components, such as message.body
try:
message.send()
except:
message.sender = #An APP-ID.appspotmail.com address, or Admin address
message.send()
If you need the email to appear as if it was sent by a user and when replied to reply back to that user's actual email address then you can make use of reply_to.
user_name = 'Some Guy'
user_email = 'some.guy#whatever.com'
admin_email = 'no-reply#yourdomain.com'
from_email = '%s <%s>' % (user_name, admin_email)
reply_to = '%s <%s>' % (user_name, user_email)
mail.send_mail(from_email, to_email, subject, body, reply_to=reply_to)
This way to the person receiving the email it will appear that it came from user_name and if they reply then their reply email will be sent to user_email.
The main negative of this approach is that if someone looks closely at the address they received the message from they will see the admin email address but most email clients show the name more prominently.
On the plus side you can send as any email address and most people would never notice it came from an admin email address.

Resources