Question

I'm trying to send a text message using Gmail and the smtplib module in Python.

The basic functionality is implemented, and using the following code, I'm perfectly able to receive these text messages on my phone:

server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login('email', 'password')
server.sendmail('email', 'recipient', '\nhttp://apple.com') 

Now, it might be of some utility to mention I am sending a link. One might wonder why I inserted the \n in front of the the example link; apparently, without it, smtplib processes the link as a header and it therefore sends an empty message.

However, a newline is added to my message, like so:

http://apple.com
newline here

I'm unable to understand why this happening:

  • is smtplib adding a newline because the message is a link ?
  • is it because I receive the message as an SMS?
  • is Gmail adding the newline ?
Was it helpful?

Solution

The msg argument to sendmail is not the message body, but the entire message. So, it has to be a valid RFC(2)822 message.

As the note at the end of the documentation says:

In general, you will want to use the email package’s features to construct an email message, which you can then convert to a string and send via sendmail(); see email: Examples.

However, the example directly above that shows how to generate a simple message yourself:

# Add the From: and To: headers at the start!
msg = ("From: %s\r\nTo: %s\r\n\r\n"
       % (fromaddr, ", ".join(toaddrs)))

If you want to know what constitutes a valid email message, see RFC 2822 (and possibly RFC 822, which 2822 replaced, but which has some usefully different explanations and examples). But the short version is this: It's a sequence of header lines, each ending in \r\n, followed by a blank line (meaning \r\n\r\n), followed by a message body.

So, technically speaking, your code shouldn't even work, because it just has a \n instead of a \r\n prefix.

More importantly, you're sending a message with no headers at all. Not even the From: and To: that you probably think you're including. As the documentation for sendmail says:

The from_addr and to_addrs parameters are used to construct the message envelope used by the transport agents. The SMTP does not modify the message headers in any way.

This may or may not be considered invalid (or spam) by various servers.

Meanwhile, the extra newline at the end is because all lines must end with a \r\n, and SMTP is a line-oriented protocol. There's simply no way to signal that the message is done if it doesn't end with a newline.

If you want to understand the details, see RFC2821, which explains the SMTP protocol. In particular, look at 2.3.1 Mail Objects, 2.3.7 Lines, and 4.1.1.4 DATA (DATA). But the short version is that sending a message requires a DATA command, which must end with \r\n.\r\n, and "the first of this terminating sequence is also the that ends the final line of the data (message text)". This means there's no way to send a message that doesn't end with a newline.

If you really want to, it's possible to get around this by encapsulating your body in a MIME message; the MIME message itself will of course end with a newline, but that won't affect your encapsulated body. There are a few ways to do this—but you'll need the recipient to be able to handle whatever you send, and I'm guessing none of those ways will work with the email-SMS gateway (much less the SMS-receiving endpoint).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top