smtplib sends blank message if the message contain certain characters

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: <[email protected]>
Received: **REDACTED**
        Fri, 03 Aug 2012 06:56:20 -0700 (PDT)
Message-ID: <[email protected]>
Date: Fri, 03 Aug 2012 06:56:20 -0700 (PDT)
From: [email protected]
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: [email protected]
     ... Subject: testin'...
     ...
     ... This is a test '''
     >>> s.sendmail("[email protected]", tolist, msg)

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


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 plain text English-language 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. See the Python email examples documentation for some quick examples.