You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django密码重置邮件CSS未生效,仅显示HTML内容求助

Django密码重置邮件CSS样式不生效的解决办法

我在使用Django的密码重置功能时,自定义了HTML模板来发送格式美观的密码重置邮件,但目前邮件仅能显示HTML内容,CSS样式(如间距、背景色等)完全不生效,无法定位原因。相关代码如下:

现有代码

password_reset_email.html

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Reset Your Password</title>
    <style>
        /* Inline styles for email clients */
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            background-color: #f5f5f5;
            margin: 0;
            padding: 0;
        }
        .password_reset_email {
            max-width: 600px;
            margin: 0 auto;
            padding: 2rem;
            background: white;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
        }
        .password_reset_email-header {
            text-align: center;
            margin-bottom: 2rem;
        }
        .password_reset_email-header h1 {
            color: #2c3e50;
            font-size: 2rem;
            margin-bottom: 1rem;
        }
        .password_reset_email-content {
            margin-bottom: 2rem;
        }
        .password_reset_email-content p {
            margin-bottom: 1rem;
            color: #333;
        }
        .password_reset_email-button {
            display: inline-block;
            background: #3498db;
            color: white;
            padding: 0.8rem 1.5rem;
            border-radius: 4px;
            text-decoration: none;
            margin: 1rem 0;
        }
        .password_reset_email-footer {
            margin-top: 2rem;
            padding-top: 1rem;
            border-top: 1px solid #ddd;
            text-align: center;
            color: #7f8c8d;
            font-size: 0.9rem;
        }
    </style>
</head>
<body>
    <div class="password_reset_email">
        <div class="password_reset_email-header">
            <h1>Reset Your Password</h1>
        </div>

        <div class="password_reset_email-content">
            <p>Hello,</p>
            <p>We received a request to reset your password for your Test account. If you didn't make this request, you can safely ignore this email.</p>
            <p>To reset your password, click the button below:</p>

            <div style="text-align: center;">
                <a href="{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}"
                   class="password_reset_email-button">
                    Reset Password
                </a>
            </div>

            <p>This link will expire in 24 hours for security reasons.</p>
            <p>If you're having trouble clicking the button, you can copy and paste this link into your browser:</p>
            <p style="word-break: break-all; color: #3498db;">
                {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
            </p>
        </div>

        <div class="password_reset_email-footer">
            <p>This email was sent by Test Domain</p>
            <p>If you have any questions, please contact our support team</p>
        </div>
    </div>
</body>
</html>

views.py

class ResetPasswordView(SuccessMessageMixin, PasswordResetView):
    template_name = 'forgot_password.html'
    html_email_template_name = 'password_reset_email.html'
    subject_template_name = 'Password_reset_subject.txt'
    success_message =  "We've emailed you instructions for resetting your password, " \
                      "if an account exists with the email you entered. You should receive an email shortly." \
                      " If you don't receive an email, " \
                      "please make sure you've entered the address you registered with, and check your spam folder."
    success_url = reverse_lazy('login')

urls.py(主路由)

from django.urls import path, include
from users.views import ResetPasswordView
from django.contrib.auth import views as auth_views


urlpatterns = [
    path('password_reset/', ResetPasswordView.as_view(), name='password_reset'),

    path('password_reset_confirm/<uidb64>/<token>/', auth_views.PasswordResetConfirmView.as_view(template_name='password_confirmation.html'), name='password_reset_confirm'),
    path('password_reset_complete/', auth_views.PasswordResetCompleteView.as_view(template_name='password_complete.html'), name='password_reset_complete'),

]

问题原因

绝大多数邮件客户端(如Gmail、Outlook)会忽略HTML头部的<style>内部样式表,仅支持内联样式(直接写在HTML元素style属性中的样式),这是邮件渲染的特殊性导致的。

解决办法

方法1:手动将CSS内联到HTML元素

把原来的类样式全部转换为内联样式,修改后的模板如下:

{% load static %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>重置您的密码</title>
</head>
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333; background-color: #f5f5f5; margin: 0; padding: 0;">
    <div style="max-width: 600px; margin: 0 auto; padding: 2rem; background: white; border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);">
        <div style="text-align: center; margin-bottom: 2rem;">
            <h1 style="color: #2c3e50; font-size: 2rem; margin-bottom: 1rem;">重置您的密码</h1>
        </div>

        <div style="margin-bottom: 2rem;">
            <p style="margin-bottom: 1rem; color: #333;">您好,</p>
            <p style="margin-bottom: 1rem; color: #333;">我们收到了您的Test账户密码重置请求。如果不是您本人操作,请忽略此邮件。</p>
            <p style="margin-bottom: 1rem; color: #333;">点击下方按钮重置密码:</p>

            <div style="text-align: center;">
                <a href="{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}"
                   style="display: inline-block; background: #3498db; color: white; padding: 0.8rem 1.5rem; border-radius: 4px; text-decoration: none; margin: 1rem 0;">
                    重置密码
                </a>
            </div>

            <p style="margin-bottom: 1rem; color: #333;">出于安全考虑,此链接24小时后失效。</p>
            <p style="margin-bottom: 1rem; color: #333;">如果无法点击按钮,请复制以下链接到浏览器地址栏:</p>
            <p style="word-break: break-all; color: #3498db; margin-bottom: 1rem;">
                {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
            </p>
        </div>

        <div style="margin-top: 2rem; padding-top: 1rem; border-top: 1px solid #ddd; text-align: center; color: #7f8c8d; font-size: 0.9rem;">
            <p style="margin-bottom: 0.5rem;">此邮件由Test Domain发送</p>
            <p>如有疑问,请联系我们的支持团队</p>
        </div>
    </div>
</body>
</html>

方法2:使用工具自动内联样式(推荐)

手动内联样式效率低且易出错,可使用django-inlinecss库自动将内部样式转换为内联样式:

  1. 安装库:
pip install django-inlinecss
  1. 在settings.py中添加inlinecss到INSTALLED_APPS:
INSTALLED_APPS = [
    # ...其他应用
    'inlinecss',
]
  1. 修改邮件模板,用{% inlinecss %}标签包裹需要处理的内容:
{% load static inlinecss %}
{% inlinecss "css/email_styles.css" %}
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>重置您的密码</title>
</head>
<body>
    <!-- 原模板内容不变,样式写在单独的email_styles.css文件中 -->
</body>
</html>
{% endinlinecss %}

发送邮件时,该库会自动把外部CSS文件的样式内联到对应的HTML元素上。

额外注意事项

  • 避免使用复杂CSS选择器(如子选择器、伪类),邮件客户端支持有限;
  • 针对老旧邮件客户端,建议用表格布局代替div布局,兼容性更好;
  • 发送测试邮件时,使用邮件预览工具查看不同客户端的渲染效果,提前规避兼容性问题。

内容的提问来源于stack exchange,提问作者Luke

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 05:55:02