Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Addng attachment to an EmailMessage raises TypeError: set_text_content() got an unexpected keyword argument 'maintype'

Following the examples in the Python email examples it seems it should be pretty straight forward to add an attachment. However, the following does not work:

import smtplib
from email.message import EmailMessage
import json

# Initialize message.
msg = EmailMessage()
msg['Subject'] = 'Testing, testing 1-2-3'
msg['To'] = '[email protected]'
msg['From'] = '[email protected]'
msg.set_content('Trying to attach a .json file')

# Create json attachment.
attachment = json.dumps({'This': 'is json'})

# Attempt to attach. This raises an exception.
msg.add_attachment(attachment, maintype='application', subtype='json', filename='test.json')

Here's the exception:

Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/local/lib/python3.7/email/message.py", line 1147, in add_attachment
    self._add_multipart('mixed', *args, _disp='attachment', **kw)
  File "/usr/local/lib/python3.7/email/message.py", line 1135, in _add_multipart
    part.set_content(*args, **kw)
  File "/usr/local/lib/python3.7/email/message.py", line 1162, in set_content
    super().set_content(*args, **kw)
  File "/usr/local/lib/python3.7/email/message.py", line 1092, in set_content
    content_manager.set_content(self, *args, **kw)
  File "/usr/local/lib/python3.7/email/contentmanager.py", line 37, in set_content
    handler(msg, obj, *args, **kw)
TypeError: set_text_content() got an unexpected keyword argument 'maintype'

Note that this very closely follows the third example here, yet fails. Any idea how I can attach a json file?

Also note this answer proposes a similar workflow, but calls the same function with the same arguments, and thus doesn't address my issue.

like image 297
blthayer Avatar asked Jun 21 '19 23:06

blthayer


1 Answers

EmailMessage.set_content delegates to a ContentManager, either one passed as a parameter or the default raw_data_manager.

raw_data_manager.set_content accepts a maintype argument if the content is bytes, but not if the content is str.

So the solution is to pass a bytes instance to EmailMessage.set_content:

# Create json attachment.
attachment = json.dumps({'This': 'is json'})

# Encode to bytes
bs = attachment.encode('utf-8')

# Attach
msg.add_attachment(bs, maintype='application', subtype='json', filename='test.json')
like image 81
snakecharmerb Avatar answered Oct 12 '22 15:10

snakecharmerb