如何通过S3 URL在Django Emailer中附加文档且无需下载至服务器
当然可以做到!不用把S3上的文件下载到服务器就能直接附加到Django邮件里,还不会暴露你的S3 URL,我给你详细说下怎么实现:
核心思路
Django的EmailMessage类支持直接将内存中的文件内容作为附件添加,不需要先保存到本地服务器。我们只需要从S3直接读取文件的二进制内容,再传给邮件的attach()方法即可。
具体实现方案
方案一:使用boto3直接操作S3
如果你直接用boto3来访问S3,可以这样写:
首先安装兼容Python2.7的boto3版本(最后支持Python2.7的是1.18.x版本):
pip install boto3==1.18.69
然后编写代码:
import boto3 from django.core.mail import EmailMessage from botocore.exceptions import ClientError def get_s3_file_content(bucket_name, s3_file_key): """从S3读取文件内容和MIME类型""" s3_client = boto3.client('s3') try: response = s3_client.get_object(Bucket=bucket_name, Key=s3_file_key) # 读取文件二进制内容,获取MIME类型 file_content = response['Body'].read() mime_type = response['ContentType'] return file_content, mime_type except ClientError as e: print(f"读取S3文件出错: {e}") return None, None # 发送邮件的逻辑 def send_email_with_s3_attachments(): # 替换成你的S3桶名和文件路径 s3_bucket = "your-s3-bucket-name" pdf_s3_key = "path/to/your/document.pdf" image_s3_key = "path/to/your/image.jpg" # 获取文件内容和MIME类型 pdf_content, pdf_mime = get_s3_file_content(s3_bucket, pdf_s3_key) image_content, image_mime = get_s3_file_content(s3_bucket, image_s3_key) if not (pdf_content and image_content): print("无法获取S3文件内容,终止发送") return # 创建邮件对象 email = EmailMessage( subject="带S3附件的邮件", body="这是包含S3文件附件的测试邮件", from_email="sender@example.com", to=["recipient@example.com"] ) # 添加附件:参数是(显示的文件名, 文件二进制内容, MIME类型) email.attach("report.pdf", pdf_content, pdf_mime) email.attach("header.jpg", image_content, image_mime) # 发送邮件 email.send(fail_silently=False)
方案二:使用django-storages(如果你已经在用这个库)
如果你的Django项目已经配置了django-storages来管理S3存储,代码会更简洁:
from django.core.files.storage import default_storage from django.core.mail import EmailMessage def send_email_with_s3_attachments(): # 替换成你的存储中的文件路径 pdf_file_path = "documents/report.pdf" image_file_path = "images/banner.png" # 从存储中读取文件内容 with default_storage.open(pdf_file_path, 'rb') as pdf_file: pdf_content = pdf_file.read() pdf_mime = default_storage.get_content_type(pdf_file_path) with default_storage.open(image_file_path, 'rb') as image_file: image_content = image_file.read() image_mime = default_storage.get_content_type(image_file_path) # 创建并发送邮件 email = EmailMessage( subject="带S3附件的邮件", body="邮件内容", from_email="sender@example.com", to=["recipient@example.com"] ) email.attach("report.pdf", pdf_content, pdf_mime) email.attach("banner.png", image_content, image_mime) email.send(fail_silently=False)
注意事项
- 确保你的Django环境已经配置好S3访问权限:在
settings.py中设置AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY,或者通过IAM角色赋予服务器访问S3的权限。 - 对于超大文件,直接读取到内存可能会占用过多资源,但邮件服务本身通常会限制附件大小(比如多数服务商限制25MB以内),所以一般场景下没问题。
- Python2.7和Django1.9都支持上述代码,不需要额外升级依赖。
内容的提问来源于stack exchange,提问作者nimeshkiranverma
相关产品推荐
相关产品推荐

