1

I am attempting to send an email with AWS SES using a Dockerized Python program. When I try to connect to SES by making an SMTP instance, the program hangs and times out.

To reproduce:

  1. Start the Python 3.6.8 REPL
  2. Import smtplib
>>> import smtplib
  1. Try to connect to SES, and observe how the statement hangs.
>>> conn = smtplib.SMTP(host='email-smtp.us-west-2.amazonaws.com', port=25)
# terminal hangs for 10 seconds
  1. Try using the connection, which fails.
>>> conn.noop()
(451, b'4.4.2 Timeout waiting for data from client.')
>>> conn.noop()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python3.6/smtplib.py", line 514, in noop
    return self.docmd("noop")
  File "/usr/lib64/python3.6/smtplib.py", line 421, in docmd
    return self.getreply()
  File "/usr/lib64/python3.6/smtplib.py", line 394, in getreply
    raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed

Unsurprisingly, step (3) sends a DNS query for the SES endpoint, and then connects; the SES endpoint responds with 220 service ready nearly instantaneously. No traffic is exchanged until 10 seconds later, when SES closes the connection with 451 timeout waiting for client. The statement completes, and then runs the rest of my program which, of course, doesn't work.

For context, the rest of my script is as follows:

smtp_host = 'email-smtp.us-west-2.amazonaws.com'
smtp_port = 25
smtp_proto = 'tls'

with smtplib.SMTP(host=smtp_host, port=smtp_port) as connection:
    try:
        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23 if smtp_proto == 'ssl' else ssl.PROTOCOL_TLS)
        connection.starttls(context=ctx)
        connection.ehlo()

        connection.login(smtp_user, smtp_pass)

        connection.send_message(from_addr=sender, to_addrs=recipients, msg=message)
    except smtplib.SMTPHeloError as e:
        print(f"SMTP HELO Failed: {e}")
    except smtplib.SMTPAuthenticationError as e:
        print(f"SMTP AUTH Failed: {e}")
    except smtplib.SMTPException as e:
        print(f"Failed to send email: {e}")

I've attempted to connect on ports 25, 587, 2587, and 465. I've done the same with the SMTP_SSL object instead, as well as changing the context in the starttls call to various SSL / TLS versions (the SSL versions result in this error - but this isn't relevant since I can't get to this portion of the script, anyway).

I've tested my connection to SES according to this article. I've also tried parts of this and this SO post (as well as a myriad of others that are lost in my browser history).

To actually send emails, I need to connect a second time. Connecting, then waiting for a timeout, then connecting again, seems wrong. What is the proper way to do this?

vpseg
  • 71
  • 5

0 Answers0