Can't send e-mails using python script on digital ocean droplet - python-3.x

I am trying to send e-mails from a production server located on a digital ocean droplet using a office 356 mail server.
The operation executes correctly when I execute the python script on my test server (located on my mac) but fails with code 500 when on the production server.
I am using this code to achieve this:
def __init__(self, from_address="some#mail.com", from_password="somePassword",
smtp_server="smtp.office365.com", smtp_port=587):
self.from_address = from_address
self.from_password = from_password
self.smtp_server = smtp_server
self.smtp_port = smtp_port
def send_mail(self, recipients, subject, message, project_id, pdf_files):
client_id = ProjectClient.query.filter_by(project_id=project_id).first().client_id
client = Client.query.filter_by(client_id=client_id).first()
server = smtplib.SMTP(self.smtp_server, self.smtp_port)
server.ehlo()
server.starttls()
server.ehlo()
server.login(self.from_address, self.from_password)
...
try:
server.sendmail(self.from_address, recipients, message_body.as_string())
I am getting this error:
File "/usr/lib/python3.5/smtplib.py", line 730, in login
raise last_exception
File "/usr/lib/python3.5/smtplib.py", line 721, in login
initial_response_ok=initial_response_ok)
File "/usr/lib/python3.5/smtplib.py", line 627, in auth
initial_response = (authobject() if initial_response_ok else None)
File "/usr/lib/python3.5/smtplib.py", line 664, in auth_login
raise SMTPAuthenticationError(code, resp)
smtplib.SMTPAuthenticationError: (500, b"5.3.3 Unrecognized command 'cmFwcG9ydEBza2ltbWVsZnJpdC5kaw==' [AM5PR0701CA0011.eurprd07.prod.outlook.com]")
Stuff that I tried:
Opened port 587 on the production server
Contacted Office support to add the production server IP adress to the trusted list

This has been fixed by updating python to 3.5.1 (from 3.5.0).

Related

SSL error while sending email using smtp with Python

