captain yossarian
captain yossarian

Reputation: 457

smtplib - sending but with no subject when indented in a while loop

Edited as was unclear earlier.

If I run the below code without it being in a while loop, it runs perfectly. As soon as I put it in a while loop (which I need to as part of a larger script), it for some reason loses the subject of the mail and sends it blank. Everything else is OK - the recipient, sender and body of the e-mail is fine. It just drops the subject for some reason. Any ideas?

import smtplib
import time


while True :
 newnumber = "200"
 oldnumber = "100"
 SERVER = "mail"
 FROM = "mail"
 TO = "mail"
 SUBJECT = "Blah blah blah blah blah"
 BODY = """Blah blah blah blah blah.\n\n
 The new number is: %s\n
 The old number is: %s\n\n
 Blah blah blah blah blah.\n\n
 Blah blah blah blah blah\n
 Blah.""" % (newnumber,oldnumber)

 message = """\
 From: %s
 To: %s
 Subject: %s

 %s
 """ % (FROM, TO, SUBJECT, BODY)

 if oldnumber < newnumber:
        server = smtplib.SMTP(SERVER)
        server.sendmail(FROM, TO, message)
        server.quit()
        time.sleep(60)

Upvotes: 1

Views: 4223

Answers (4)

Dhananjay D. Argade
Dhananjay D. Argade

Reputation: 9

You need to mention the Subject: in the very beginning of your message.

e.g. in your case, your message should be like

message = """Subject: %s
From: %s 
To: %s
%s
""" % (FROM, TO, SUBJECT, BODY)

I also faced the same problem, and it worked for me.

Upvotes: 0

Serge Ballesta
Serge Ballesta

Reputation: 149075

Ok, as I suggested in my above comment, the problem comes from you indentation of message. The headers are no longer at the beginning of their line as required by SMTP protocol and they are probably rejected into the message body. You must write either :

message = "From: %s\nTo: %s\nSubject: %s\n\n%s" % (FROM, TO, SUBJECT, BODY)

or

    message = """\
From: %s
To: %s
Subject: %s

%s\
""" % (FROM, TO, SUBJECT, BODY)

In fact you must ensure that there cannot be any space before From:, To: and Subject:.

You can also test the sent mail with the smtpd module.

python -m smtpd -c DebuggingServer -n localhost:8025

starts a smtp server that listen on port 8025 on localhost and simply display the received messages. If you had use it, you would have seen that the headers was present but that they did not start on first column.

Last remark : you reopen a new connection to the smtp server for each message. You can avoid it by writing :

import smtplib
import time

server = smtplib.SMTP(SERVER)
while True :
    ...
    if oldnumber < newnumber:
        server.sendmail(FROM, TO, message)
        time.sleep(60)

server.quit()

Upvotes: 2

Burhan Khalid
Burhan Khalid

Reputation: 174662

If you are indenting the message block, it might be causing this problem. Consider simplifying your strings a bit:

message = "From: {}\nTo: {}\nSubject: {}\n\n{}"
message.format(FROM, TO, SUBJECT, BODY)

Now you can indent this as far in and out as you like without problems.

Upvotes: 0

Joram
Joram

Reputation: 3246

see python documentation here https://docs.python.org/3.4/library/email-examples.html#email-examples

Here is an example sending multipart message

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText    SERVER = "localhost"

SERVER = "localhost"    
FROM = "me"
TO = "you"
SUBJECT = "Test"
BODY = "Test"

# Create message container - the correct MIME type is multipart/alternative.
msg = MIMEMultipart('alternative')
msg['Subject'] = SUBJECT
msg['From'] = FROM
msg['To'] = TO
# Record the MIME types of both parts - text/plain and text/html.
part1 = MIMEText(BODY, 'text')
# part2 = MIMEText(HTML_BODY, 'html')

# Attach parts into message container.
# According to RFC 2046, the last part of a multipart message, in this case
# the HTML message, is best and preferred.
msg.attach(part1)
# msg.attach(part2)

# Send the message via SMTP server.
s = smtplib.SMTP(SERVER)
# sendmail function takes 3 arguments: sender's address, recipient's address
# and message to send - here it is sent as one string.
failed_addresses = s.sendmail(mailFrom, mailTo, msg.as_string())

Upvotes: 0

Related Questions