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

如何用Django框架验证邮箱真实性?现有邮件发送器无校验逻辑

嘿,这个问题我之前做邮件服务的时候也踩过坑!要判断收件邮箱是不是真实存在,没法做到100%精准,但通过几个步骤能大幅筛掉无效邮箱,下面给你具体的实现思路和代码:

实现收件邮箱真实性验证的方案

1. 先做格式层面的基础验证

首先,确保你的Django表单用内置的EmailField做基础格式校验,它会自动检查邮箱是否符合xxx@xxx.xxx的格式,过滤掉明显的无效输入。比如你的表单可以这么写:

from django import forms

class SubscribeForm(forms.Form):
    to_email = forms.EmailField(label="收件邮箱", required=True)
    subject = forms.CharField(label="主题", max_length=200)
    body = forms.CharField(label="邮件内容", widget=forms.Textarea)

2. 检查邮箱域名的MX记录

真实能接收邮件的域名(比如gmail.com、outlook.com)一定有MX邮件交换记录,这是验证域名有效性的关键一步。我们可以用dnspython库来查询MX记录:

首先安装依赖:

pip install dnspython

然后在表单里添加自定义验证逻辑,或者单独写一个验证函数:

import dns.resolver

def is_valid_email_domain(email):
    try:
        # 拆分出邮箱的域名部分
        domain = email.split('@')[1]
        # 查询该域名的MX记录
        dns.resolver.resolve(domain, 'MX')
        return True
    except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer, IndexError):
        # 域名不存在/无MX记录/邮箱格式错误时返回False
        return False

# 在表单里添加字段级验证
class SubscribeForm(forms.Form):
    # ... 字段定义 ...

    def clean_to_email(self):
        email = self.cleaned_data.get('to_email')
        if not is_valid_email_domain(email):
            raise forms.ValidationError("该邮箱域名无法接收邮件,请检查邮箱是否正确")
        return email

这一步能过滤掉大部分伪造的域名(比如xxx@fake-domain.com这种不存在的域名),但没法确认具体的邮箱账号是否真实存在(比如nonexistent-user@gmail.com这种域名有效但账号不存在的情况)。

3. 发送验证邮件(最可靠的方式)

如果要彻底确认邮箱真实存在,最靠谱的方法是给收件邮箱发一封验证邮件,让用户点击链接确认。这种方式适合订阅类场景,具体实现步骤如下:

第一步:创建存储验证信息的模型

from django.db import models
import uuid
from datetime import datetime, timedelta

class VerifiedEmail(models.Model):
    email = models.EmailField(unique=True)
    token = models.UUIDField(default=uuid.uuid4, editable=False)
    is_verified = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    expires_at = models.DateTimeField()

    def save(self, *args, **kwargs):
        # 默认设置验证链接24小时过期
        if not self.expires_at:
            self.expires_at = datetime.now() + timedelta(hours=24)
        super().save(*args, **kwargs)

第二步:修改发送邮件的视图逻辑

先检查邮箱是否已验证,未验证则发验证邮件,已验证再发正式邮件:

from django.core.mail import send_mail, EmailMessage
from django.urls import reverse
from django.contrib import messages
from .models import VerifiedEmail

def send_email(request):
    if request.method == 'POST':
        form = SubscribeForm(request.POST)
        if form.is_valid():
            email = form.cleaned_data['to_email']
            verified_email, created = VerifiedEmail.objects.get_or_create(email=email)
            
            if not verified_email.is_verified:
                # 生成验证链接
                verify_url = request.build_absolute_uri(
                    reverse('verify_email', kwargs={'token': verified_email.token})
                )
                # 发送验证邮件
                send_mail(
                    "请验证你的邮箱",
                    f"点击下方链接完成邮箱验证:\n{verify_url}\n链接24小时内有效",
                    EMAIL_HOST_USER,
                    [email]
                )
                messages.info(request, f"验证邮件已发送到{email},请点击链接验证后再发送正式邮件")
                return redirect('/')
            else:
                # 已验证,发送正式邮件
                message = form.cleaned_data['body']
                subject = form.cleaned_data['subject']
                email_msg = EmailMessage(subject, message, EMAIL_HOST_USER, [email])
                email_msg.send(fail_silently=False)
                messages.success(request, f'邮件已成功发送到 {email}')
                return redirect('/')
        else:
            context = {'form': form}
            return render(request, 'index.html', context)
    else:
        form = SubscribeForm()
        context = {'form': form}
        return render(request, 'index.html', context)

第三步:添加验证视图和路由

写一个处理验证链接的视图:

from datetime import datetime
from django.contrib import messages
from django.shortcuts import redirect
from .models import VerifiedEmail

def verify_email(request, token):
    try:
        # 检查token是否有效且未过期
        verified_email = VerifiedEmail.objects.get(token=token, expires_at__gt=datetime.now())
        verified_email.is_verified = True
        verified_email.save()
        messages.success(request, "邮箱验证成功!现在可以发送邮件啦")
    except VerifiedEmail.DoesNotExist:
        messages.error(request, "验证链接无效或已过期")
    return redirect('/')

在urls.py里添加路由:

from django.urls import path
from .views import send_email, verify_email

urlpatterns = [
    path('', send_email, name='send_email'),
    path('verify-email/<uuid:token>/', verify_email, name='verify_email'),
]

注意事项

  • MX记录验证能快速过滤无效域名,但无法确认具体账号是否存在
  • 发送验证邮件是最可靠的方式,但需要用户配合,适合需要长期交互的场景
  • 如果你用Gmail的SMTP服务,记得开启应用专用密码(不要用账号密码直接登录),避免被谷歌拦截
  • 不要频繁给同一个未验证邮箱发邮件,容易被判定为垃圾邮件

内容的提问来源于stack exchange,提问作者Zakaria Abdessamed Brahimi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 11:07:31