I am trying to connect to my mail server, then disconnect, then reconnect at another time. The initial connection works and the email is sent. I disconnect using quit() and the reply is closing the connection. When I attempt to connect again, it raises SMTPServerDisconnected please run connect() first. I found this from a few years ago as the exact same problem (https://bugs.python.org/issue22216) and it shows that it was fixed. I am having this same issue now and unsure how to properly fix it or close the connection.
mail = smtplib.SMTP_SSL('mail.hostname.com', 465)
MAIL_PASS = 'password'
SENDER = 'name#hostname.com'
RECEIVER = 'receiver#something.com'
while True:
if (something)
mail.login(SENDER, MAIL_PASS)
mail.sendmail(SENDER, RECEIVER, 'test email')
mail.quit()
elif (something else)
mail.login(SENDER, MAIL_PASS)
mail.sendmail(SENDER, RECEIVER, 'test2 email')
mail.quit()
After the first email and the quit request it says this:
reply: b'221 box5454.bluehost.com closing connection\r\n'
reply: retcode (221); Msg: b'box5454.bluehost.com closing connection'
The next connection attempt says this:
send: 'ehlo [127.0.1.1]\r\n'
Traceback (most recent call last):
mail.login(SENDER, MAIL_PASS)
self.ehlo_or_helo_if_needed()
if not (200 <= self.ehlo()[0] <= 299):
self.putcmd(self.ehlo_msg, name or self.local_hostname)
self.send(str)
raise SMTPServerDisconnected('please run connect() first')
smtplib.SMTPServerDisconnected: please run connect() first
I have found a way to make the program work. I am using a while True to continue the program. It seems when I declare the variable for the smtplib before while True, it has the problem. I declare the variable after while True and it works. May be a noob problem using while True, but it drove me nuts and hopefully it will help someone else
MAIL_PASS = 'password'
SENDER = 'name#hostname.com'
RECEIVER = 'receiver#something.com'
while True:
mail = smtplib.SMTP_SSL('mail.hostname.com', 465)
if (something)
mail.login(SENDER, MAIL_PASS)
mail.sendmail(SENDER, RECEIVER, 'test email')
mail.quit()
elif (something else)
mail.login(SENDER, MAIL_PASS)
mail.sendmail(SENDER, RECEIVER, 'test2 email')
mail.quit()
Related
I am using python to code a program that will ping a device, and do nothing if it gets a response back from the device, but if it does not receive any response, it will send me an email to notify me that the device may be down. However, as has been mentioned on here before, when the response from the ping is "Destination Host Unreachable," the return value is 0, which is the same as if it received a response. So what I'm looking for is help with how to discern the Destination Host Unreachable from the actual response so I can have an email sent to me under that condition (since it means the device is most likely down).
import platform
import subprocess
import smtplib
import time
#Delay to wait for Rigs to Boot
#time.sleep(600)
a = 1
while 1==1:
#Ping other PC's
def myping(host):
parameter = '-n' if platform.system().lower()=='windows' else '-c'
command = ['ping', parameter, '1', host]
response = subprocess.call(command)
if response == 0:
return True
#Will Send email if response from ping is false (aka not pingable/down)
else:
gmail_user = 'email'
gmail_password = 'password'
sent_from = gmail_user
to = ['recepient']
subject = 'subject'
body = 'body'
email_text = """\
From: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(to), subject, body)
try:
smtp_server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
smtp_server.ehlo()
smtp_server.login(gmail_user, gmail_password)
smtp_server.sendmail(sent_from, to, email_text)
smtp_server.close()
print ("Email sent successfully!")
except Exception as ex:
print ("Something went wrong….",ex)
#delay so i dont recieve spam emails while the 'while' loop runs
time.sleep(43000)
print(myping("ip to ping"))
Thank you for the help in advance.
You obviously can't change the behavior of ping. However, you can certainly use subprocess.check_output, which returns the output of the command, and parse that.
Using ping like this is not particularly useful. There are many reasons why you can't reach a remote host. Perhaps your local network is down, or your router has died, or your cable has been unplugged.
here is the code from my college, but I thougt it's not much effecient 'cause it'll connect smtp server and login every time, and just send one mail..., so how about I connect smtp and login for the first time once the service started, and using this long connection to send mail aferwards?
def send_email(receiver, subject, mail_body):
msg = MIMEText(mail_body, _subtype='html', _charset='utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = XXXX#xx.com
msg['To'] = receiver
try:
smtp = smtplib.SMTP()
smtp.connect(xxxx.com)
smtp.login(user, password)
smtp.sendmail(XXXX#xx.com, receiver.split(','), msg.as_string())
except Exception:
logger.error('Send email failed: %s' % traceback.format_exc())
finally:
smtp.quit()
It's OK to reuse the connection to send email, but the server may terminate the connection at any time, that depends on server's strategy. So just catch the corresponding error and reconnect again.
def send_email(receiver, subject, mail_body):
try:
smtp = smtplib.SMTP()
smtp.connect(xxxx.com)
smtp.login(user, password)
# for test
for i in range (10):
smtp.sendmail(XXXX#xx.com, receiver.split(','), msg.as_string())
except Exception:
logger.error('Send email failed: %s' % traceback.format_exc())
finally:
smtp.quit()
using the above code, I test sending 10 emails using the same connection, but got Exception below, I think that may be related to the safety strategy of target smtp server.
[2021-03-01 15:56:25,386] [ERROR] [125:MainThread] [send_email.py:47] [send_email]:send email failed: Traceback (most recent call last):
File "send_email.py", line 41, in send_email
smtp.sendmail(EmailAccount, email_receiver.split(','), msg.as_string())
File "/usr/lib/python2.7/smtplib.py", line 737, in sendmail
raise SMTPSenderRefused(code, resp, from_addr)
SMTPSenderRefused: (450, 'Requested mail action not taken: too much delivery in this connection', 'xxxx#xxxx.com')
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 <from#smtp.mailtrap.io>"
receiver = "A Test User <to#smtp.mailtrap.io>"
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 <from#smtp.mailtrap.io>"
receiver = "Test User <to#smtp.mailtrap.io>"
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
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.
I want to send a E-mail using python using this code but the final result is a "Connection unexpectedly closed" error:
import smtplib
sender_email = "example#gmail.com"
rec_email = "example2#gmail.com"
password = "password"
message = "Test message using python !"
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(sender_email, password)
server.sendmail(sender_email, rec_email, message)
This is the error:
raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed
It might be that the bigger email providers (I would believe this includes Gmail) block 'unsafe applications' from accessing the server.
You might want to try to login to sender_email and there should be an option somewhere that allows 'unsafe applications to access', or something similar.
I had a similar problem when doing the same thing with my Yahoo account, and this basically solved the problem.
This maybe a repeated question but I'm still facing issues on this, hope there's a solution around. Thanks in advance.
I'm trying to send mail through the company's server
I'm currently using Python version 2.6 and Ubuntu 10.04
This is the error message I got
Traceback (most recent call last):
File "hxmass-mail-edit.py", line 227, in <module>
server.starttls()
File "/usr/lib/python2.6/smtplib.py", line 611, in starttls
raise SMTPException("STARTTLS extension not supported by server.") smtplib.SMTPException: STARTTLS extension not supported by server.
Here goes part of the code
server = smtplib.SMTP('smtp.abc.com', 587)
server.set_debuglevel(1)
server.ehlo()
server.starttls()
server.ehlo()
server.login('sales#abc.com', 'abc123')
addressbook=sys.argv[1]
Remove the ehlo() before starttls().
starttls() + ehlo() results in two HELLO messages, which cause the server remove the STARTTLS in the reply message.
server = smtplib.SMTP('smtp.abc.com', 587)
server.starttls()
server.ehlo()
server.login('sales#abc.com', 'abc123')
I had a similar issue trying to send a mail through the company's server (without autentication needed)
I solved removing the server.ehlo and removing the port number:
server = smtplib.SMTP("smtp.mycompany.com")
server.sendmail(fromaddr, toaddr, text)
removing server.ehlo() before server.starttls() helped me get my code working! Thank you, Leonard!
my code:
s = smtplib.SMTP("smtp.gmail.com",587)
s.starttls()
s.ehlo
try:
s.login(gmail_user, gmail_psw)
except SMTPAuthenticationError:
print 'SMTPAuthenticationError'
s.sendmail(gmail_user, to, msg.as_string())
s.quit()
The error says it all, it seems the SMTP server sou are using doesn't support STARTTLS and you aru issuing server.starttls(). Try using the server without calling server.starttls().
Without more info is the only I can say.
I am able to resolve the issue with below code, by adding port number with server name:
server = smtplib.SMTP('smtp.abc.com:587')
from smtplib import SMTP_SSL, SMTP, SMTPAuthenticationError
from ssl import create_default_context
from email.message import EmailMessage
sender = 'aaa#bbb.com'
description = "This is the test description supposed to be in body of the email."
msg = EmailMessage()
msg.set_content(description)
msg['Subject'] = 'This is a test title'
msg['From'] = f"Python SMTP <{sender}>"
msg['To'] = 'bbb#ccc.com'
def using_ssl():
try:
server = SMTP_SSL(host='smtp.gmail.com', port=465, context=create_default_context())
server.login(sender, password)
server.send_message(msg=msg)
server.quit()
server.close()
except SMTPAuthenticationError:
print('Login Failed')
def using_tls():
try:
server = SMTP(host='smtp.gmail.com', port=587)
server.starttls(context=create_default_context())
server.ehlo()
server.login(sender, password)
server.send_message(msg=msg)
server.quit()
server.close()
except SMTPAuthenticationError:
print('Login Failed')
By testing and researching myself, I found out that the gmail servers do not use tls connections with python anymore.
You must not use service.startttls(). Gmail service do not support this type of connection anymore.
Also remember to use the SMTP ports (mail reserved ports) for sending emails.
POP3 and IMAP ports for receiving email.
s_u = "Test"
service = smtplib.SMTP_SSL("smtp.gmail.com", 465)
service.ehlo()
service.sendmail("SENDER_EMAIL","RECEIVER_EMAIL","MESSAGE")
You can't send the email even if you put the correct credentials,
look at this: Login credentials not working with Gmail SMTP
Are you sure that you want to encrypt (StartTLS) the connection to the mail server? I would contact someone who knows the insides of that server to see what protocol/encryption to use.
You say that upon removing the call to server.starttls(), you get a different series of error messages. Could you please post those messages as well?
Also, you might want to read up on StartTLS so you understand what it is and why you would want to use it. It seems you're writing a Serious Business program, in which case you'll probably want to understand what you are doing, security-wise.
Yes putting server.starttls() above server.ehlo() solved this.