使用Python smtplib发送不包含密钥文件(仅包含证书文件)的电子邮件 [英] Sending email without keyfile (only certfile) using Python smtplib
问题描述
尝试使用以下脚本发送带有证书文件的电子邮件:
Trying to send email with a certificate file using the following script:
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
我认为文档( smtplib.html 和 ssl.html )说我需要提供一个私钥。我只有证书文件(base64 PEM格式)。我的开发人员说,在这种情况下不需要私钥,因为我不需要识别连接的本地端。
I think documentations (smtplib.html and ssl.html) say I need to provide a private key. I only have the certificate file (base64 PEM format). My devops says that a private key is not required in this case because I do not need to identify the local side of the connection.
是否可以在不提供私钥的情况下发送电子邮件?如果需要私钥,为什么?
Is there a way to send the email without providing the private key? If a private key is required, why?
推荐答案
使用SSL / TLS的方法有两种:客户端身份验证和基本客户端未经身份验证的位置。在客户端身份验证的连接中,服务器和客户端都向对方发送证书。
There are two ways to use SSL/TLS: client authenticated and "basic" where the client is unauthenticated. In client authenticated connections, the both the server and the client send a certificate to the other. In "basic" only the server does.
如果您既未通过证书也未通过密钥文件,则将使用 smtplib
If you pass neither a certificate nor a keyfile, smtplib
will use a basic connection, where the client is authenticated.
如果您使用证书,它将用于客户端认证的连接。在这种情况下,服务器将通过签名握手消息来要求客户端显示其拥有证书。为了使客户端能够做到这一点,它还需要私钥,该私钥可以在证书文件中,也可以作为单独的密钥文件。
If you use a certificate, it will be used for a client authenticated connection. In that case, the server will demand that the client shows it owns the certificate by signing a handshake message. For the client to be able to do that it also needs the private key, which can be either in the certificate file or as a separate keyfile.
长话短说,如果要使用客户端证书,还必须使用密钥。如果没有,则可以将两者都保留为空。
Long story short, if you want to use a client certificate, you must also use a key. If not, you can just leave both empty.
OTOH,也许您有服务器证书文件或想要的CA列表可以与连接一起使用?
OTOH, maybe you have a server certificate file or CA list you want to use with the connection?
在那种情况下,您需要将其传递给 ssl.wrap_socket
c $ c> ca_certs 参数。由于您使用的是Python 2.6,所以没有简单的方法使用 smtplib
(Python 3.3+具有 context
自变量< a href = https://docs.python.org/3.4/library/smtplib.html#smtplib.SMTP.starttls rel = nofollow> starttls )。
In that case you need to pass it to ssl.wrap_socket
in the ca_certs
parameter. Since you use Python 2.6 there's no easy way to do that with smtplib
(Python 3.3+ has a context
argument to starttls).
如何解决此问题取决于您的应用程序。例如,如果您不需要 ssl
进行其他操作,则不可靠的解决方案是猴子修补 ssl.wrap_socket
,其中一个可以提供您的 ca_cert
(可能还有 cert_reqs = CERT_REQUIRED
)。
How to solve this depends on your application. For example, if you do not need ssl
for anything else, a hackish solution would be to monkey-patch ssl.wrap_socket
with one that provides your ca_cert
(as well as cert_reqs=CERT_REQUIRED
, likely).
一个更完善的解决方案是使用您自己的允许传入这些参数的变体来扩展 smtplib.SMTP
。
A more full blown solution would be to extend smtplib.SMTP
with your own variant that does allow passing in those parameters.
这篇关于使用Python smtplib发送不包含密钥文件(仅包含证书文件)的电子邮件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!