Search code examples
pythondockeraws-lambdagmailsmtplib

Connection failed AWS Lambda SMTP mail


I'm trying to send an email from a python container running on AWS lambda. It is working fine when I am testing locally my Lambda container. But as soon as I'm trying the same on AWS Lambda, it is failing with the following traceback:

Function return

{ "errorMessage": "can only concatenate str (not \"bytes\") to str", "errorType": "TypeError", "stackTrace": [ " File \"/var/lang/lib/python3.8/imp.py\", line 234, in load_module\n return load_source(name, filename, file)\n", " File \"/var/lang/lib/python3.8/imp.py\", line 171, in load_source\n module = _load(spec)\n", " File \"<frozen importlib._bootstrap>\", line 702, in _load\n", " File \"<frozen importlib._bootstrap>\", line 671, in _load_unlocked\n", " File \"<frozen importlib._bootstrap_external>\", line 848, in exec_module\n", " File \"<frozen importlib._bootstrap>\", line 219, in _call_with_frames_removed\n", " File \"/var/task/app.py\", line 65, in <module>\n handler(None, None)\n", " File \"/var/task/app.py\", line 62, in handler\n __send_email(msg)\n", " File \"/var/task/app.py\", line 22, in __send_email\n server.login(gmail_user, gmail_password)\n", " File \"/var/lang/lib/python3.8/smtplib.py\", line 732, in login\n (code, resp) = self.auth(\n", " File \"/var/lang/lib/python3.8/smtplib.py\", line 635, in auth\n (code, resp) = self.docmd(\"AUTH\", mechanism + \" \" + response)\n" ] }

Log output:

[ERROR] TypeError: can only concatenate str (not "bytes") to str
Traceback (most recent call last):
  File "/var/lang/lib/python3.8/imp.py", line 234, in load_module
    return load_source(name, filename, file)
  File "/var/lang/lib/python3.8/imp.py", line 171, in load_source
    module = _load(spec)
  File "<frozen importlib._bootstrap>", line 702, in _load
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/var/task/app.py", line 65, in <module>
    handler(None, None)
  File "/var/task/app.py", line 62, in handler
    __send_email(msg)
  File "/var/task/app.py", line 22, in __send_email
    server.login(gmail_user, gmail_password)
  File "/var/lang/lib/python3.8/smtplib.py", line 732, in login
    (code, resp) = self.auth(
  File "/var/lang/lib/python3.8/smtplib.py", line 635, in auth
    (code, resp) = self.docmd("AUTH", mechanism + " " + response)

Code

def __send_email(msg:str) -> None:
    gmail_user = os.getenv('EMAIL_USER')
    gmail_password = os.getenv('EMAIL_PASSWORD')

    # Create Email
    mail_from = gmail_user
    mail_to = gmail_user
    mail_subject = f'DB Update today {datetime.today().strftime("%m/%d/%Y")}'
    mail_message = f'Subject: {mail_subject}\n\n{msg}'

    # Send Email
    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login(gmail_user, gmail_password)

    server.sendmail(mail_from, mail_to, mail_message)
    server.close()

Other env variables are working well so I don't think the problem is coming from here.

I am using the following docker image : public.ecr.aws/lambda/python:3.8.

Thanks you for your help!


Solution

  • I tested your function as it and it worked:

    import os
    from datetime import datetime
    
    os.environ["EMAIL_USER"] = "<test_email>"
    os.environ["EMAIL_PASSWORD"] = "<test password>"
    
    def __send_email(msg:str) -> None:
        gmail_user = os.getenv('EMAIL_USER')
        gmail_password = os.getenv('EMAIL_PASSWORD')
    
        # Create Email
        mail_from = gmail_user
        mail_to = gmail_user
        mail_subject = f'DB Update today {datetime.today().strftime("%m/%d/%Y")}'
        mail_message = f'Subject: {mail_subject}\n\n{msg}'
    
        # Send Email
        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.starttls()
        server.login(gmail_user, gmail_password)
    
        server.sendmail(mail_from, mail_to, mail_message)
        server.close()
    
    
    __send_email("hello world")
    

    Also, I looked at one of my lambdas and this is how I am sending emails using SMTP:

    import smtplib
    
    smtp_server = "smtp.gmail.com"
    smtp_port = 465
    smtp_username = "<test_email>"
    smtp_passwword = "<test password>"
    send_to = "<send_to_email_address>"
    send_from = "<send_from_email_address>"
    message_to_send = "hello world"
    
    
    def send_email(msg):
        server = smtplib.SMTP_SSL(smtp_server, smtp_port)
        server.login(smtp_username, smtp_passwword)
        message = f"""From: {send_to}
    To: {send_to}
    Subject: Test message
    
    {msg}."""
        server.sendmail(send_from, send_to, message)
        server.quit()
    
    
    send_email(message_to_send)
    

    Can you verify the env variables for username and password and see if they are passed in correctly.