Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/email/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python smtplib发送不带密钥文件(仅certfile)的电子邮件_Python_Email_Smtp_Python 2.6 - Fatal编程技术网

使用Python smtplib发送不带密钥文件(仅certfile)的电子邮件

使用Python smtplib发送不带密钥文件(仅certfile)的电子邮件,python,email,smtp,python-2.6,Python,Email,Smtp,Python 2.6,尝试使用以下脚本发送带有证书文件的电子邮件: import smtplib client = smtplib.SMTP(myhost, myport) client.ehlo() client.starttls(certfile=mycertfile) client.ehlo() client.login(myusername, mypassword) client.sendmail(sender, receiver, Message) client.quit() 我得到以下错误: SSL

尝试使用以下脚本发送带有证书文件的电子邮件:

import smtplib

client = smtplib.SMTP(myhost, myport)
client.ehlo()
client.starttls(certfile=mycertfile)
client.ehlo()

client.login(myusername, mypassword)
client.sendmail(sender, receiver, Message)
client.quit()
我得到以下错误:

SSLError: error:140B0009:SSL routines:SSL_CTX_use_PrivateKey_file:PEM lib
我认为文档说明我需要提供一个私钥。我只有证书文件(base64 PEM格式)。我的devops说,在这种情况下不需要私钥,因为我不需要标识连接的本地端

问题:
有没有不提供私钥就发送电子邮件的方法?如果需要私钥,为什么?

使用SSL/TLS有两种方法:客户端已验证和“基本”,其中客户端未经验证。在客户端身份验证连接中,服务器和客户端都向另一方发送证书。在“基本”中,只有服务器可以执行此操作

如果您既不传递证书也不传递密钥文件,
smtplib
将使用基本连接,在该连接中,客户端经过身份验证

如果您使用证书,它将用于经过客户端身份验证的连接。在这种情况下,服务器将要求客户端通过签署握手消息来显示其拥有证书。为了让客户端能够做到这一点,它还需要私钥,私钥可以在证书文件中,也可以作为单独的密钥文件

长话短说,如果要使用客户端证书,还必须使用密钥。如果没有,您可以将两者都留空


OTOH,也许您有一个服务器证书文件或CA列表,您想用于连接

在这种情况下,您需要将其传递到
ssl.wrap\u socket
ca\u certs
参数中。由于您使用的是Python2.6,因此使用
smtplib
(Python3.3+有一个
context
参数)

如何解决这个问题取决于您的应用程序。例如,如果您不需要
ssl
进行任何其他操作,一个黑客解决方案是使用猴子补丁
ssl。用一个提供
ca\u证书的套接字(以及
cert\u reqs=cert\u REQUIRED
)来包装


一个更全面的解决方案是使用您自己的变体扩展
smtplib.SMTP
,该变体允许传入这些参数。

以下是一个猴子补丁:


使用来自

的根证书时,错误指的是SSLv3,原因可能是其中一个实现(客户端或服务器)将连接从TLSv1降级为SSLv3,或者因为OpenSSL重用了两个实现的错误代码(SSLv3到TLSv1的更改很少)。关于这个错误没有什么要说的了,它意味着您的证书文件不包含服务器的证书,也不包含与之相关的信任链。
class SMTPExt(smtplib.SMTP):
    """
    This class extends smtplib.SMTP and overrides the starttls method
    allowing extra parameters and forwarding them to ssl.wrap_socket.
    """

    def starttls(self, keyfile=None, certfile=None, **kwargs):
        self.ehlo_or_helo_if_needed()
        if not self.has_extn("starttls"):
            raise SMTPException("STARTTLS extension not supported by server.")
        (resp, reply) = self.docmd("STARTTLS")
        if resp == 220:
            self.sock = ssl.wrap_socket(self.sock, keyfile, certfile, **kwargs)
            self.file = SSLFakeFile(self.sock)
            # 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)