Python 2: SMTPServerDisconnected: Connection unexpectedly closed - python

I have a small problem with sending an email in Python:
#me == my email address
#you == recipient's email address
me = "some.email#gmail.com"
you = "some_email2#gmail.com"
# 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?

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:
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
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 = "some.email#gmail.com"
my_password = r"your_actual_password"
you = "some.email2#gmail.com"
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 :)

I Had the same issue and solved it just by specifying the right port like this:
smtplib.SMTP('smtp.gmail.com', 587)

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

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.

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...!!!

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.

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.

Related

Sending mail with through python with roundcube

Am trying to send mail with python using my rouncube webmail but when i run it outputs this error TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
I checked in my mail and my port is "290" which have provided but when i run the function the mail doesn't send. I know how to send with gmail by turning on less secure app access but don't know how to work around to send with my webmail.
I need your suggestion to work around it.
from smtplib import SMTP_SSL as SMTP
import logging, logging.handlers, sys
from email.mime.text import MIMEText
def send_message():
text = '''
Hello,
Trying to send mail from my webmail in python 3.
Sincerely,
My name
'''
message = MIMEText(text, 'plain')
message['Subject'] = "Email Subject"
my_email = 'joe#mycompany.com'
# Email that you want to send a message
message['To'] = my_email
# You need to change here, depending on the email that you use.
# For example, Gmail and Yahoo have different smtp. You need to know what it is.
connection = SMTP('smtp.roundcube.com', 290)
connection.set_debuglevel(True)
# Attention: You can't put for example: 'your_address#email.com'.
# You need to put only the address. In this case, 'your_address'.
connection.login('fred.kings', 'fredsw321a')
try:
# sendemail(<from address>, <to address>, <message>)
connection.sendmail(my_email, my_email, message.as_string())
finally:
connection.close()
send_message()
I'm using:
Ubuntu 18.04.4 LTS.
Python 3.7.4
Jupyter-Notebook 6.0.1
Anaconda 1.7.2
I can successfully send an email through Python with Roundcube, executing the following script in a jupyter-notebook cell:
import smtplib
email = "myemail#mycompany.com"
password = "mypassword"
to = ["destination#dest.com"]
with smtplib.SMTP_SSL('mail.mycompany.com', 465) as smtp:
smtp.login(email, password)
subject = "testing mail sending"
body = "the mail itself"
msg = "Subject: {}\n\n{}".format(subject, body)
smtp.sendmail(email, to, msg)
I found this information as follows (so you can find yours):
Log into you company email.
Look for the following image and click on it (Webmail Home).
You'll see something like the following:
Scroll down, looking for the following image and click on it (Configure Mail...).
Look for the info at mail server section.
If there are using port 465 (such as in my case) it means that you want to use smtplib.SMTP_SSL instead of smtplib.SMTP.
NOTE: The previous worked for me from my personal computer, however, when I tried to use the same code, from my "virtual machine" at office, it does not work, which makes me think that there is a system limitation, and that the problem is not code-related.
Hope it helps, regards.

Google SMTP less secure applications

I am trying to send email via Google SMTP server using the following simple python and mailclient.
I am a bit confused about the part where Google flags this script as insecure and requires me to allow less secure applications to access the sender's gmail account.
Is there any way to solve this problem without having to allow less secure applications to access my gmail account.
#Make necessary imports
import mailclient
#Craft the message
msg = mailclient.Message("This will be the subject", "This will be the body content", 'sender#gmail.com', 'recipient#domain.com')
#Create server object with gmail
s = mailclient.Server('smtp.gmail.com', '587', 'sender#gmail.com', 'senderpassword', True)
#Send email
s.send(msg)
Hard to say, because Google is not very explicit for what they call unsecure applications, but I guess that they are applications that use ports 25 or 587. On those ports, the connection is initially established on an unencrypted channel, and becomes encrypted only when (and if) the STARTTLS command is issued.
So I guess that you should try to establish a connection directly over SSL on port 465. I do not know whether it is possible using mailclient but with the standard library modules, it should be as simple as:
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg['Subject'] = "This will be the subject"
msg['From'] = 'sender#gmail.com'
msg['To'] = [ 'recipient#domain.com' ]
msg.set_content("This will be the body content")
server = smtplib.SMTP_SSL('smtp.gmail.com')
server.login('sender#gmail.com', 'senderpassword')
server.send_message(msg)
server.quit()

