使用带 Python 的 smtp 发送电子邮件时出现 SSL 错误
SSL error while sending email using smtp with Python
我想使用 outlook 发送电子邮件。代码如下:
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!')
我收到以下错误:
---------------------------------------------------------------------------
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 在发送电子邮件时使用 STARTTLS。所以你需要用 smtplib.SMTP
替换 smtplib.SMTP_SSL
并且你需要调用 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()
这是我的 Gmail 帐户中的 Outlook 邮件。
我注意到我必须更改我的 Outlook 密码,因为它有一个 \n
,Python 读作一个新行。
----------------------------------------
My system information
----------------------------------------
Platform: macOS
OS Version: 10.15.7
Python Version: 3.9
----------------------------------------
你的问题没有确定你拥有的 Outlook 帐户类型。
- 免费帐户
- 企业账户
你在下面的评论中说你的错误消息包括 ask your email administrator.
我没有在 免费帐户 中看到这条消息所以我假设你可能拥有 公司帐户。 如果您有后者,请查看此 Enable or disable authenticated client SMTP submission,因为电子邮件管理员需要在您的公司帐户上启用 Authenticated SMTP
。
用户“生活是复杂的”的回答几乎是正确的。我想从我身边补充一些可能有帮助的东西。我不太确定您在这里使用的 python 版本。我猜它是 Python 3.X。您需要根据在您的案例中使用的 python 的实际版本进行检查。
来自 Python smtplib 文档,link。请检查您使用的 python 版本与下面的指南。
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
您需要检查服务器端是否启用了SSLV3。查看此 link 以查看哪个客户端版本可以首先连接到哪个服务器版本 SSL Version Compatibility。
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')
我想使用 outlook 发送电子邮件。代码如下:
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!')
我收到以下错误:
---------------------------------------------------------------------------
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 在发送电子邮件时使用 STARTTLS。所以你需要用 smtplib.SMTP
替换 smtplib.SMTP_SSL
并且你需要调用 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()
这是我的 Gmail 帐户中的 Outlook 邮件。
我注意到我必须更改我的 Outlook 密码,因为它有一个 \n
,Python 读作一个新行。
----------------------------------------
My system information
----------------------------------------
Platform: macOS
OS Version: 10.15.7
Python Version: 3.9
----------------------------------------
你的问题没有确定你拥有的 Outlook 帐户类型。
- 免费帐户
- 企业账户
你在下面的评论中说你的错误消息包括 ask your email administrator.
我没有在 免费帐户 中看到这条消息所以我假设你可能拥有 公司帐户。 如果您有后者,请查看此 Enable or disable authenticated client SMTP submission,因为电子邮件管理员需要在您的公司帐户上启用 Authenticated SMTP
。
用户“生活是复杂的”的回答几乎是正确的。我想从我身边补充一些可能有帮助的东西。我不太确定您在这里使用的 python 版本。我猜它是 Python 3.X。您需要根据在您的案例中使用的 python 的实际版本进行检查。
来自 Python smtplib 文档,link。请检查您使用的 python 版本与下面的指南。
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
您需要检查服务器端是否启用了SSLV3。查看此 link 以查看哪个客户端版本可以首先连接到哪个服务器版本 SSL Version Compatibility。
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')