Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using smtplib to send an email to mailtrap only works when code is not within function or class

this question is somehow similar to python: sending a mail, fails when inside a "with" block .

I'm using Python (3.6) to send emails to mailtrap smtp. Mailtrap actually provides you with the integration code for smtplib which is the one below:

import smtplib

sender = "Private Person <[email protected]>"
receiver = "A Test User <[email protected]>"

message = f"""\
Subject: Hi Mailtrap
To: {receiver}
From: {sender}

This is a test e-mail message."""

with smtplib.SMTP("smtp.mailtrap.io", 2525) as server:
    server.login("<MYUSER>", "<MYPASSWORD>")
    server.sendmail(sender, receiver, message)

The code above works just fine if I place it in a module and run it.I go to mailtrap inbox and verify that the email is there. However I want to encapsulate this in a function like this:


import smtplib
from socket import gaierror


def test():
    sender = "Test Dev <[email protected]>"
    receiver = "Test User <[email protected]>"
    message = f"""\
    Subject: Hi there
    To: {receiver}
    From: {sender}

    TESTING"""

    try:
        with smtplib.SMTP("smtp.mailtrap.io", 2525) as server:
            server.login("<MYUSER>", "<MYPASSWORD")
            print("Sending email")
            server.sendmail(sender, receiver, message)
        print('Sent')


    except (gaierror, ConnectionRefusedError):
        print('Failed to connect to the server. Bad connection settings?')
    except smtplib.SMTPServerDisconnected:
        print('Failed to connect to the server. Wrong user/password?')
    except smtplib.SMTPException as e:
        print('SMTP error occurred: ' + str(e))

if __name__ == "__main__":
    test()

This doesn't work. WHY? Here is the output: output image There's no connection error or any other exception. However I go to mailtrap and don't find the email there.

Is this a mailtrap issue or is it related to smtplib ? I'm cracking my head around this one

like image 244
Rafael Santos Avatar asked Nov 25 '25 04:11

Rafael Santos


1 Answers

I was having this same issue and couldn't wrap my head around it. I did notice that when I made my message an empty string, it worked.

After an embarrassingly long time of searching; I found this post which pointed me to the solution.

You must set the MIME type of the email message. So rather than just passing a string you pass a message object:

message = MIMEText("TEST!")
    message["Subject"] = "Alert!"
    message["From"] = sender
    message["To"] = receiver

... then eventually

server.sendmail(sender, receiver, message.as_string())

my full send email function looks like this:

    def send_mail(self):
    message = MIMEText("TEST!")
    message["Subject"] = "Alert!"
    message["From"] = sender
    message["To"] = receiver
    try:
        context = ssl.create_default_context()

        with smtplib.SMTP(smtp_server, port) as server:
            server.set_debuglevel(1)
            server.ehlo()  # Can be omitted
            server.starttls(context=context)
            server.ehlo()  # Can be omitted
            server.login(login, password)
            server.sendmail(sender, receiver, message.as_string())
        print('Sent')
    except (gaierror, ConnectionRefusedError):
        print('Failed to connect to the server. Bad connection settings?')
    except smtplib.SMTPServerDisconnected:
        print('Failed to connect to the server. Wrong user/password?')
    except smtplib.SMTPException as e:
        print('SMTP error occurred: ' + str(e))
    except Exception as e:
        print('everything else')

It's unfortunate that you must specify the sender and receiver in both the message object and sendemail fuction.

like image 113
Cody Avatar answered Nov 27 '25 18:11

Cody