Reputation: 6319
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
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