Python 2: SMTPServerDisconnected: Connection unexpectedly closed
Asked Answered
U

8

35

I have a small problem with sending an email in Python:

#me == my email address
#you == recipient's email address
me = "[email protected]"
you = "[email protected]"

# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = "Alert"
msg['From'] = me
msg['To'] = you

# Create the body of the message (a plain-text and an HTML version).
html = '<html><body><p>Hi, I have the following alerts for you!</p></body></html>'

# Record the MIME types of both parts - text/plain and text/html.
part2 = MIMEText(html, 'html')

# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part2)

# Send the message via local SMTP server.
s = smtplib.SMTP('aspmx.l.google.com')
# sendmail function takes 3 arguments: sender's address, recipient's address
# and message to send - here it is sent as one string.
s.sendmail(me, you, msg.as_string())
s.quit()

So before now, my program didn't give me an error, but it also didn't send me an email. And now python gives me an error:

SMTPServerDisconnected: Connection unexpectedly closed

How can I fix this?

Urethroscope answered 20/7, 2013 at 7:25 Comment(6)
did u check ur internet connection ?Stoffel
hey see this question : - https://mcmap.net/q/37846/-how-to-send-an-email-with-pythonStoffel
possible duplicate of Issue with sending mails from a distribution mail id [Python]Salahi
i think the problem is in local SMTP serverUrethroscope
do anyone know any other public SMTP servers?Urethroscope
smtp.gmail.com on 465 or 587? just ensure to allow -in thes ender account- "access to less secure applications" (in the Security settings for the sender account). perhaps THAT server is not working as expected, but other google servers are workingOperation
M
31

TLDR: switch to authenticated connection over TLS.

Most probably the gmail server rejected the connection after the data command (very nasty of them to do so at this stage :). The actual message is most probably this one:

    retcode (421); Msg: 4.7.0 [ip.octets.listed.here      15] Our system has detected an unusual rate of
    4.7.0 unsolicited mail originating from your IP address. To protect our
    4.7.0 users from spam, mail sent from your IP address has been temporarily
    4.7.0 rate limited. Please visit
    4.7.0  https://support.google.com/mail/answer/81126 to review our Bulk Email
    4.7.0 Senders Guidelines. qa9si9093954wjc.138 - gsmtp

How do I know that? Because I've tried it :) with the s.set_debuglevel(1), which prints the SMTP conversation and you can see firsthand what's the issue.

You've got two options here:

  1. Continue using that relay; as explained by Google, it's unencrypted gmail-to-gmail only, and you have to un-blacklist your ip through their procedure

  2. The most fool-proof option is to switch to TLS with authentication

Here's how the changed source looks like:

# skipped your comments for readability
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

me = "[email protected]"
my_password = r"your_actual_password"
you = "[email protected]"

msg = MIMEMultipart('alternative')
msg['Subject'] = "Alert"
msg['From'] = me
msg['To'] = you

html = '<html><body><p>Hi, I have the following alerts for you!</p></body></html>'
part2 = MIMEText(html, 'html')

msg.attach(part2)

# Send the message via gmail's regular server, over SSL - passwords are being sent, afterall
s = smtplib.SMTP_SSL('smtp.gmail.com')
# uncomment if interested in the actual smtp conversation
# s.set_debuglevel(1)
# do the smtp auth; sends ehlo if it hasn't been sent already
s.login(me, my_password)

s.sendmail(me, you, msg.as_string())
s.quit()

Now, if try to 'cheat' the system and send with a different (non-gmail) address it's gonna a) require you to connect to a different hostname (some of the MX records for gmail), then b) stop you and close the connection on the grounds of blacklisted ip, and c) do reverse DNS, DKIM and lots of other countermeasures to make sure you're actually in control of the domain you presented in the MAIL FROM: address.

Finally, there's also option 3) - use any other email relaying service, there are tons of good ones :)

Monmouth answered 14/10, 2015 at 9:10 Comment(1)
+1 not for the actual solution, but for set_debuglevel. That helped me diagnose my problem, which turned out to be google complaining about the header.Evenings
C
19

I Had the same issue and solved it just by specifying the right port like this:

smtplib.SMTP('smtp.gmail.com', 587)
Chumash answered 21/4, 2017 at 21:34 Comment(0)
R
8

Using smtplib.SMTP_SSL() instead of smtplib.SMTP() works for me. Try this.

Riddle answered 2/10, 2017 at 7:39 Comment(1)
Be careful, these functions make an SMTP server request on different ports. So check the port of the TCP socket endpoints that are listening. It may correct the exception, but that is because a completely different source code path is executed.Lorrin
R
1

I have realised a strange behavior. I have used similar codes mentioned both the question and answers. My code has been working for the last days. However, today I encountered the error message mentioned in the question.

My solution: I had tried my successful attempt via library network. Today I have tried it via Starbucks network (over captive portal). I changed it to my mobile network. It started working again.

Possibly, Google rejects requests from unreliable networks.

Ruttish answered 27/12, 2017 at 17:29 Comment(0)
Y
0

Googlers: I had a test smtp server running locally. I was getting this error because I was shutting down the local smtp server before closing the client smtp.

Yousuf answered 1/5, 2019 at 15:34 Comment(5)
Do you think that is what the problem was in the question, or are you adding this only because it had the same error message. If it was just because the error message was the same it would be better to add a new question and provide this as an answer to that new question.Epirogeny
Why not ask the same question for all of the answers above?Yousuf
Because the review queue only shows one answer for review at a time. It may be fair to ask the same of the others, and you can flag them for review if you wish.Epirogeny
That makes sense. I think it could be an answer to the question above, none have been accepted. I view the answers section as help for future users with the same error message not only the person asking the question especially when an answer has not been accepted.Yousuf
The benefit of wording a new question is that it is more likely to be found if someone searches for the error message and a few keywords. The problem with a question that is basically an error message is that if the error message is generic then you can end up with tons of unrelated answers below it which all might be great answers to a more specific question.Epirogeny
L
0

This link will give you the meaning of this exception.

https://documentation.help/python-3-7-3/smtplib.html

exception smtplib.SMTPServerDisconnected

This exception is raised when the server unexpectedly disconnects, or when an attempt is made to use the SMTP instance before connecting it to a server.

The request is clearly leaving the client machine and has reached the server machine, because the exception has the word "SMTPServer" in it.

Check what TCP sockets are listening on the server. Find out all details (ie: interface, IP address, port) for the socket endpoints for SMTP TCP listeners, and configure the SMTP server accordingly.

Firewall rules are not the cause of this error/exception. It's a communication issue with the two socket endpoints (client and server/listener). The source code which creates the socket endpoint on the remote socket (from the client's perspective--this is the server socket endpoint), is missing configuration. Or the client is requesting a server connection with the incorrect interface, IP or port.

Lorrin answered 22/2 at 23:20 Comment(0)
A
-1

I was facing the same problem. In my case, password was changed just few days back. So, it was giving the error. As I updated the password in code, its working like a charm...!!!

Adahadaha answered 12/6, 2018 at 9:25 Comment(0)
E
-1
with smtplib.SMTP_SSL("smtp.mail.yahoo.com", port=465) as connection:

connection.login(
    user=my_email,
    password=my_password
)

connection.sendmail(
    from_addr=my_email,
    to_addrs=friend_address,
    msg=f"Subject:Text\n\n"
        f"Body of the text"
)

This is my code. I hope it will be helpful.

Entomology answered 21/6, 2022 at 6:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.