【问题标题】:Twisted Python - access SMTPFactory attribute from ApplicationTwisted Python - 从应用程序访问 SMTPFactory 属性
【发布时间】:2014-12-19 04:44:01
【问题描述】:

这一次,我提出了一个简单直接的问题!有人可以建议我如何从 ConsoleMessage 类中访问下面的 ConsoleSmtpFactory 代码中的“p.startedTLS”吗?

我希望能够转储到文件,作为消息的一部分,无论它是通过 TLS 传递...

换一种说法——在 Twisted 中,你的应用程序代码可以访问协议属性吗? (我想这就是我想问的?!?

我什至尝试过使用全局变量(让我们暂时忽略编码标准问题!)...不高兴。下面我的 CustomSmtpFactory 中的“buildProtocol”在 p.StartedTLS 设置为 true 之前被调用 - 我想事后看来很明显 - 它构建工厂,并在收到来自客户。

所以我想我的问题更准确的是 - 在协议构建之后如何访问协议属性?

谢谢!

class ConsoleMessageDelivery:
    implements(custom_esmtp.IMessageDelivery)

    def receivedHeader(self, helo, origin, recipients):
        by = helo[1]
        from_ = origin
        target = ""
        for u in recipients:
           target = target + u.__str__() + "\n"
        """ 
        Want to add something here like:
        tls=protcol.startTLS 
        then add "tls" to the returned string below
        """
        return "Client: %s\nFrom: %s\nTo: %s\n\n" % (by, from_, target)

    def validateFrom(self, helo, origin):
        return origin

    def validateTo(self, user):
        return lambda: ConsoleMessage()
        #return None


class ConsoleMessage:
    implements(custom_esmtp.IMessage)

    def __init__(self):
        self.lines = []

    def lineReceived(self, line):
        self.lines.append(line)

    def dumpMsgToFile(self, msgData):
        inx = 0
        filePrefix = datetime.datetime.utcnow().strftime("%Y%m%d%H%M%S%f")
        while os.path.exists(filePrefix + "-" + str(inx)):
           inx = inx + 1
        fileName = filePrefix + "-" + str(inx)
        msgFile = open("./" + fileName,"a")
        msgFile.writelines(msgData)
        msgFile.write ("\n----------------------\n")
        msgFile.close()

    def eomReceived(self):
        print "\n".join(self.lines)
        self.dumpMsgToFile(self.lines)
        self.lines = None
        return defer.succeed(None)

    def connectionLost(self):
        # There was an error, throw away the stored lines
        self.lines = None


class ConsoleSMTPFactory(custom_esmtp.SMTPFactory):
    protocol = custom_esmtp.mySMTP

    def __init__(self, *a, **kw):
        custom_esmtp.SMTPFactory.__init__(self, *a, **kw)
        self.delivery = ConsoleMessageDelivery()

    def buildProtocol(self, addr):
        try:
           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()
        except IOError as e:
           print "Failed in reading files({0}): {1}".format(e.strerrror)
        except:
           print "Unknown error"

        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)
        p = custom_esmtp.SMTPFactory.buildProtocol(self, addr)
        p.delivery = self.delivery
       # p.challengers = {"LOGIN": LOGINCredentials, "PLAIN": PLAINCredentials}
        p.ctx=sslCtxFactory
        print (p.startedTLS) # << returns true / false depending on if switched to TLS
        return p


class SimpleRealm:
    implements(IRealm)

    def requestAvatar(self, avatarId, mind, *interfaces):
        if smtp.IMessageDelivery in interfaces:
            return smtp.IMessageDelivery, ConsoleMessageDelivery(), lambda: None
        raise NotImplementedError()


def main():
    from twisted.application import internet
    from twisted.application import service

    portal = Portal(SimpleRealm())
    checker = InMemoryUsernamePasswordDatabaseDontUse()
    checker.addUser("guest", "password")
    portal.registerChecker(checker)

    a = service.Application("Console SMTP Server")
    internet.TCPServer(5000, ConsoleSMTPFactory(portal)).setServiceParent(a)

    return a

application = main()

【问题讨论】:

    标签: python attributes smtp protocols twisted


    【解决方案1】:

    这可能是 SMTP 实现中缺少的功能。我认为origin 是一个字符串形式的IP 地址。它可能应该是一个功能更全面的地址对象,不仅代表客户端的对等地址,还代表用于与客户端通信的传输。

    或者,这可能是 SMTP 协议实现与门户(或交付对象或交付工厂对象)交互方式的更普遍的失败。也许它应该从一开始就公开更多信息(而不是在调用receivedHeader 之前保留它的解决方案)。

    无论如何,基本答案是这是一个不受支持的功能(它会在 Twisted 问题跟踪器中提出很好的功能请求)。您可以通过在 ESMTP 子类(阅读基本实现)上覆盖 receivedHeader 来为交付对象提供必要的额外信息,从而找到一种方法来破解您想要的功能。

    【讨论】:

    • 谢谢@Jean-PaulCalderone - 可惜这是一个缺失的功能,但我想我可以自豪的是,自从我发布扭曲的问题以来,我第一次问了一个相当不错的问题;) 当我周一回来工作时,我会添加请求,并破解 ESMTP :) 再次感谢 :)
    • 实际上@Jean-PaulCalderone - 如果我们想从收到的消息中获取完整的 SMTP 标头 - 我猜这将是有效的相同功能请求?或者这已经可以用我现有的代码完成(以我错过的方式)?谢谢! (((不试图在评论中提出不同的问题 - 只是试图“完善”答案!)
    • (扭曲的票 #7695 提出)
    猜你喜欢
    • 1970-01-01
    • 2020-08-22
    • 2014-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多