python - 带有 TLS 的 Twisted Python ESMTP 邮件服务器/转储

标签 python ssl smtp twisted

正如你们中的一些人最近可能看到的那样,我正在努力建立并运行一个简单的客户端/服务器 TCP 连接,我可以根据 https://twistedmatrix.com/documents/14.0.0/core/howto/ssl.html#starttls-server 中的 Twisted 示例在发出命令时切换到 TLS。 , 但修改为使用证书身份验证。好吧,好消息是现在可以使用了!感谢@Jean-PaulCalderone 和@Glyph 的帮助。

但是我现在想将我的服务器端代码扩展/转换为 ESMTP 服务器 - 即,让客户端连接,然后服务器将 STARTTLS 作为其 EHLO 响应的一部分进行通告,如果客户端随后以 STARTTLS 响应,则协商并切换到安全连接。我相信我需要修改下面服务器代码中的“TLSServer”类,使其继承自 twisted.mail.smtp.ESMTP 而不是 twisted.protocols.basic.LineReceiver - 但这里不能 100% 确定.此外,可在 http://twistedmatrix.com/documents/12.1.0/api/twisted.mail.smtp.ESMTP.html 找到 t.m.s.ESMTP 的 API 文档。在地面上有点薄(很多未记录的方法)。

任何人都可以 a) 告诉我关于修改现有服务器代码的继承是否正确,以及 b) 提供一些方法的解释,例如 do_EHLO 和 ext_STARTTLS?

最终我正在寻找一个 SMTP 服务器,它将接受(安全的)客户端连接,从客户端接收邮件,并将邮件转储到文件。

我现有的服务器代码:

from twisted.internet import ssl, protocol, defer, task, endpoints
from twisted.protocols.basic import LineReceiver
from twisted.python.modules import getModule
from OpenSSL.crypto import load_privatekey, load_certificate, FILETYPE_PEM

class TLSServer(LineReceiver):
    def lineReceived(self, line):
        print("received: " + line)
        if line == "STARTTLS":
            print("-- Switching to TLS")
            self.sendLine('READY')
            self.transport.startTLS(self.factory.options)

def main(reactor):
    caCertFile = open("/some/path/to/cacert.pem","r")
    certFile = open("/some/path/to/server.crt","r")
    keyFile = open("/some/path/to/server.key","r")
    caCertData = caCertFile.read()
    pKeyData = keyFile.read()
    certData = certFile.read()
    caCert = ssl.Certificate.loadPEM(caCertData)
    cert = load_certificate(FILETYPE_PEM, certData)
    pKey = load_privatekey(FILETYPE_PEM, pKeyData)
    factory = protocol.Factory.forProtocol(TLSServer)
    factory.options = ssl.CertificateOptions(privateKey=pKey, certificate=cert, trustRoot=caCert)
    endpoint = endpoints.TCP4ServerEndpoint(reactor, 8000)
    endpoint.listen(factory)
    return defer.Deferred()

if __name__ == '__main__':
    import starttls_server
    task.react(starttls_server.main)

提前致谢!

最佳答案

您不应该拥有自己的 TLSServer 类。相反,直接使用 ESMTP 作为您的服务器类。您已经确定 ext_STARTTLS 方法很有趣 - 基本上,它已经实现了您的 TLSServer 在其 lineReceived 方法中具有的逻辑。

与其执行 factory.options = ...,不如在构建时向 ESMTP 传递一个 contextFactory 参数。最简单的,你可以做这样的事情:

sslCtxFactory = ssl.CertificateOptions(...)
factory = Factory.forProtocol(lambda: ESMTP(contextFactory=sslCtxFactory))

相信 ESMTP 默认情况下将STARTTLS 宣传为扩展 - 至少,这是对 实现的快速阅读>ESMTP.extensions() 方法对我说。

关于python - 带有 TLS 的 Twisted Python ESMTP 邮件服务器/转储,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26218289/

相关文章:

python - 查找两个 numpy 数组之间的索引映射

python - 为什么 K 最近点到原点的堆比排序慢?

ssl - Cipher 用于浏览器使用的请求数据加密

python - 通过 GMAIL SMTP 的 SVN 通知

javascript - 将 autoload_static 与 Holoviews 图形一起使用?

python - 使用 PySocks 和 Socks5 代理时如何禁用 SSL 证书验证?

ssl - 常规子域和移动子域上单独的 SSL 证书

Python smtplib 代理支持

smtp - 如何检查我的 ISP 是否阻止了端口 25?

python - Matplotlib:关闭轴并同时设置面色是不可能的吗?