I want to send an email using outlook. The code is as follows:
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg['From'] = '*******'
msg['Subject'] = 'Some subject here'
msg['To'] = '********'
msg.set_content('Some text here')
with smtplib.SMTP_SSL('smtp-mail.outlook.com', 587) as smtp:
smtp.login('******', '****')
smtp.send_message(msg)
print('Email sent!')
I get the following error:
---------------------------------------------------------------------------
SSLError Traceback (most recent call last)
<ipython-input-8-4d5956f55c88> in <module>
6 msg.set_content('Some text here')
7
----> 8 with smtplib.SMTP_SSL('smtp-mail.outlook.com', 587) as smtp:
9 smtp.login('sender_email', 'password')
10 smtp.send_message(msg)
~/anaconda/envs/quant2/lib/python3.6/smtplib.py in __init__(self, host, port, local_hostname, keyfile, certfile, timeout, source_address, context)
1029 self.context = context
1030 SMTP.__init__(self, host, port, local_hostname, timeout,
-> 1031 source_address)
1032
1033 def _get_socket(self, host, port, timeout):
~/anaconda/envs/quant2/lib/python3.6/smtplib.py in __init__(self, host, port, local_hostname, timeout, source_address)
249
250 if host:
--> 251 (code, msg) = self.connect(host, port)
252 if code != 220:
253 self.close()
~/anaconda/envs/quant2/lib/python3.6/smtplib.py in connect(self, host, port, source_address)
334 if self.debuglevel > 0:
335 self._print_debug('connect:', (host, port))
--> 336 self.sock = self._get_socket(host, port, self.timeout)
337 self.file = None
338 (code, msg) = self.getreply()
~/anaconda/envs/quant2/lib/python3.6/smtplib.py in _get_socket(self, host, port, timeout)
1037 self.source_address)
1038 new_socket = self.context.wrap_socket(new_socket,
-> 1039 server_hostname=self._host)
1040 return new_socket
1041
~/anaconda/envs/quant2/lib/python3.6/ssl.py in wrap_socket(self, sock, server_side, do_handshake_on_connect, suppress_ragged_eofs, server_hostname, session)
405 suppress_ragged_eofs=suppress_ragged_eofs,
406 server_hostname=server_hostname,
--> 407 _context=self, _session=session)
408
409 def wrap_bio(self, incoming, outgoing, server_side=False,
~/anaconda/envs/quant2/lib/python3.6/ssl.py in __init__(self, sock, keyfile, certfile, server_side, cert_reqs, ssl_version, ca_certs, do_handshake_on_connect, family, type, proto, fileno, suppress_ragged_eofs, npn_protocols, ciphers, server_hostname, _context, _session)
815 # non-blocking
816 raise ValueError("do_handshake_on_connect should not be specified for non-blocking sockets")
--> 817 self.do_handshake()
818
819 except (OSError, ValueError):
~/anaconda/envs/quant2/lib/python3.6/ssl.py in do_handshake(self, block)
1075 if timeout == 0.0 and block:
1076 self.settimeout(None)
-> 1077 self._sslobj.do_handshake()
1078 finally:
1079 self.settimeout(timeout)
~/anaconda/envs/quant2/lib/python3.6/ssl.py in do_handshake(self)
687 def do_handshake(self):
688 """Start the SSL/TLS handshake."""
--> 689 self._sslobj.do_handshake()
690 if self.context.check_hostname:
691 if not self.server_hostname:
SSLError: [SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:852)
Microsoft Outlook uses STARTTLS when sending an email. So you need to replace smtplib.SMTP_SSL with smtplib.SMTP and you need to call starttls
reference: smtplib.SMTP.starttls
import smtplib
from email.message import EmailMessage
sender = 'somename#outlook.com'
recipient = 'somename#gmail.com'
msg = EmailMessage()
msg.set_content('this is a test')
msg['From'] = 'somename#outlook.com'
msg['To'] = 'somename#gmail.com'
msg['Subject'] = 'test email'
with smtplib.SMTP('smtp.office365.com', 587) as server:
server.ehlo()
server.starttls()
server.ehlo()
server.ehlo()
server.login('your_login', "your_password", initial_response_ok=True)
server.ehlo()
server.sendmail(sender, recipient, msg.as_string())
print('Email sent!')
server.close()
Here is the Outlook message in my Gmail account.
I noted that I had to change my Outlook password, because it had a \n, which Python read as a new line.
----------------------------------------
My system information
----------------------------------------
Platform: macOS
OS Version: 10.15.7
Python Version: 3.9
----------------------------------------
Your question didn't identity the type of Outlook account you have.
Free account
Corporate account
You stated in the comments below that your error message included ask your email administrator. I haven't seem this message with the Free account so I'm assuming that you might have a Corporate account. If you do have the latter please review this Enable or disable authenticated client SMTP submission, because an email administrator would need to enable Authenticated SMTP on your corporate account.
The answer from user "Life is complex" is almost right. I would like to add few more things from myside which might help. I am not very sure which python version you are using here. I am guessing it as Python 3.X. You need to go through based on actual version of python you are using in your case.
From Python smtplib documents, link. Please check which python version you are using with below guide line.
class smtplib.SMTP_SSL(host='', port=0, local_hostname=None,
keyfile=None, certfile=None, [timeout, ]context=None,
source_address=None) An SMTP_SSL instance behaves exactly the same as
instances of SMTP. SMTP_SSL should be used for situations where SSL is
required from the beginning of the connection and using starttls() is
not appropriate. If host is not specified, the local host is used. If
port is zero, the standard SMTP-over-SSL port (465) is used. The
optional arguments local_hostname, timeout and source_address have the
same meaning as they do in the SMTP class. context, also optional, can
contain a SSLContext and allows configuring various aspects of the
secure connection. Please read Security considerations for best
practices.
keyfile and certfile are a legacy alternative to context, and can
point to a PEM formatted private key and certificate chain file for
the SSL connection.
Changed in version 3.3: context was added.
Changed in version 3.3: source_address argument was added.
Changed in version 3.4: The class now supports hostname check with
ssl.SSLContext.check_hostname and Server Name Indication (see
ssl.HAS_SNI).
Deprecated since version 3.6: keyfile and certfile are deprecated in
favor of context. Please use ssl.SSLContext.load_cert_chain() instead,
or let ssl.create_default_context() select the system’s trusted CA
certificates for you.
Changed in version 3.9: If the timeout parameter is set to be zero, it
will raise a ValueError to prevent the creation of a non-blocking
socket
You need to check that SSLV3 is enabled at Server end or not. Check out this link to see which client version can connect to which server version SSL Version Compatibility first.
import smtplib
import ssl
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
#Above line is required to switch default SSLV3 protocol to TLS, recommended by python docs
# If you want to use SSLV3 and you are sure that it is enabled on server end then use
#context = ssl.SSLContext(ssl.PROTOCOL_SSLv3)
connection = smtplib.SMTP('smtp-mail.outlook.com', 587)
connection.ehlo()
connection.starttls(context=context)
connection.ehlo()
connection.login('now_your_real_login_data#outlook.com', 'otherwise_SMTPServerDisconnect')
The accepted answer didn't work for me, I kept getting this error:
smtplib.SMTPNotSupportedError: STARTTLS extension not supported by server.
I also tried SMTP_SSL instead of SMTP:
context = ssl.SSLContext(ssl.PROTOCOL_TLS)
with smtplib.SMTP_SSL('smtp-mail.outlook.com', 587, context=context) as server:
server.ehlo()
server.starttls(context=context)
but got this error:
[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1131)
Fortunately this post (thanks #dhruv-gami) helped me find my issue.
I found out that my hostname (using WSL on windows) is uppercase, but Outlook servers do not accept uppercase host names.
The solution is to just add a lowercase string in the ehlo commands:
with smtplib.SMTP('smtp.office365.com', 587) as server:
server.ehlo('lowercase')
server.starttls()
server.ehlo('lowercase')
server.login('your_login', "your_password", initial_response_ok=True)

flask mail error “SMTPServerDisconnected('please run connect() first')”

I am writing a little web application based on Miguel Grinberg's Flasky. I use the exact same code for user send reset password mail using gmail.
The following as my email.py file here i can implement mail sending function
def send_password_reset_email(user):
token = user.get_reset_password_token()
send_email(_('[Microblog] Reset Your Password'),
sender=current_app.config['ADMINS'][0],
recipients=[user.email],
text_body=render_template('email/reset_password.txt',
user=user, token=token),
html_body=render_template('email/reset_password.html',
user=user, token=token))
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
def send_email(subject, sender, recipients, text_body, html_body):
msg = Message(subject, sender=sender, recipients=recipients)
msg.body = text_body
msg.html = html_body
Thread(target=send_async_email,
args=(current_app._get_current_object(), msg)).start()
In routes.py file im getting email from the user and if the user email match then i well send the token to the user via mail
#bp.route('/reset_password_request', methods=['GET', 'POST'])
def reset_password_request():
if current_user.is_authenticated:
return redirect(url_for('main.index'))
form = ResetPasswordRequestForm()
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user:
send_password_reset_email(user)
flash(
_('Check your email for the instructions to reset your password'))
return redirect(url_for('auth.login'))
return render_template('auth/reset_password_request.html',
title=_('Reset Password'), form=form)
#bp.route('/reset_password/<token>', methods=['GET', 'POST'])
def reset_password(token):
if current_user.is_authenticated:
return redirect(url_for('main.index'))
user = User.verify_reset_password_token(token)
if not user:
return redirect(url_for('main.index'))
form = ResetPasswordForm()
if form.validate_on_submit():
user.set_password(form.password.data)
db.session.commit()
flash(_('Your password has been reset.'))
return redirect(url_for('auth.login'))
return render_template('auth/reset_password.html', form=form)
In model.py file in the user model i generate a token for a user and also check the user token
def get_reset_password_token(self, expires_in=600):
return jwt.encode(
{'reset_password': self.id, 'exp': time() + expires_in},
current_app.config['SECRET_KEY'],
algorithm='HS256').decode('utf-8')
#staticmethod
def varify_reset_password_token(token):
try:
id = jwt.decode(token, current_app.config['SECRET_KEY'],
algorithms=['HS256'])['reset_password']
except:
return
return User.query.get(id)
my flask mail setup is as follows config.py file
MAIL_SERVER = os.environ.get('MAIL_SERVER')
MAIL_PORT = int(os.environ.get('MAIL_PORT') or 25)
MAIL_USE_TLS = os.environ.get('MAIL_USE_TLS') is not None
MAIL_USERNAME = os.environ.get('MAIL_USERNAME')
MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD')
ADMINS =['socialtraffic#gmail.com']
The following Error i get in the terminal
Traceback (most recent call last):
File "c:\python38\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "c:\python38\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "C:\Users\Ijaz Bacha\project\microblog1\app\email.py", line 9, in send_async_email
mail.send(msg)
File "c:\users\ijaz bacha\project\microblog1\venv\lib\site-packages\flask_mail.py", line 492, in send
message.send(connection)
File "c:\users\ijaz bacha\project\microblog1\venv\lib\site-packages\flask_mail.py", line 152, in __exit__
self.host.quit()
File "c:\python38\lib\smtplib.py", line 988, in quit
res = self.docmd("quit")
File "c:\python38\lib\smtplib.py", line 424, in docmd
self.putcmd(cmd, args)
File "c:\python38\lib\smtplib.py", line 371, in putcmd
self.send(str)
File "c:\python38\lib\smtplib.py", line 363, in send
raise SMTPServerDisconnected('please run connect() first')
smtplib.SMTPServerDisconnected: please run connect() first
I am also doing the same tutorial and ran into the same problem. I found the answer on Miguel's Blog:
You need two terminal windows.
The first terminal running your local mail server that emulates your emails being sent:
$(venv) python -m smtpd -n -c DebuggingServer localhost:8025
Your main flask terminal window with the following required commands (FLASK_DEBUG=1 is optional but highly recommended for troubleshooting):
$ export FLASK_APP=microblog.py
$ export FLASK_DEBUG=1
$ export MAIL_SERVER=localhost
$ export MAIL_PORT=8025
$ flask run
This solved my problems.
In my experience, a while ago I had a very similar issue that you you were having. After troubleshooting, I found out that my code worked when I would create a mail class, and call function like $mailclass.ehlo etc.
Based on the error its having an issue connecting or staying connected. Try calling the connect methods in the function itself and close of the connection after each email.
I decided to change the following line in the app/__init__.py file:
mail = Mail(app)
with:
mail = Mail()
mail.init_app(app)
Solved the issue for me

Python3 Slack RTMClient in not working behind proxy

I am trying to create a simple Python bot for my project. Everything is working fine on my localhost, but the same code stops working behind the network firewall which needs environment proxy to be set.
from slack import RTMClient
proxy='http://XXXX:NNNN'
token='XXXX'
class Botso():
def __init__(self):
self.proxy=self.get_proxy()
self.rt= RTMClient(
token=token,
connect_method='rtm.start',
proxy=self.proxy
)
def get_proxy(self):
host=socket.gethostname()
if "internal" in host:
return None
elif "XXX" in host:
return proxy
#RTMClient.run_on(event="message")
def say_hello(**payload):
data = payload['data']
web_client = payload['web_client']
if 'text' in data and 'hii' in data['text']:
channel_id = data['channel']
thread_ts = data['ts']
user = data['user'] # This is not username but user ID (the format is either U*** or W***)
web_client.chat_postMessage(
channel=channel_id,
text=f"Hi <#{user}>!"
#thread_ts=thread_ts
)
if __name__ == '__main__':
botso=Botso()
botso.rt.start()
The error I am getting while initializing the RTMClient is
Traceback (most recent call last):
File "botso.py" , in <module>
botso.rt.start()
File "/usr/lib64/python3.6/http/client.py", line 974, in send
self.connect()
File "/usr/lib64/python3.6/http/client.py", line 1407, in connect
super().connect()
File "/usr/lib64/python3.6/http/client.py", line 950, in connect
self._tunnel()
File "/usr/lib64/python3.6/http/client.py", line 929, in _tunnel
message.strip()))
OSError: Tunnel connection failed: 403 Forbidden
I have other code in the same environment which uses the same proxy to send slack messages and works fine bu using request api.
params={
'token': self.slack_token,
'types': ['public_channel','private_channel']
}
slack_url='https://slack.com/api/conversations.list'
response = requests.get(url=slack_url,params=params,proxies=self.proxy).json()
How can we make the RTMClient work with proxy and Python3.
Couldn't find much help in slack API documents.

