handle
handle

Reputation: 6319

Setting email content from string in email.message?

I'd like to send an email using Python.

There's sendmail (Sending mail via sendmail from python), but also https://docs.python.org/3/library/smtplib.html. It recommends constructing a message based on https://docs.python.org/3/library/email.message.html and has a few examples https://docs.python.org/3/library/email.examples.html#email-examples which reads the message content from file:

# Open the plain text file whose name is in textfile for reading.
with open(textfile) as fp:
    # Create a text/plain message
    msg = EmailMessage()
    msg.set_content(fp.read())

I've tried

msg.set_content(b"test message sent locally")

but that results in TypeError: set_bytes_content() missing 2 required positional arguments: 'maintype' and 'subtype'. It seems https://docs.python.org/3/library/email.message.html#email.message.EmailMessage.set_content requires a context manager?

How can a string be used to construct the message body?

Upvotes: 3

Views: 6920

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148910

The error message is correct yet misleading. The default content manager (context manager is a different animal...) provides this set_content method (emphasize mine):

email.contentmanager.set_content(msg, <'str'>, subtype="plain", charset='utf-8' cte=None, disposition=None, filename=None, cid=None, params=None, headers=None) 
email.contentmanager.set_content(msg, <'bytes'>, maintype, subtype, cte="base64", disposition=None, filename=None, cid=None, params=None, headers=None) 
email.contentmanager.set_content(msg, <'EmailMessage'>, cte=None, disposition=None, filename=None, cid=None, params=None, headers=None) 
email.contentmanager.set_content(msg, <'list'>, subtype='mixed', disposition=None, filename=None, cid=None, params=None, headers=None) 

Add headers and payload to msg:

Add a Content-Type header with a maintype/subtype value.

For str, set the MIME maintype to text, and set the subtype to subtype if it is specified, or plain if it is not.

For bytes, use the specified maintype and subtype, or raise a TypeError if they are not specified.

...

Long story make short, if you want to send a simple text message, pass a plain (unicode) string to set_content:

msg.set_content("test message sent locally")    # pass a str string and not a byte string

Upvotes: 6

Related Questions