【发布时间】:2019-07-25 08:11:08
【问题描述】:
我的脚本
from stmplib import SMTP
con = SMTP(server, port)
con.starttls()
con.login(user, pass)
con.quit()
出现错误:
python2.7/ssl.py", line 847, in do_handshake self._sslobj.do_handshake()
当我对该服务器运行命令 openssl 时,它会出现错误 21:Verify return code: 21 (unable to verify the first certificate)。
我想知道如何在 python 选项的 smtplib 中指定“通过 tls 建立连接到电子邮件服务器时始终接受自签名证书”?
就像我在requests.get 设置键verify=False 中所做的那样。
更新
此带有自定义 smtp 类和 context = ssl._create_unverified_context() 的变体返回与上述相同的错误:
import smtplib
import ssl
class MySMTP(smtplib.SMTP):
def __init__(self, host='', port=0, timeout=5):
smtplib.SMTP.__init__(self, host, port, timeout=timeout)
self._host = host
def starttls(self, keyfile=None, certfile=None, context=None):
from urllib import _have_ssl
self.ehlo_or_helo_if_needed()
if not self.has_extn("starttls"):
raise SMTPNotSupportedError("STARTTLS extension not supported by server.")
(resp, reply) = self.docmd("STARTTLS")
if resp == 220:
if not _have_ssl:
raise RuntimeError("No SSL support included in this Python")
if context is not None and keyfile is not None:
raise ValueError("context and keyfile arguments are mutually "
"exclusive")
if context is not None and certfile is not None:
raise ValueError("context and certfile arguments are mutually "
"exclusive")
if context is None:
context = ssl._create_stdlib_context(certfile=certfile,
keyfile=keyfile)
self.sock = context.wrap_socket(self.sock,
server_hostname=self._host)
self.file = None
# RFC 3207:
# The client MUST discard any knowledge obtained from
# the server, such as the list of SMTP service extensions,
# which was not obtained from the TLS negotiation itself.
self.helo_resp = None
self.ehlo_resp = None
self.esmtp_features = {}
self.does_esmtp = 0
return (resp, reply)
con= MySMTP(server, port)
context = ssl._create_unverified_context()
con.starttls(context = context)
con.login(user, pass)
con.quit()
【问题讨论】:
-
您使用的是哪个版本的 Python?
-
问题状态 2.7
-
您的自签名证书是否来自 CA(“认证机构”)?
-
您是否尝试过使用
ssl._https_verify_certificates(enable=False)? (尽管这不应该影响这种情况)。对于第二个变体,请尝试context = ssl._create_unverified_context(cert_reqs=ssl.CERT_NONE)(或在创建上下文后手动执行相同的操作:context.verify_mode = ssl.CERT_NONE)。 -
感谢尝试,但都失败了。
标签: python python-2.7 ssl smtplib starttls