使用带有Python的smtp发送电子邮件时出现SSL错误

6tdlim6h  于 2023-01-27  发布在  Python
关注(0)|答案(3)|浏览(640)

我想用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)
9wbgstp7

9wbgstp71#

Microsoft Outlook在发送电子邮件时使用STARTTLS。因此,您需要将smtplib.SMTP_SSL替换为smtplib.SMTP,并且需要调用starttls
参考文件:smtplib. SMTP.启动

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帐户类型。
1.免费帐户
1.公司账户
您在下面的评论中指出,您的错误消息包括ask your email administrator.我没有看到这个消息与 * 免费帐户 ,所以我假设你可能有一个 * 公司帐户。 如果你有后者,请检查此启用或禁用验证客户端SMTP提交,因为电子邮件管理员将需要启用Authenticated SMTP对您的公司帐户。

zphenhs4

zphenhs42#

用户"生活很复杂"的回答几乎是正确的。我想从我的Angular 补充一些可能会有帮助的东西。我不太确定你在这里使用的是哪个python版本。我猜是Python 3.X。你需要根据你在你的案例中使用的python的实际版本进行检查。
来自Python smtplib文档link。请检查您使用的是哪个Python版本。
类smtplib. SMTP_SSL(主机="",端口= 0,本地主机名=无,密钥文件=无,证书文件=无,[超时,]上下文=无,源地址=无)SMTP_SSL示例的行为与SMTP示例完全相同。SMTP_SSL应用于从连接开始就需要SSL并使用starttl的情况()不合适。如果未指定主机,则使用本地主机。如果端口为零,则使用标准SMTP-over-SSL端口(465)。可选参数local_hostname、timeout和source_address的含义与它们在SMTP类中的含义相同。context也是可选的,可以包含SSLContext并允许配置安全连接的各个方面。请阅读安全注意事项以了解最佳做法。
keyfile和certfile是context的传统替代方案,可以指向SSL连接的PEM格式私钥和证书链文件。
版本3.3中的变更:添加了上下文。
版本3.3中的变更:已添加source_address参数。
版本3.4中的变更:该类现在支持使用ssl.SSLContext.check_hostname和服务器名称指示进行主机名检查(请参见ssl.HAS_SNI)。
自版本3.6起弃用:密钥文件和证书文件已弃用,请改用上下文。请改用ssl. SSLContext. load_cert_chain(),或让ssl. create_default_context()为您选择系统的受信任CA证书。
版本3.9中的变更:如果将timeout参数设置为零,它将引发ValueError以阻止创建非阻塞套接字
您需要检查服务器端是否启用了SSLV3。请先查看此链接以查看哪个客户端版本可以连接到哪个服务器版本SSL版本兼容性。

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')
g6ll5ycj

g6ll5ycj3#

接受的答案不为我工作,我不断得到这个错误:

smtplib.SMTPNotSupportedError: STARTTLS extension not supported by server.

我还尝试了SMTP_SSL而不是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)

但得到了这个错误:

[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1131)

幸运的是,这个post(感谢@dhruv-gami)帮助我找到了我的问题。

我发现我的主机名(在Windows上使用WSL)是大写的,但Outlook服务器不接受大写的主机名。

解决方案是在ehlo命令中添加一个小写字符串:

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)

相关问题