使用Twisted SMTP服务器时,如果为电子邮件指定了多个收件人地址,收件者列表里只会显示最后一个收件人的地址。同时,用户还希望能够访问完整的SMTP报头,包括消息ID等信息。此外,用户还希望创建一个文件(可能分为2个部分,分别保存报头和正文),并根据消息ID对文件进行命名。
- 解决方案
- 为了解决收件者列表只显示最后一个收件人的地址的问题,需要修改receivedHeader方法,将所有收件人地址都添加到recipients列表中,并对recipients列表进行遍历,将每个收件人地址都添加到receivedHeader方法的返回语句中。
- 为了访问完整的SMTP报头,可以重写validateTo方法,该方法返回一个工厂函数,该工厂函数返回一个实现了IMessage接口的消息对象。在IMessage接口中,有一个lineReceived方法,当接收到每行SMTP报头时,该方法都会被调用。在lineReceived方法中,可以将每行SMTP报头添加到一个列表中,并保存在消息对象中。
- 为了将文件分成两个部分,分别保存报头和正文,可以修改IMessage接口,使其包含两个方法:getHeader()和getBody()。在lineReceived方法中,可以将每行SMTP报头添加到getHeader()方法返回的列表中,将正文添加到getBody()方法返回的列表中。
- 为了根据消息ID对文件命名,可以修改ConsoleMessage类,使其包含一个getMessageId()方法,该方法返回消息ID。然后,就可以在创建文件时,使用getMessageId()方法获取消息ID,并将其作为文件名的一部分。
以下是一些代码示例:
class ConsoleMessageDelivery:
def receivedHeader(self, helo, origin, recipients):
by = helo[1]
from_ = origin
recipients = ' '.join(map(str, recipients))
return "Client: %s\nFrom: %s\nTo: %s\n\n" % (by, from_, recipients)
def validateTo(self, user):
def messageFactory():
# 定义消息对象
message = ConsoleMessage()
# 当收到每行SMTP报头时,将其添加到列表中
message.lines = []
def lineReceived(line):
message.lines.append(line)
return message
return messageFactory
class ConsoleMessage:
def eomReceived(self):
# 打印收到的SMTP报头和正文
print("New message received:")
print("\n".join(self.lines))
# 将SMTP报头和正文分成两个文件
headerFile = open("./header.txt", "w")
bodyFile = open("./body.txt", "w")
headerFile.writelines(self.getHeader())
bodyFile.writelines(self.getBody())
headerFile.close()
bodyFile.close()
# 清空列表
self.lines = None
return defer.succeed(None)
def getMessageId(self):
# 获取消息ID
for line in self.lines:
if line.startswith("Message-ID:"):
return line.split(":")[1].strip()
return None
def getHeader(self):
# 获取SMTP报头
return self.lines[:self.lines.index("\n\n")]
def getBody(self):
# 获取正文
return self.lines[self.lines.index("\n\n") + 1:]
通过这些修改,用户就可以在Twisted SMTP服务器中获取完整的收件人列表和报头数据,并可以将文件分成两个部分,分别保存报头和正文,还可以根据消息ID对文件命名。