I’m stuck trying to send user-uploaded files as attachments using Mailgun and Bottle. The basic message sending works fine, but I’m having trouble with the attachment part.
Here’s what I’ve tried:
files=[('attachment', open(request.files.data.file)),],
But I get this error:
TypeError: invalid file: <_io.BufferedRandom name=19>
My HTML form looks like this:
<form action='/send-file' method='post' enctype='multipart/form-data'>
<input type='email' name='email' required>
<textarea name='description'></textarea>
<input type='file' name='attachment' required>
<button type='submit'>Send</button>
</form>
And my Bottle route:
@route('/send-file', method='POST')
def send_file():
email = request.forms.get('email')
description = request.forms.get('description')
response = requests.post('https://api.mailgun.net/v3/your-domain/messages',
auth=('api', 'your-api-key'),
files=[('attachment', open(request.files.attachment.file))],
data={
'from': 'Your Name <[email protected] >',
'to': '[email protected] ',
'subject': 'File Submission',
'text': f'{email} {description}'
})
return 'File sent successfully' if response.ok else 'Error sending file'
How can I properly attach the user-uploaded file to the Mailgun request? Any help would be great!
I’ve encountered this issue before when working with Bottle and Mailgun. The key is to properly handle the file object that Bottle provides.
Instead of trying to open the file directly, you should use the file object’s ‘file’ attribute, which is already an open file-like object. Here’s how you can modify your code:
@route('/send-file', method='POST')
def send_file():
email = request.forms.get('email')
description = request.forms.get('description')
attachment = request.files.get('attachment')
if attachment:
file_content = attachment.file.read()
file_name = attachment.filename
response = requests.post(
'https://api.mailgun.net/v3/your-domain/messages',
auth=('api', 'your-api-key'),
files=[('attachment', (file_name, file_content))],
data={
'from': 'Your Name <[email protected] >',
'to': '[email protected] ',
'subject': 'File Submission',
'text': f'{email} {description}'
}
)
return 'File sent successfully' if response.ok else 'Error sending file'
else:
return 'No file uploaded'
This approach should resolve your TypeError and allow you to send attachments successfully via Mailgun.
I’ve dealt with this exact issue before, and I can tell you it’s a bit tricky. The problem is that Bottle handles file uploads differently than what Mailgun expects.
Here’s what worked for me:
Instead of trying to open the file directly, you need to access the file’s content through the file attribute of the uploaded file object. Then, create a tuple with the filename, file content, and content type.
Try modifying your route like this:
@route('/send-file', method='POST')
def send_file():
email = request.forms.get('email')
description = request.forms.get('description')
attachment = request.files.get('attachment')
if attachment:
file_content = attachment.file.read()
file_name = attachment.filename
content_type = attachment.content_type
response = requests.post(
'https://api.mailgun.net/v3/your-domain/messages',
auth=('api', 'your-api-key'),
files=[('attachment', (file_name, file_content, content_type))],
data={
'from': 'Your Name <[email protected] >',
'to': '[email protected] ',
'subject': 'File Submission',
'text': f'{email} {description}'
}
)
return 'File sent successfully' if response.ok else f'Error: {response.text}'
else:
return 'No file uploaded'
This approach should resolve the TypeError you were encountering. Just remember to handle potential exceptions and maybe add some file size checks to avoid issues with Mailgun’s limits.
Luna23
April 30, 2025, 5:00pm
4
hey mate, i had similar issue. try this:
@route('/send-file', method='POST')
def send_file():
email = request.forms.get('email')
description = request.forms.get('description')
attachment = request.files.get('attachment')
if attachment:
files = [('attachment', (attachment.filename, attachment.file, attachment.content_type))]
response = requests.post('https://api.mailgun.net/v3/your-domain/messages',
auth=('api', 'your-api-key'),
files=files,
data={
'from': 'Your Name <[email protected] >',
'to': '[email protected] ',
'subject': 'File Submission',
'text': f'{email} {description}'
})
return 'sent ok' if response.ok else 'oops, error'
return 'no file uploaded'
this shud work for ya. good luck!