Ser*_*ity 6 python ssl smtplib python-2.7 starttls
我的剧本
from stmplib import SMTP
con = SMTP(server, port)
con.starttls()
con.login(user, pass)
con.quit()
Run Code Online (Sandbox Code Playgroud)
落入错误:
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设置key中所做的那样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()
Run Code Online (Sandbox Code Playgroud)
Ped*_*ito 11
迟到的答案,但我修复了使用ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:852), 即:python 3.7ssl._create_unverified_context()
import smtplib, ssl
context = ssl._create_unverified_context()
with smtplib.SMTP_SSL("domain.tld", 465, context=context) as server:
server.login(user, password)
server.sendmail(sender_email, receiver_email, message.as_string())
Run Code Online (Sandbox Code Playgroud)
看来您使用子类化SMTP类和重写starttls()方法来接受context参数的方法确实是可行的方法 - 实际上甚至在 Python 3.x 中引入了这种方法。
然而:
con = MySMTP(server, port)
context = ssl.create_default_context(cafile=PATH_TO_CERTIFICATE_AUTHORITY_ROOT_CRT_FILE)
con.starttls(context=context)
con.login(user, pass)
con.quit()
Run Code Online (Sandbox Code Playgroud)
应该有效,而不是未经验证的上下文。
当您对证书进行自签名时,您使用了自己的证书颁发机构,因此您之前可能创建了根 CA 证书。
您的 SMTP 客户端必须知道此根证书才能验证您的 SMTP 服务器证书。
因此,找到该文件,将其放在 SMTP 客户端可访问的位置,并将该路径的值设置为PATH_TO_CERTIFICATE_AUTHORITY_ROOT_CRT_FILE.
相反,你所做的是:
ssl._create_stdlib_context(certfile=certfile, keyfile=keyfile)
Run Code Online (Sandbox Code Playgroud)
但是certfile和keyfile是客户端证书和密钥 - 某些服务器不会接受来自未经验证的客户端的连接。
有用的链接:
ssl.create_default_context() 文档
如果您找不到根证书,您可以从头开始(只需忽略图片上的所有 MacOS 窗口 - 您的 SMTP 客户端想要访问根证书文件 - 他们添加到浏览器的根证书文件在本指南中)
| 归档时间: |
|
| 查看次数: |
599 次 |
| 最近记录: |