110

I am successfully able to send email using the smtplib module. But when the emial is sent, it does not include the subject in the email sent.

import smtplib

SERVER = <localhost>

FROM = <from-address>
TO = [<to-addres>]

SUBJECT = "Hello!"

message = "Test"

TEXT = "This message was sent with Python's smtplib."
server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()

How should I write "server.sendmail" to include the SUBJECT as well in the email sent.

If I use, server.sendmail(FROM, TO, message, SUBJECT), it gives error about "smtplib.SMTPSenderRefused"

mugabits
  • 1,015
  • 1
  • 12
  • 22
nsh
  • 1,499
  • 6
  • 13
  • 14

9 Answers9

211

Attach it as a header:

message = 'Subject: {}\n\n{}'.format(SUBJECT, TEXT)

and then:

server = smtplib.SMTP(SERVER)
server.sendmail(FROM, TO, message)
server.quit()

Also consider using standard Python module email - it will help you a lot while composing emails. Using it would look like this:

from email.message import EmailMessage

msg = EmailMessage()
msg['Subject'] = SUBJECT
msg['From'] = FROM
msg['To'] = TO
msg.set_content(TEXT)

server.send_message(msg)
Arturo Mendes
  • 490
  • 1
  • 6
  • 11
Roman Bodnarchuk
  • 29,461
  • 12
  • 59
  • 75
  • 4
    in 2021, this adds the subject into the body of the message unfortunately. – Theo F Jul 02 '21 at 14:39
  • 1
    @TheoF No, it does not. The example constructs a small and trivial but perfectly valid RFC5322 message, still in 2021. But as the answer suggests, you _really really_ want to use the `email` module to construct the input message if it's at all less trivial than this. – tripleee Sep 01 '21 at 07:42
  • I have a question tho, why two linebreaks, why won't three work, with three I get no subject at all, why does it have to be two, I can't find any documentation on this anywhere as the main docs use the email module – public static void Main Oct 13 '22 at 18:32
  • @publicstaticvoidMain As repeated multiple times already, don't do that. Three newlines should work fine _per se_ but adds a silly empty line to the top of the body of the message. But you really want to use the `email` library, or **really** understand email and MIME before you start assembling messages yourself. – tripleee Feb 02 '23 at 17:03
45

This will work with Gmail and Python 3.6+ using the new "EmailMessage" object:

import smtplib
from email.message import EmailMessage

msg = EmailMessage()
msg.set_content('This is my message')

msg['Subject'] = 'Subject'
msg['From'] = "me@gmail.com"
msg['To'] = "you@gmail.com"

# Send the message via our own SMTP server.
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.login("me@gmail.com", "password")
server.send_message(msg)
server.quit()
emehex
  • 9,874
  • 10
  • 54
  • 100
  • 3
    This is the best answer for Python 3.6+. Thanks! – prrao Dec 21 '20 at 22:06
  • 1
    The port number and the authentication details depend on which server you are connecting to. Common variations include using port 587 (or, for internal servers, 25, without SSL) and/or doing `ehlo` before - or even twice, before and after - `login`. – tripleee Sep 01 '21 at 07:56
  • Works for Outlook too! Also if your server doesn't require SSL, you can use this instead: smtplib.SMTP('smtp.outlook.com', 365, timeout=5) – Prithu Srinivas Jul 13 '22 at 04:35
19

try this:

import smtplib
from email.mime.multipart import MIMEMultipart
msg = MIMEMultipart()
msg['From'] = 'sender_address'
msg['To'] = 'reciver_address'
msg['Subject'] = 'your_subject'
server = smtplib.SMTP('localhost')
server.sendmail('from_addr','to_addr',msg.as_string())
Hackaholic
  • 19,069
  • 5
  • 54
  • 72
  • 7
    What about the body of the message? Where does that go? – Dss Jan 21 '15 at 15:50
  • 3
    I ended up following this to put in the body https://docs.python.org/2/library/email-examples.html#id5 – Nico Oct 10 '16 at 19:39
  • 1
    In the current python version, this functionality is now managed by email.message.MailMessage. – chiffa Jun 24 '20 at 12:52
  • This is now obsolescent, and should not be used for new code. Prior to Python 3.6, this was what you had to use (except then too you would have wanted your message to also have a body). – tripleee Sep 01 '21 at 07:47
7

You should probably modify your code to something like this:

