smtplib sends blank message if the message contain certain characters

拥有回忆 提交于 2019-11-27 05:34:54

The problem is that smtplib is not putting a blank line between the message header and the message body as shown by in the "Show Original" form of my test:

Return-Path: <me@gmail.com>
Received: **REDACTED**
        Fri, 03 Aug 2012 06:56:20 -0700 (PDT)
Message-ID: <501bd884.850c320b@mx.google.com>
Date: Fri, 03 Aug 2012 06:56:20 -0700 (PDT)
From: me@gmail.com
http: //www.example.com

Although this is a legal mail header, Mail Transfer Agents and Mail User Agents should ignore apparent header fields they don't understand. And because the RFC822 header continues until the first blank line and http: looks like a header line, it is parsed as if it were a header. If given a newline:

mensaje = '\nhttp://www.example.com'

Then it works as expected. Although email technically only needs the "envelope" as provided by smtplib the contents of the mail should be more complete if you expect your recipients (and their mailers) to treat the message nicely, you should probably use the email module to generate the body.

added

Based on the doctest in smtplib.py it looks as if this is an intentional feature allowing the caller of sendmail() to append to the header:

     >>> msg = '''\\
     ... From: Me@my.org
     ... Subject: testin'...
     ...
     ... This is a test '''
     >>> s.sendmail("me@my.org", tolist, msg)

Where the From: and Subject: lines are part of the "nice" headers I mentioned above.

I don't think it is about the colon but it's about http:// starting the message.

mailto('test@gmail.com', 'http://www.url.com')
mailto('test@gmail.com', 'http://www.url.com that is a url')
mailto('test@gmail.com', ' http://www.url.com')

all fail, but:

mailto('test@gmail.com', 'Here is a url http://www.url.com')

comes through fine.

The proper solution is to use the Python email library to create a valid message, instead of painstakingly learning (or wildly guessing at random) how to construct a valid MIME message structure by joining together pieces of text.

A trivial RFC822 message which contains only ASCII can easily be created with

'From: {0}\nTo: {1}\nSubject: {2}\n\n{3}'.format(
    fromaddr, toaddr,
    'Hello, I am the exiled prince of Ubandingba',
    'http://clickme.example.net/scam/')

but as soon as you need anything with other character sets, lines longer than some 80 characters, content types other than plain text, or in general anything more advanced than email as it was in 1990, the code should look something like

from email.message import EmailMessage

msg = EmailMessage()
msg['from'] = fromaddr
msg['to'] = toaddr
msg['subject'] = 'You have been nominated for the Nobel prize'
msg.set_content('http://scam.example.org/clickme')

which is admittedly slightly more verbose, but also infinitely more versatile, robust, and extensible.

This uses the EmailMessage API which was officially introduced in Python 3.6. New code should probably target this platform rather than the legacy email.Message module from earlier versions, although most online code examples you can find will be for the older Python library.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!