【发布时间】:2014-12-07 22:30:36
【问题描述】:
感谢这里的几个用户,我现在有一个(几乎)工作的 SMTP 服务器,它支持根据需要从纯文本切换到 TLS 连接。基本服务器代码是:
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
from custom_esmtp import mySMTP
def main(reactor):
caCertFile = open("/opt/tesa/etc/certs/CA/cacert.pem","r")
certFile = open("/opt/tesa/etc/certs/server/server.crt","r")
keyFile = open("/opt/tesa/etc/certs/server/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)
sslCtxFactory = ssl.CertificateOptions(privateKey=pKey, certificate=cert, trustRoot=caCert)
myESMTP = mySMTP(contextFactory=sslCtxFactory)
factory = protocol.Factory.forProtocol(lambda: mySMTP(contextFactory=sslCtxFactory))
endpoint = endpoints.TCP4ServerEndpoint(reactor, 8001)
endpoint.listen(factory)
return defer.Deferred()
if __name__ == '__main__':
import starttls_server
task.react(starttls_server.main)
如您所见 - 我创建了 mySMTP 类的对象实例 (myESMTP)。正如您可能猜到的那样(在 custom_esmtp.py 中)是从twisted 的 mail.py 中的 ESMTP 派生的——它又派生自 SMTP 类——我们已经为 myESMTP 类编写了几个函数重载,未来还会有更多。
然而,在twisted的mail.py中,SMTP类定义有一个方法“validateFrom”:
def validateFrom(self, helo, origin):
<<snip>>
if self.portal:
result = self.portal.login(
cred.credentials.Anonymous(),
None,
IMessageDeliveryFactory, IMessageDelivery)
def ebAuthentication(err):
"""
Translate cred exceptions into SMTP exceptions so that the
protocol code which invokes C{validateFrom} can properly report
the failure.
"""
if err.check(cred.error.UnauthorizedLogin):
print ("Unauth Login")
exc = SMTPBadSender(origin)
elif err.check(cred.error.UnhandledCredentials):
exc = SMTPBadSender(
origin, resp="Unauthenticated senders not allowed")
else:
return err
return defer.fail(exc)
result.addCallbacks(
self._cbAnonymousAuthentication, ebAuthentication)
def continueValidation(ignored):
"""
Re-attempt from address validation.
"""
return self.validateFrom(helo, origin)
result.addCallback(continueValidation)
return result
raise SMTPBadSender(origin)
因此,如果定义了 self.portal,则该方法在退出 if 条件之前返回 - 但如果未定义,它将引发 SMTPBadSender 错误。并且在 SMTP 类定义中没有任何地方定义了门户。
我注意到 self.portal 确实在 SMTPFactory 类的 init 方法中定义 - 我们是否应该以某种方式使用它 - 如果是这样,有人可以解释一下这将如何影响我们的服务器代码?也就是说,即使这似乎也没有将 self.portal 设置为任何“有意义的”......
def init(自我,门户 = 无): self.portal = 门户
这可能是 SMTP 类定义中的错误?似乎不太可能......也许我们只需要创建我们自己的 validateFrom 覆盖版本,并删除代码以在 self.portal 未定义时引发错误?不过,我再次尝试了这个 - (删除在 if 块之外生成错误的 2 行代码) - 结果是“不寻常的”......
mail from: me@localhost
250 Sender address accepted
rcpt to:you@somedomain.test
503 Must have sender before recipient
一如既往的感谢!
【问题讨论】:
-
你为什么不想要一个门户?是不是因为你不知道怎么做?
-
嗨@Jean-PaulCalderone - 我想就是这样......试图解决如何在那里实现门户/ SmtpFactory以及我上面的服务器代码(支持TLS / cert)。我现在想我真的应该有一个门户,因为我认为我下面的超载解决方案实际上只是“躲避子弹”。作为上述服务器代码的一部分,我能否寻求一些帮助来创建门户等?正如您可能已经意识到的那样 - 将我的头包裹在其中的一些内容上是具有挑战性的!
-
我现在有:).... emailserver.tac (几乎所有“主要”的后半部分都可以在我的服务器中逐字使用(除了用 ESMTP 替换对 SMTP 的引用)......但这是我重新工作后半部分的方式主要我现在很迷茫/无能为力...:|
-
实际上@Jean-PaulCalderone 我认为我错了-而不是更新主要功能...我认为 ConsoleSMTPFactory 类需要包含我的 ESMTP / 证书支持?我想我需要更新 protocol=smtp.ESMTP 行以指定 contextFactory,按照我上面的代码传递我的 sslCtxFactory....但是当我尝试添加代码以在“protocol=ESMTP”上方创建 sslCtxFactory 时,并修改该行以指定 contextFactory,服务器运行,但是当客户端连接时,我得到“exceptions.AttributeError: ESMTP instance has no call method”??