from smtplib import SMTP as smtp
from email.mime.text import MIMEText as text

s = smtp(server)

s.login(<mail-user>, <mail-pass>)

m = text(message)

m['Subject'] = 'Hello!'
m['From'] = <from-address>
m['To'] = <to-address>

s.sendmail(<from-address>, <to-address>, m.as_string())

Obviously, the <> variables need to be actual string values, or valid variables, I just filled them in as place holders. This works for me when sending messages with subjects.

g.d.d.c
  • 46,865
  • 9
  • 101
  • 111
  • I am getting the following error: from email.mime.text import MIMEText as text ImportError: No module named mime.text – nsh Aug 29 '11 at 16:38
  • @nsh - with what version of Python? I'm using 2.6.6 on this particular install. It's entirely possible that it's in a slightly different place in 3.x. – g.d.d.c Aug 29 '11 at 17:00
  • The `email` library was overhauled in 3.6 and is now quite a bit more versatile and logical. Probably review the current [examples from the `email` documentation.](https://docs.python.org/3/library/email.examples.html) – tripleee Sep 01 '21 at 07:49
6
import smtplib
 
# creates SMTP session 

List item

s = smtplib.SMTP('smtp.gmail.com', 587)
 
# start TLS for security   
s.starttls()
 
# Authentication  
s.login("login mail ID", "password")
 
 
# message to be sent   
SUBJECT = "Subject"   
TEXT = "Message body"
 
message = 'Subject: {}\n\n{}'.format(SUBJECT, TEXT)
 
# sending the mail    
s.sendmail("from", "to", message)
 
# terminating the session    
s.quit()
Flair
  • 2,609
  • 1
  • 29
  • 41
King_Avi
  • 77
  • 1
  • 2
5

See the note at the bottom of smtplib's documentation:

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.

Here's the link to the examples section of email's documentation, which indeed shows the creation of a message with a subject line. https://docs.python.org/3/library/email.examples.html

It appears that smtplib doesn't support subject addition directly and expects the msg to already be formatted with a subject, etc. That's where the email module comes in.

dmmfll
  • 2,666
  • 2
  • 35
  • 41
jeffcook2150
  • 4,028
  • 4
  • 39
  • 51
  • Like the accepted answer demonstrates, you can construct a valid RFC5322 message from simple strings if you know what you are doing, or are following an example exactly. For anything more than that, this is the way to go. – tripleee Sep 01 '21 at 07:44
4

I think you have to include it in the message:

import smtplib

message = """From: From Person <from@fromdomain.com>
To: To Person <to@todomain.com>
MIME-Version: 1.0
Content-type: text/html
Subject: SMTP HTML e-mail test

This is an e-mail message to be sent in HTML format

<b>This is HTML message.</b>
<h1>This is headline.</h1>
"""

try:
   smtpObj = smtplib.SMTP('localhost')
   smtpObj.sendmail(sender, receivers, message)         
   print "Successfully sent email"
except SMTPException:
   print "Error: unable to send email"

code from: http://www.tutorialspoint.com/python/python_sending_email.htm

Martin
  • 5,954
  • 5
  • 30
  • 46
  • One observation: from, to and subject fields, for example, must be at the VERY BEGINNING of the variable "message", for example, or else, the fields will not be interpreted as it must be expected. I had the experience with just inserting "Subject" field, not at the beginning of the variable, and the message came to the receiver's mailbox with no subject. Cheers. – ivanleoncz Jan 17 '17 at 23:04
  • can you please add, "sender" and "receivers" variables in your code. they are being passed into smtpObj.sendmail(), but aren't initialized. – Uday Kiran Apr 11 '22 at 15:40
0

In case of wrapping it in a function, this should work as a template.

def send_email(login, password, destinations, subject, message):
    server = smtplib.SMTP_SSL("smtp.gmail.com", 465)

    server.login(login, password)
    message = 'Subject: {}\n\n{}'.format(subject, message)

    for destination in destinations:
        print("Sending email to:", destination)
        server.sendmail(login, destinations, message)

    server.quit()
Flair
  • 2,609
  • 1
  • 29
  • 41
0

try this out :

from = "myemail@site.com"
to= "someemail@site.com"

subject = "Hello there!"
body = "Have a good day."

message = "Subject:" + subject + "\n" + body


server.sendmail(from, , message)
server.quit()
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 22 '22 at 03:35