4

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)
Life is complex
  • 15,374
  • 5
  • 29
  • 58
Echchama Nayak
  • 971
  • 3
  • 23
  • 44

3 Answers3

5

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.

enter image description here

enter image description here

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.

  1. Free account
  2. 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.

Life is complex
  • 15,374
  • 5
  • 29
  • 58
2

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')
Chinmay T
  • 745
  • 1
  • 9
  • 17
  • I modified my answer. I removed the SSLContext piece and changed my password to one that didn't contain a new line character. I was able to send an email correctly with no errors. – Life is complex Nov 15 '21 at 17:51
0

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) 
healthybodhi
  • 306
  • 2
  • 4