Python和Twisted:使用message-id制作utf-8 html邮件

时间:2012-10-18 17:51:24

标签: python smtp twisted

我正在尝试使用Twisted向Gmail发送电子邮件,但遇到一些奇怪的问题。

首先,this方法适用于简单的纯文本消息。但是当我尝试将此代码段与来自this article的cStringIO数据一起使用时,我收到了没有标题的空消息和我的电子邮件作为收件人。

现在,我想,我忘记了一些简单的事情,但我什么也没有,试图今天找到答案。所以,问题的最终来源是:

from twisted.internet import defer
from twisted.mail import smtp, relaymanager
from twisted.internet import reactor
from cStringIO import StringIO

from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.header import Header
from email import Charset
from email.generator import Generator
from email.Utils import make_msgid

MXCALCULATOR = relaymanager.MXCalculator()

def getMailExchange(host):
    def cbMX(mxRecord):
        return str(mxRecord.name)
    return MXCALCULATOR.getMX(host).addCallback(cbMX)

def sendEmail(mailFrom, mailTo, msg, subject=""):
    def dosend(host):
        print "emailing %s (using host %s) from %s" % (mailTo, host, mailFrom)

        html = u'<html><body>You\'re registered. Now you should use site.</body></html>'
        text = u'You\'re registered. Now you should use site.'

        # Override python's weird assumption that utf-8 text should be encoded with
        # base64, and instead use quoted-printable (for both subject and body).  I
        # can't figure out a way to specify QP (quoted-printable) instead of base64 in
        # a way that doesn't modify global state. :-(
        Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8')

        # This example is of an email with text and html alternatives.
        multipart = MIMEMultipart('alternative')

        # We need to use Header objects here instead of just assigning the strings in
        # order to get our headers properly encoded (with QP).
        # You may want to avoid this if your headers are already ASCII, just so people
        # can read the raw message without getting a headache.
        multipart['Subject'] = Header(subject.encode('utf-8'), 'UTF-8').encode()
        multipart['To'] = Header(mailTo.encode('utf-8'), 'UTF-8').encode()
        multipart['From'] = Header(mailFrom.encode('utf-8'), 'UTF-8').encode()
        multipart['Message-Id'] = Header(make_msgid('e_shop').encode('utf-8'), 'UTF-8').encode()

        # Attach the parts with the given encodings.
        htmlpart = MIMEText(html.encode('utf-8'), 'html', 'UTF-8')
        multipart.attach(htmlpart)
        textpart = MIMEText(text.encode('utf-8'), 'plain', 'UTF-8')
        multipart.attach(textpart)

        # And here we have to instantiate a Generator object to convert the multipart
        # object to a string (can't use multipart.as_string, because that escapes
        # "From" lines).

        io = StringIO()
        g = Generator(io, False) # second argument means "should I mangle From?"
        g.flatten(multipart)

        d = defer.Deferred()
        factory = smtp.ESMTPSenderFactory(None, None, mailFrom, mailTo, io, d,
                                          requireAuthentication=False,
                                          requireTransportSecurity=False)
        reactor.connectTCP(host, 25, factory)
        return d
    return getMailExchange(mailTo.split("@")[1]).addCallback(dosend)

d = sendEmail('admin@mysite.me', 'myemail@gmail.com', 'template filename', 'this is a test subject')
d.addCallback(lambda _: reactor.stop())

reactor.run()

我应该改变什么来使其有效?

1 个答案:

答案 0 :(得分:2)

以下是为我工作(减去子)这是一个多部分的消息 - 也许你可以得到消息ID:

fn = "example.mp3"
multipart = MIMEMultipart('alternative')
multipart['Subject'] = 'Tutorate!'
multipart['To'] = 'Selfie'
multipart['From'] = 'Selfie'

text = "Hello, how are you, goodbye."
textpart = MIMEText(text)
multipart.attach(textpart)
htmlpart = MIMEText("<html>" + text + "</html>", 'html')
multipart.attach(htmlpart)

part = MIMEBase('audio', "mp3")
part.set_payload( open(fn,"rb").read() )
Encoders.encode_base64(part)
part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(fn))
multipart.attach(part)

io = StringIO.StringIO()
g = Generator(io, False)  # second argument means "should I mangle From?"
g.flatten(multipart)
v = io.getvalue()

class SMTPTutorialClient(smtp.ESMTPClient):
    mailFrom = "selfie@~"
    mailTo = "selfie@~"
    def getMailFrom(self):
        result = self.mailFrom
        self.mailFrom = None
        return result

    def getMailTo(self):
        return [self.mailTo]

    def getMailData(self):
        #print v
        return StringIO.StringIO(v)

    def sentMail(self, code, resp, numOk, addresses, log):
        print 'Sent', numOk, 'messages'

        from twisted.internet import reactor
        reactor.stop()