Django
Email checker for Django. Python email verification in Django views and forms.
Integrieren Sie EmailVerify mit Django-Anwendungen mit Hilfe von benutzerdefinierten Validatoren, Formularfeldern und Middleware.
Installation
pip install emailverifyKonfiguration
Fügen Sie zu Ihren Django-Einstellungen hinzu:
# settings.py
EMAILVERIFY_API_KEY = os.environ.get('EMAILVERIFY_API_KEY')
# Optionale Einstellungen
EMAILVERIFY_TIMEOUT = 10 # seconds
EMAILVERIFY_BLOCK_DISPOSABLE = True
EMAILVERIFY_BLOCK_ROLE_BASED = False
EMAILVERIFY_CACHE_DURATION = 3600 # 1 hourBenutzerdefinierter Validator
Erstellen Sie einen wiederverwendbaren E-Mail-Validator.
# validators.py
from django.core.exceptions import ValidationError
from django.conf import settings
from emailverify import Client
import logging
logger = logging.getLogger(__name__)
def validate_email_deliverable(email):
"""Überprüfen Sie, dass eine E-Mail-Adresse zustellbar ist."""
client = Client(api_key=settings.EMAILVERIFY_API_KEY)
try:
result = client.verify(email)
if result.status == 'invalid':
raise ValidationError(
'Bitte geben Sie eine gültige E-Mail-Adresse ein.',
code='invalid_email'
)
if getattr(settings, 'EMAILVERIFY_BLOCK_DISPOSABLE', True):
if result.result.disposable:
raise ValidationError(
'Wegwerfmail-Adressen sind nicht zulässig.',
code='disposable_email'
)
if getattr(settings, 'EMAILVERIFY_BLOCK_ROLE_BASED', False):
if result.result.role:
raise ValidationError(
'Rollenbasierte E-Mail-Adressen sind nicht zulässig.',
code='role_email'
)
except Exception as e:
# Fehler protokollieren, aber Einreichung nicht blockieren
logger.warning(f'E-Mail-Verifikation für {email} fehlgeschlagen: {e}')
class EmailDeliverableValidator:
"""Klassenbasierter Validator mit anpassbaren Optionen."""
def __init__(self, block_disposable=True, block_role_based=False):
self.block_disposable = block_disposable
self.block_role_based = block_role_based
self.client = Client(api_key=settings.EMAILVERIFY_API_KEY)
def __call__(self, email):
try:
result = self.client.verify(email)
if result.status == 'invalid':
raise ValidationError(
'Bitte geben Sie eine gültige E-Mail-Adresse ein.',
code='invalid_email'
)
if self.block_disposable and result.result.disposable:
raise ValidationError(
'Wegwerfmail-Adressen sind nicht zulässig.',
code='disposable_email'
)
if self.block_role_based and result.result.role:
raise ValidationError(
'Rollenbasierte E-Mail-Adressen sind nicht zulässig.',
code='role_email'
)
except ValidationError:
raise
except Exception as e:
logger.warning(f'Email verification failed: {e}')
def __eq__(self, other):
return (
isinstance(other, EmailDeliverableValidator) and
self.block_disposable == other.block_disposable and
self.block_role_based == other.block_role_based
)Modellfeld
Fügen Sie Verifikation zu Modellfeldern hinzu.
# models.py
from django.db import models
from .validators import validate_email_deliverable
class User(models.Model):
email = models.EmailField(
unique=True,
validators=[validate_email_deliverable]
)
name = models.CharField(max_length=255)
email_verification_status = models.CharField(
max_length=20,
blank=True,
null=True
)
email_verification_score = models.FloatField(
blank=True,
null=True
)
email_verified_at = models.DateTimeField(
blank=True,
null=True
)
class Meta:
db_table = 'users'Formular-Integration
Basis-Formular
# forms.py
from django import forms
from django.core.validators import EmailValidator
from .validators import EmailDeliverableValidator
class RegistrationForm(forms.Form):
name = forms.CharField(max_length=255)
email = forms.EmailField(
validators=[
EmailValidator(),
EmailDeliverableValidator(
block_disposable=True,
block_role_based=False
)
]
)
password = forms.CharField(widget=forms.PasswordInput)
password_confirm = forms.CharField(widget=forms.PasswordInput)
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
password_confirm = cleaned_data.get('password_confirm')
if password and password_confirm and password != password_confirm:
raise forms.ValidationError('Passwörter stimmen nicht überein.')
return cleaned_dataModellformular
# forms.py
from django import forms
from .models import User
from .validators import validate_email_deliverable
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['name', 'email']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Validator zu E-Mail-Feld hinzufügen
self.fields['email'].validators.append(validate_email_deliverable)View-Integration
# views.py
from django.shortcuts import render, redirect
from django.contrib import messages
from django.views import View
from emailverify import Client
from django.conf import settings
from .forms import RegistrationForm
from .models import User
class RegistrationView(View):
template_name = 'registration/register.html'
def get(self, request):
form = RegistrationForm()
return render(request, self.template_name, {'form': form})
def post(self, request):
form = RegistrationForm(request.POST)
if form.is_valid():
# Zusätzliche Verifikation mit vollem Ergebnis
client = Client(api_key=settings.EMAILVERIFY_API_KEY)
email = form.cleaned_data['email']
try:
result = client.verify(email)
# Benutzer mit Verifikationsdaten erstellen
user = User.objects.create(
name=form.cleaned_data['name'],
email=email,
email_verification_status=result.status,
email_verification_score=result.score,
)
user.set_password(form.cleaned_data['password'])
user.save()
messages.success(request, 'Registrierung erfolgreich!')
return redirect('login')
except Exception as e:
messages.error(request, 'Registrierung fehlgeschlagen. Bitte versuchen Sie es erneut.')
return render(request, self.template_name, {'form': form})Middleware
Überprüfen Sie E-Mails in eingehenden Anfragen.
# middleware.py
from django.http import JsonResponse
from django.conf import settings
from emailverify import Client
import logging
import json
logger = logging.getLogger(__name__)
class EmailVerificationMiddleware:
"""Middleware zur Verifikation von E-Mail-Adressen in POST-Anfragen."""
def __init__(self, get_response):
self.get_response = get_response
self.client = Client(api_key=settings.EMAILVERIFY_API_KEY)
self.protected_paths = getattr(
settings,
'EMAILVERIFY_PROTECTED_PATHS',
['/api/register/', '/api/subscribe/']
)
def __call__(self, request):
if request.method == 'POST' and self._should_verify(request.path):
email = self._extract_email(request)
if email:
try:
result = self.client.verify(email)
if result.status == 'invalid':
return JsonResponse(
{'error': 'Ungültige E-Mail-Adresse'},
status=400
)
# Verifikationsergebnis an Anfrage anhängen
request.email_verification = result
except Exception as e:
logger.warning(f'Email verification failed: {e}')
return self.get_response(request)
def _should_verify(self, path):
return any(path.startswith(p) for p in self.protected_paths)
def _extract_email(self, request):
# Versuchen Sie, den JSON-Body zu lesen
if request.content_type == 'application/json':
try:
data = json.loads(request.body)
return data.get('email')
except json.JSONDecodeError:
pass
# Versuchen Sie, POST-Daten zu lesen
return request.POST.get('email')Middleware registrieren
# settings.py
MIDDLEWARE = [
# ... other middleware
'myapp.middleware.EmailVerificationMiddleware',
]
EMAILVERIFY_PROTECTED_PATHS = [
'/api/register/',
'/api/subscribe/',
'/api/contact/',
]Zwischenspeicherung
Zwischenspeicherung von Verifikationsergebnissen zur Reduzierung von API-Aufrufen.
# services.py
from django.core.cache import cache
from django.conf import settings
from emailverify import Client
import hashlib
class EmailVerificationService:
def __init__(self):
self.client = Client(api_key=settings.EMAILVERIFY_API_KEY)
self.cache_duration = getattr(
settings,
'EMAILVERIFY_CACHE_DURATION',
3600
)
def verify(self, email):
cache_key = self._get_cache_key(email)
cached = cache.get(cache_key)
if cached:
return cached
result = self.client.verify(email)
cache.set(cache_key, result, self.cache_duration)
return result
def is_valid(self, email):
result = self.verify(email)
return result.status == 'valid'
def is_disposable(self, email):
result = self.verify(email)
return result.result.disposable
def clear_cache(self, email):
cache.delete(self._get_cache_key(email))
def _get_cache_key(self, email):
email_hash = hashlib.md5(email.lower().encode()).hexdigest()
return f'email_verification:{email_hash}'
# Usage
verification_service = EmailVerificationService()
if verification_service.is_valid(email):
# Gültige E-Mail verarbeiten
passDjango REST Framework
Serializer-Validierung
# serializers.py
from rest_framework import serializers
from django.conf import settings
from emailverify import Client
class RegistrationSerializer(serializers.Serializer):
name = serializers.CharField(max_length=255)
email = serializers.EmailField()
password = serializers.CharField(write_only=True)
def validate_email(self, value):
client = Client(api_key=settings.EMAILVERIFY_API_KEY)
try:
result = client.verify(value)
if result.status == 'invalid':
raise serializers.ValidationError(
'Bitte geben Sie eine gültige E-Mail-Adresse ein.'
)
if result.result.disposable:
raise serializers.ValidationError(
'Wegwerfmail-Adressen sind nicht zulässig.'
)
# Ergebnis für späteren Gebrauch speichern
self.context['email_verification'] = result
except serializers.ValidationError:
raise
except Exception as e:
# Log but don't block
pass
return valueBenutzerdefinierte Berechtigung
# permissions.py
from rest_framework.permissions import BasePermission
from django.conf import settings
from emailverify import Client
class ValidEmailPermission(BasePermission):
"""Nur Anfragen mit gültigen E-Mail-Adressen zulassen."""
message = 'Eine gültige E-Mail-Adresse ist erforderlich.'
def has_permission(self, request, view):
email = request.data.get('email')
if not email:
return True # Andere Validatoren kümmern sich um fehlende E-Mail
client = Client(api_key=settings.EMAILVERIFY_API_KEY)
try:
result = client.verify(email)
return result.status != 'invalid'
except Exception:
return True # Auf API-Fehler zulassenManagement-Befehl
E-Mails von Benutzern in Massen überprüfen.
# management/commands/verify_emails.py
from django.core.management.base import BaseCommand
from django.conf import settings
from emailverify import Client
from myapp.models import User
import time
class Command(BaseCommand):
help = 'Überprüfen Sie alle E-Mail-Adressen des Benutzers'
def add_arguments(self, parser):
parser.add_argument(
'--batch-size',
type=int,
default=100,
help='Anzahl der E-Mails pro Batch'
)
def handle(self, *args, **options):
client = Client(api_key=settings.EMAILVERIFY_API_KEY)
batch_size = options['batch_size']
users = User.objects.filter(
email_verification_status__isnull=True
)
total = users.count()
self.stdout.write(f'Überprüfe {total} E-Mails...')
# E-Mails für Massenverifikation sammeln
emails = list(users.values_list('email', flat=True)[:10000])
# Masse-Job einreichen
job = client.verify_bulk(emails)
self.stdout.write(f'Job-ID: {job.job_id}')
# Auf Fertigstellung warten
while True:
status = client.get_bulk_job_status(job.job_id)
self.stdout.write(
f'Fortschritt: {status.progress_percent}%',
ending='\r'
)
if status.status == 'completed':
break
time.sleep(5)
self.stdout.write('')
# Ergebnisse abrufen und verarbeiten
results = client.get_bulk_job_results(job.job_id)
for result in results.results:
User.objects.filter(email=result.email).update(
email_verification_status=result.status,
email_verification_score=result.score,
)
self.stdout.write(self.style.SUCCESS('Verifikation abgeschlossen!'))
# Zusammenfassung ausgeben
summary = {}
for result in results.results:
summary[result.status] = summary.get(result.status, 0) + 1
for status, count in summary.items():
self.stdout.write(f' {status}: {count}')Signale
Reagieren Sie auf Modellereignisse.
# signals.py
from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.conf import settings
from emailverify import Client
from .models import User
import logging
logger = logging.getLogger(__name__)
@receiver(pre_save, sender=User)
def verify_user_email(sender, instance, **kwargs):
"""Überprüfen Sie die E-Mail vor dem Speichern des Benutzers."""
# Überspringen, wenn E-Mail nicht geändert hat
if instance.pk:
try:
old_instance = User.objects.get(pk=instance.pk)
if old_instance.email == instance.email:
return
except User.DoesNotExist:
pass
client = Client(api_key=settings.EMAILVERIFY_API_KEY)
try:
result = client.verify(instance.email)
instance.email_verification_status = result.status
instance.email_verification_score = result.score
except Exception as e:
logger.warning(f'E-Mail-Verifikation fehlgeschlagen: {e}')Testen
# tests.py
from django.test import TestCase
from unittest.mock import patch, MagicMock
from .validators import validate_email_deliverable
from django.core.exceptions import ValidationError
class EmailValidationTest(TestCase):
@patch('validators.Client')
def test_valid_email_passes(self, mock_client):
mock_result = MagicMock()
mock_result.status = 'valid'
mock_result.result.disposable = False
mock_result.result.role = False
mock_client.return_value.verify.return_value = mock_result
# Sollte nicht auslösen
validate_email_deliverable('valid@example.com')
@patch('validators.Client')
def test_invalid_email_fails(self, mock_client):
mock_result = MagicMock()
mock_result.status = 'invalid'
mock_client.return_value.verify.return_value = mock_result
with self.assertRaises(ValidationError):
validate_email_deliverable('invalid@example.com')
@patch('validators.Client')
def test_disposable_email_blocked(self, mock_client):
mock_result = MagicMock()
mock_result.status = 'valid'
mock_result.result.disposable = True
mock_client.return_value.verify.return_value = mock_result
with self.assertRaises(ValidationError):
validate_email_deliverable('temp@mailinator.com')