Python's smtplib module violating Gmail's terms of use

How can I avoid violating Gmail's terms of use when using Python's smtplib?
I would like to send internal emails using Python. After 2 days of fighting with the Gmail API, I gave up. Then I found the smtplib module, which looked simple and promising.
Following the example here, I wrote this small block of Python code:
import smtplib
# Details of where to send FROM
emailUser = 'an.account.I.made.just.for this.test#gmail.com'
emailPassword = 'password123'
# Send the following message to an address...
message = '[ I am email content ]'
toAddress = 'test.victim#gmail.com'
# Define the HEADER (to, from, and subject)
header = """
To: %s
From: %s
Subject: Python SMTPLIB Test
"""
header = header % (toAddress, emailUser)
# [ Don't know what this does ]
smtpserver = smtplib.SMTP("smtp.gmail.com",587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo
# Use User/Password credentials to send email
smtpserver.login(emailUser, emailPassword)
smtpserver.sendmail(emailUser, toAddress, message)
smtpserver.close()
I executed this script. It looks like Google's algorithms must have interpreted this as having been sent with bad intentions, and promptly closed my account! Which is fair enough, as I'm sure smtplib can be abused quite readily. However, I have honest intentions, but I do not know how to get around this issue: how can I avoid violating Gmail's terms of use when using Python's smtplib?
It could be because you are indiscriminately making connections with EHLO, you should be using HELO.
If the server supports EHLO, the client can use EHLO instead of HELO as its first request.
On the other hand, if the server does not support EHLO, and the client sends EHLO, the server will reject EHLO. The client then has to fall back to HELO.
There are a few servers that disconnect when they see EHLO. If the client finds that neither EHLO nor HELO was accepted, for example because the connection was closed, then it has to make a new connection and start with HELO.

Sending an email, via python, from one outlook account to another

I'm writing a program to help the school's Biology Department and it involves sending an email. I've gathered all of the variables I need for the content of the message, it's just the actual sending of the email that's causing some issues.
I've looked around and realized that I was using code that sent to gmail, whereas the servers at school use Outlook 2010. Once I remembered that, I looked around for some python code that sent emails, but so far nothing has worked.
It all seems very complicated for just sending an email, but I need some help as to were to go from here.
gsal.org.uk is our school's web server address, which is an outlook server.
The current error that I am receiving is smtplib.SMTPException: STARTTLS extension not supported by server., but I keep receiving various errors with everything I try.
This is the code:
fromaddr = "test#gsal.org.uk"
toaddrs = "technicians#gsal.org.uk"
msg = "\r\n".join([
"From: user",
"To: user",
"Subject: Practical Request",
"",
"Test"
])
server = smtplib.SMTP_SSL('smtp.gmail.com:465')
server.ehlo()
server.starttls()
# server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
messagebox.showinfo("Success!", "Your request has been sent successfully.")
All I want to do is send an email from an email account (specified within the program) to an email account that will soon be set up at school called technicians#gsal.org.uk. Any help appreciated.
EDIT
Thought I'd add the fact that if I remove the starttls() line, I get this:
smtplib.SMTPSenderRefused: (530, b'5.5.1 Authentication Required. Learn more at\n5.5.1 https://support.google.com/mail/answer/14257 hw1sm42144009wjb.6 - gsmtp', 'test#gsal.org.uk')
I've read that link, but it seems to be talking about gmail? I want to use outlook? I understand that I need to do authentication, but how?
In order to fight spam and protect resources, a normally configured SMTP server provides its services only to its owner (e.g. a company, organization or registered customers). Your school server probably accepts mail only if it is:
addressed to the school's own domain, or
coming from an authenticated person (e.g. a student, teacher), or
coming from a host with IP address belonging to the school's LAN (when allowed by the admin)
Further, a SMTP server communicates with other servers on TCP port 25 and with users submitting new mail (which is your case) on port 465 or 587. (Port 25 was used in the past for all mail, this is now deprecated)
Communication on port 465 is always encrypted (TLS). Communication on port 587 starts in plaintext, but with the STARTTLS command, the encryption is turned on. A successfull STARTTLS is usually required to allow authentication (login).
Why your progam does not work?
You are trying to start TLS on an TLS connection. It has been started. Either don't STARTTLS or change the port to 587.
You are using gmail's server to send a message not addressed to gmail. In this case you must login with a name and a password as a registered gmail user.
What should help? Contact the local admin for details about using the school's own server.

AOL mail rejected using smtplib

I'm using smtplib to send email via AOL account, but after successful authentication it gets rejected with following error.
reply: '521 5.2.1 : AOL will not accept delivery of this message.\r\n'
reply: retcode (521); Msg: 5.2.1 : AOL will not accept delivery of this message.
data: (521, '5.2.1 : AOL will not accept delivery of this message.')
Here's explanation for this error.
The SMTP reply code 521 indicates an Internet mail host DOES NOT ACCEPT
incoming mail. If you are receiving this error it indicates a configuration
error on the part of the recipient organisation, i.e. inbound e-mail traffic
is being routed through a mail server which has been explicitly configured
(intentionally or not) to NOT ACCEPT incoming e-mail.
Recipient mail (in my script) is valid (gmail) address and after this debug message mail gets rejected.
send: 'Content-Type: text/plain; charset="us-ascii"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\nSubject: My reports\r\nFrom: myAOLmail#aol.com\r\nTo: reportmail#gmail.com\r\n\r\nDo you have my reports?\r\n.\r\n'
Here's short version of code:
r_mail = MIMEText('Do you have my reports?')
r_mail['Subject'] = 'My reports'
r_mail['From'] = e_mail
r_mail['To'] = 'reportmail#gmail.com'
mail = smtplib.SMTP("smtp.aol.com", 587)
mail.set_debuglevel(True)
mail.ehlo()
mail.starttls()
mail.login(e_mail, password)
mail.sendmail(e_mail, ['reportmail#gmail.com'] , r_mail.as_string())
Is this some kind of permission problem because I'm successfully sending same email with Yahoo account without any problems?
I guess that AOL doesn't allow relay access by default or you have not configured it manually. The error you get says that aol doesn't have recipient you want to send message. In this case if you want to send email to gmail account try to connect to gmail SMPT server instead of AOL.
Change smpt server to gmail-smtp-in.l.google.com for example and turn off authentication.
Was running into 5.2.1 : AOL will not accept delivery of this message. from the AOL SMTP relay myself. What I ended up needing was valid From and To headers in the MIME message body, as opposed to just the SMTP connection.
In your particular case there could be any number of reasons for getting this 5.2.1 bounce. The postmaster.aol.com site has some helpful tools to diagnose, as well as some pretty vague documentation for this specific error message. In my case I ended up packet sniffing the SMTP messages that my Thunderbird email client was sending vs. the Python script, and eventually spotted the difference.
postmaster.aol.com documentation:
https://postmaster.aol.com/error-codes
AOL will not accept delivery of this message
This is a permanent bounce due to:
RFC2822 From domain does not match the rDNS of sending server.
RFC 2822 FROM address does not have an A record and is not a valid domain.
IP has a poor reputation and mail is sent to multiple recipients.
There are multiple From address in the mail headers and the IP reputation is poor.
My Python function for sending mail through smtp.aol.com:
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def genEmail(user, passwd, to, subject, message):
smtp=smtplib.SMTP_SSL('smtp.aol.com',465)
smtp.login(user, passwd)
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = user # This has to exist, and can't be forged
msg['To'] = to
msg.attach(MIMEText(message, 'plain'))
smtp.sendmail(user, to, msg.as_string())
smtp.quit()

Categories

Resources