1

I am developing a simple system for obtaining stock information and sending it to me by email. The problem is occurring with the function that should send the email.

I'm trying to use Gmail to do this and it works on my machine, but when it runs on the Google Cloud Function instance, an error is generated. The error says:

smtplib.SMTPAuthenticationError: (534, b'5.7.14 <https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=AKgnsbt\n5.7.14 DI7EWTXsfkIgcqDF1iU9gzO45O2rHEDek8EzvslcMMuOLXixqGFX_YhwsIz9P9OsZkRDf\n5.7.14 F7fWu8KmILP4m54Yb925Tl93FSuXLCUiWn7REseAjcak7RpZ_2tgWliAGFufsPSW>\n5.7.14 Please log in via your web browser and then try again.\n5.7.14 Learn more at\n5.7.14 https://support.google.com/mail/answer/78754 b18sm13789218iln.46 - gsmtp')

And here is my simple code

import smtplib, ssl, os, sys
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase

SMTP_SERVER = os.getenv('SMTP_SERVER', 'smtp.gmail.com')
SMTP_PORT = os.getenv('SMTP_PORT', 587) 
EMAIL_USER = os.getenv('EMAIL_USER')
EMAIL_PASSWORD = os.getenv('EMAIL_PASSWORD')

def send_mail(email_from, to, subject, body_message, from_name=None):
  from_str = '{} <{}>'.format(from_name, email_from) if not from_name is None else email_from 
  msg = MIMEMultipart()
  msg['From'] = from_str
  msg['To'] = to
  msg['Subject'] = subject
  body_html = body_message
  msg.attach(MIMEText(body_html, 'html'))
  text = msg.as_string()
  server = smtplib.SMTP(SMTP_SERVER,SMTP_PORT)
  server.ehlo() # Can be omitted
  server.starttls()
  server.ehlo() # Can be omitted
  server.login(EMAIL_USER, EMAIL_PASSWORD)
  server.sendmail(email_from, to, text)
  server.quit()

The above function works perfectly on my machine. I already enabled insecure apps on this account.

I saw a post here that was talking about something like that. At one point in the post you can find the quote below.

Still not working? If you still get the SMTPAuthenticationError but now the code is 534, its because the location is unknown. Follow this link: https://accounts.google.com/DisplayUnlockCaptcha

So, this is the error that I'm getting but I don't know how to solve it inside of a Cloud Function.

Here is the link to the full discussion: Login credentials not working with Gmail SMTP

Lauren
  • 844
  • 4
  • 8
GeekSilva
  • 481
  • 1
  • 5
  • 20
  • Since you cannot login using your username/password and handle prompts in Cloud Functions, you will need to use `Sign in with App Passwords` https://support.google.com/accounts/answer/185833?hl=end Note using port 465 and `starttls` is not recommended. Instead use port 587 and `smtplib.SMTP_SSL(gmail_host, gmail_port)` – John Hanley Dec 22 '20 at 00:49
  • See this might be helpful - https://stackoverflow.com/a/57066097/11866104 – Mahboob Dec 22 '20 at 01:24
  • @JohnHanley The port already is 567. I tried to use SMTP_SSL but I got another error that says `ssl.SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1056)` – GeekSilva Dec 22 '20 at 01:38
  • @Mahboob unsafe applications are already enabled. – GeekSilva Dec 22 '20 at 01:39
  • By the way, using app passwords on your Google account makes it work. But for the sake of learning (I am preparing a tutorial on this) I would like to know why this method is throwing an error. – GeekSilva Dec 22 '20 at 01:51
  • You are using `starttls` which is for port 465. Use SMTP_SSL for port 587. Double check the code you posted in your question. There are a zillion tutorials on Gmail and SMTP. First understand the Gmail service, the protocol and then the libraries. – John Hanley Dec 22 '20 at 02:43
  • @JohnHanley I think I understand how it works. If you notice and look at the post you will see that I mentioned that this script works normally and only presents problems in the Google Cloud Functions environment. One of the zillions of tutorials available on the web was used as the basis for this simple code. Thank you for your help. – GeekSilva Dec 22 '20 at 05:02
  • 1
    Your code is wrong and incorrect. Review how the SMTP protocol works with an eye on negotiating encryption (TLS). For example, endpoints that are already have TLS enabled (Gmail port 587) you do not call `starttls`. You are using code that starts with an endpoint that is unencrypted (port 465) and then switches to encryption later. Hackers/spammers often do this because their code does not know the underlying framework, so they try different methods until they can successfully connect. – John Hanley Dec 22 '20 at 05:08
  • 1
    Another item. If you deploy incorrect code, intrusion detection system can flag you as a threat vector. – John Hanley Dec 22 '20 at 05:12
  • Ok. I understand it. But why this works in some cases? There is an explanation? – GeekSilva Dec 22 '20 at 05:12
  • I'll review it and make tests again. – GeekSilva Dec 22 '20 at 05:13
  • 1
    Some SMTP systems allow sloppy clients. Some do not. The point is to learn how the protocol works and then you will understand what not to do. – John Hanley Dec 22 '20 at 05:13

0 Answers0