Reputation: 5793
I'm trying to attach a media file saved in an S3 bucket to an email, which I'm doing with this line of code:
email.attach_file(standard.download.url)
The model is defined as follows:
class Standard(models.Model):
name = models.CharField(max_length = 51)
download = models.FileField(upload_to="standard_downloads/", null=True, blank=True)
def __str__(self):
return self.name
Within settings.py
I have defined my media files as follows:
AWS_DEFAULT_ACL = 'public-read'
AWS_S3_CUSTOM_DOMAIN = '%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}
DEFAULT_FILE_STORAGE = 'sme.storage_backends.MediaStorage'
MEDIA_ROOT = 'https://%s.s3.amazonaws.com/media/' % AWS_STORAGE_BUCKET_NAME
When trying to run the code I'm getting
No such file or directory: 'https:/bucket-name.s3.amazonaws.com/media/standard_downloads/filename.ext
Please note it is showing as https:/
(a single /). How do I correct this?
Upvotes: 5
Views: 2330
Reputation: 544
A better way to do this would be to leverage default_storage
which will work whether you are using local file storage, S3 or any other storage backend.
from django.core.files.storage import default_storage
msg = EmailMessage(
subject="Your subject",
body="Your Message",
from_email="[email protected]",
to=["[email protected]"],
)
filename = "standard_downloads/filename.ext"
with default_storage.open(filename, "r") as fh:
msg.attach(filename, fh.read())
msg.send()
Upvotes: 1
Reputation: 9521
Here's the source code of attach_file
from Django. It clearly says - to attach file from the filesystem. It does not work with remote urls. And when you give it a url it thinks you are referring to local file, so it escapes all double slashes to single slashes.
def attach_file(self, path, mimetype=None):
"""
Attach a file from the filesystem.
Set the mimetype to DEFAULT_ATTACHMENT_MIME_TYPE if it isn't specified
and cannot be guessed.
For a text/* mimetype (guessed or specified), decode the file's content
as UTF-8. If that fails, set the mimetype to
DEFAULT_ATTACHMENT_MIME_TYPE and don't decode the content.
"""
path = Path(path)
with path.open('rb') as file:
content = file.read()
self.attach(path.name, content, mimetype)
Django does not provide anything built-in for that. You will have to write something custom on the lines of above code also using libraries like request
or boto
. Basically the idea is to fetch from remote url save as temp and then use attach
on that.
Here's one example on how you could get the file on the fly:
from django.core.mail.message import attach
import requests
response = requests.get("http://yoururl/somefile.pdf")
email.attach('My file',response.read(),mimetype="application/pdf")
Upvotes: 7