Issue when trying to send emails through Python

OS: MacCatalinva V10.15.3
Python: 3.7.7
PiP: 20.0.2
Hey,
I'm new to coding so I'm not sure what this really means.
I'm trying to send emails via Python through Gmail, I've set my account to accept "Less secure app access" and followed the steps in this guide, but all I get is the following:
`[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1076)
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/smtplib.py", line 354, in send
self.sock.sendall(s)
OSError: [Errno 9] Bad file descriptor
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/mymac/Desktop/Test2.py", line 34, in
server.quit()
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/smtplib.py", line 984, in quit
res = self.docmd("quit")
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/smtplib.py", line 420, in docmd
self.putcmd(cmd, args)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/smtplib.py", line 367, in putcmd
self.send(str)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/smtplib.py", line 357, in send
raise SMTPServerDisconnected('Server not connected')
smtplib.SMTPServerDisconnected: Server not connected`
And this is my Code:
import smtplib
import ssl
sender_email = "myemailadress#gmail.com"
receiver_email = "myadress#hotmail.com"
message = """\
Subject: Hi there
This message is sent from Python."""
# Send email here
smtp_server = "smtp.gmail.com"
port = 587 # For starttls
sender_email = "myemailadress#gmail.com"
password = input("Type your password and press enter: ")
# Create a secure SSL context
context = ssl.create_default_context()
# Try to log in to server and send email
try:
server = smtplib.SMTP(smtp_server, port)
server.ehlo() # Can be omitted
server.starttls(context=context) # Secure the connection
server.ehlo() # Can be omitted
server.login(sender_email, password)
# TODO: Send email here
except Exception as e:
# Print any error messages to stdout
print(e)
finally:
server.quit()
1)After this line:
server.login(sender_email, password)
make sure to send the message you have it.
For that:
server.sendmail(sender_email,receiver_email,message)
that's it, I hope.

