Django发送含媒体文件图片的HTML邮件失败问题求助
Django发送HTML邮件本地媒体图片无法加载的解决方法(部署在Pythonanywhere)
问题背景
使用Python-Django发送正文包含图片的HTML邮件时,互联网图片链接能正常显示,但本地媒体文件中的图片无法被收件方加载。应用部署在Pythonanywhere平台,现有测试代码及模板如下:
测试函数代码
def send_html_email(subject, from_email, to_email, html_content): # Create the email message email = EmailMultiAlternatives(subject, strip_tags(html_content), from_email, to_email) email.attach_alternative(html_content, "text/html") # Send the email email.send() def send_email_with_picture(request): subject = "Example HTML Email" from_email = "sender email" to_email = ["<recipient email>"] # Retrieve the picture URL from your database email_instance = Emails.objects.get(subject="Test sending email with picture") picture_url = default_storage.url(email_instance.product1_image.name) # Retrieve the current domain current_site = get_current_site(request) domain = current_site.domain # Construct the complete absolute URL of the image picture_url = f"http://{domain}{picture_url}" # Render the HTML content with the absolute image URL html_content = render_to_string('email_templates/email_template.html', {'picture_data':picture_url }) # Send the email send_html_email(subject, from_email, to_email, html_content)
邮件模板代码
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Email Template</title> </head> <body> <h1>Welcome to our newsletter!</h1> <p>Here is a picture for you: {{ picture_data }} ## </p> <!-- Render the image directly from the picture_data --> <img src="{{ picture_data.url }}" alt="Picture"> <!-- Additional content for your email --> </body> </html>
问题原因分析
- 模板引用错误:模板中使用
{{ picture_data.url }},但picture_data已经是拼接好的完整绝对URL(如http://xxx.pythonanywhere.com/media/xxx.jpg),.url后缀会导致生成的图片地址无效。 - Pythonanywhere媒体文件访问配置缺失:默认情况下,Pythonanywhere不会自动对外暴露媒体目录,需手动配置静态文件映射才能让外部访问到媒体文件。
- 邮件客户端外部图片屏蔽:多数邮件客户端默认屏蔽外部加载的图片,即使URL正确也可能无法显示。
解决步骤
1. 修正模板中的图片引用
将模板里的图片标签修改为直接使用picture_data:
<img src="{{ picture_data }}" alt="Picture">
2. 配置Pythonanywhere媒体文件对外访问
登录Pythonanywhere后台,进入对应Web应用的设置页面:
- 找到Static files板块
- 添加新映射:
- URL:填写
/media/ - Directory:填写Django项目中
MEDIA_ROOT对应的绝对路径,例如/home/your_username/your_project_name/media/
- URL:填写
- 保存设置,等待配置生效。
3. 可选:将图片嵌入邮件(彻底解决客户端屏蔽问题)
如果希望图片直接在邮件中显示,不依赖外部链接,可以将图片作为附件嵌入,通过CID(Content-ID)关联:
修改发送函数
from django.core.mail import EmailMultiAlternatives from django.template.loader import render_to_string from django.utils.html import strip_tags from django.core.files.storage import default_storage def send_html_email(subject, from_email, to_email, html_content, image_info=None): email = EmailMultiAlternatives(subject, strip_tags(html_content), from_email, to_email) email.attach_alternative(html_content, "text/html") # 嵌入图片附件 if image_info: image_path, image_cid = image_info with default_storage.open(image_path, 'rb') as img_file: # 根据图片类型调整MIME类型,比如image/png、image/gif等 email.attach(image_path.split('/')[-1], img_file.read(), 'image/jpeg') email.mixed_subtype = 'related' # 确保HTML和附件关联 email.send() def send_email_with_picture(request): subject = "Example HTML Email" from_email = "sender email" to_email = ["recipient email"] email_instance = Emails.objects.get(subject="Test sending email with picture") image_path = email_instance.product1_image.name image_cid = "product_image_1" # 自定义唯一CID html_content = render_to_string('email_templates/email_template.html', { 'image_cid': image_cid }) send_html_email(subject, from_email, to_email, html_content, (image_path, image_cid))
修改邮件模板
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Email Template</title> </head> <body> <h1>Welcome to our newsletter!</h1> <img src="cid:{{ image_cid }}" alt="Product Picture"> </body> </html>
内容的提问来源于stack exchange,提问作者Giosroom
相关产品推荐
相关产品推荐

