Twisted Python - 从Application访问SMTPFactory属性

时间:2014-10-23 13:36:51

标签: python attributes smtp protocols twisted

一次,一个简单,直截了当的问题!有人可以建议我如何访问" p.startedTLS"在下面的ConsoleSmtpFactory代码中,来自ConsoleMessage类?

我希望能够转发到文件,作为邮件的一部分,是否通过TLS传递...

所以换句话说 - 在Twisted中,您的应用程序代码可以访问协议属性吗? (我认为这就是我想要问的问题?!​​?

我甚至尝试过使用全局变量(让我们暂时忽略编码标准问题!)......没有快乐。 " buildProtocol"我在下面的CustomSmtpFactory中调用p.StartedTLS设置为true - 我认为事后很明显 - 它构建了工厂,并且在收到" STARTTLS"后,在ext_STARTTLS(在ESMTP类中)中设置了startsTLS。来自客户的命令。

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

谢谢!

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()

1 个答案:

答案 0 :(得分:1)

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

或者它可能是SMTP协议实现与门户(或交付对象或交付工厂对象)交互的方式更加普遍的失败。也许它应该暴露更多的信息开始(而不是一个解决方案,它保持这一点,直到,例如,receivedHeader被调用)。

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