Why do I get a "No SSL included in this python" when I run script using smtplib from a batch file but not when I run it manually?

I am able to send emails fine from a script using smtplib, but when I try to run it from a batch file or from task scheduler everything works except the email doesn't send at the end. I get a "No SSL" error.
I'm running this from a conda environment, but I've double checked that I calling python from within that environment and not base.
python version 3.7.3.
I call this function from another script and pass the email subject and message to the function.
def send_log_email(subject, message):
smtp_server = 'smtp.office365.com'
smpt_port = 25
sender = '[emailed address]'
pw = '[password]'
msg = MIMEMultipart()
msg['From'] = sender
msg['To'] = sender
msg['Subject'] = subject
msg.attach(MIMEText(message))
conn = SMTP(smtp_server,smtp_port)
conn.set_debuglevel(1)
conn.starttls()
conn.login(sender, pw)
conn.sendmail(sender, sender, msg.as_string())
Here's the error I get when I run it from a batch file.
send: 'ehlo []\r\n'
reply: b'250-Outlook Hello [IP]\r\n'
reply: b'250-SIZE 157286400\r\n'
reply: b'250-PIPELINING\r\n'
reply: b'250-DSN\r\n'
reply: b'250-ENHANCEDSTATUSCODES\r\n'
reply: b'250-STARTTLS\r\n'
reply: b'250-8BITMIME\r\n'
reply: b'250-BINARYMIME\r\n'
reply: b'250-CHUNKING\r\n'
reply: b'250 SMTPUTF8\r\n'
reply: retcode (250); Msg: b'outlook' Hello [IP]\nSIZE 157286400\nPIPELINING\nDSN\nENHANCEDSTATUSCODES\nSTARTTLS\n8BITMIME\nBINARYMIME\nCHUNKING\nSMTPUTF8'
send: 'STARTTLS\r\n'
reply: b'220 2.0.0 SMTP server ready\r\n'
reply: retcode (220); Msg: b'2.0.0 SMTP server ready'
Traceback (most recent call last):
File "path\my_script.py", line 136, in <module>
send_log_email(result, message)
File "path\my_email_script.py", line 31, in send_log_email
conn.starttls()
File "python_path\custom_environment\lib\smtplib.py", line 756, in starttls
raise RuntimeError("No SSL support included in this Python")
RuntimeError: No SSL support included in this Python
Contrary to most of what I found online, I needed to activate the environment in the batch file to get the script to run properly from task scheduler.
call C:\ProgramData\Anaconda3\Scripts\activate.bat
"C:\my_env_path\python.exe" "C:\my_script_path\my_script.py"
call C:\ProgramData\Anaconda3\Scripts\deactivate.bat
Not sure if I actually need to deactivate the environment or not, but there it is.

Resources