电子邮件确认系统 - 如何将已提交的电子邮件设置为信号中的recipient_list

时间:2017-05-15 13:53:41

标签: python django email django-signals django-email

我成功手动将电子邮件发送到特定的电子邮件地址并激活了用户,但我无法弄清楚如何:

  1. 将提交的电子邮件设置为我的recipient_list post_save_activation_receiver信号,因为电子邮件字段本身是在其他模型中定义的(如果可能的话)?
  2. 使我发送的电子邮件更安全,因为gmail正在处理 他们喜欢潜在的钓鱼内容。
  3. models.py

    from django.conf import settings
    from django.contrib.auth.models import (
        BaseUserManager, AbstractBaseUser
    )
    from django.contrib import messages
    from django.core.mail import send_mail
    from django.conf import settings
    from django.core.validators import RegexValidator
    from django.db import models
    from django.db.models.signals import post_save
    # Create your models here.
    from .utils import code_generator
    
    USERNAME_REGEX = '^[a-zA-Z0-9.+-]*$'
    
    class MyUserManager(BaseUserManager):
        def create_user(self, username, email, password=None):
            """
            Creates and saves a User with the given email, date of
            birth and password.
            """
            if not email:
                raise ValueError('Users must have an email address')
    
            user = self.model(
                username = username,
                email=self.normalize_email(email),
            )
    
            user.set_password(password)
            user.save(using=self._db)
            return user
    
        def create_superuser(self, username, email, password):
            """
            Creates and saves a superuser with the given email, date of
            birth and password.
            """
            user = self.create_user(
                username,
                email,
                password=password,
            )
            user.is_admin = True
            user.is_staff = True
            user.save(using=self._db)
            return user
    
    
    class MyUser(AbstractBaseUser):
        username = models.CharField(
                    max_length=255, 
                    validators=[
                        RegexValidator(
                            regex = USERNAME_REGEX,
                            message = 'Username must be Alpahnumeric or contain any of the following: ". @ + -" ',
                            code='invalid_username'
                        )],
                    unique=True,
                )
        email = models.EmailField(
            verbose_name='email address',
            max_length=255,
            unique=True,
        )
        zipcode   = models.CharField(max_length=120, default="92660")
        is_active = models.BooleanField(default=True)
        is_staff = models.BooleanField(default=False)
        is_admin = models.BooleanField(default=False)
    
        objects = MyUserManager()
    
        USERNAME_FIELD = 'username'
        REQUIRED_FIELDS = ['email']
    
        def get_full_name(self):
            # The user is identified by their email address
            return self.email
    
        def get_short_name(self):
            # The user is identified by their email address
            return self.email
    
        def __str__(self):              # __unicode__ on Python 2
            return self.email
    
        def has_perm(self, perm, obj=None):
            "Does the user have a specific permission?"
            # Simplest possible answer: Yes, always
            return True
    
        def has_module_perms(self, app_label):
            "Does the user have permissions to view the app `app_label`?"
            # Simplest possible answer: Yes, always
            return True
    
    
    
        # @property
        # def is_staff(self):
        #     "Is the user a member of staff?"
        #     # Simplest possible answer: All admins are staff
        #     return self.is_admin
    
    
    
    class ActivationProfile(models.Model):
        user    = models.ForeignKey(settings.AUTH_USER_MODEL)
        key     = models.CharField(max_length=120)
        expired = models.BooleanField(default=False)
    
        def save(self, *args, **kwargs):
            self.key = code_generator()
            super(ActivationProfile, self).save(*args, **kwargs)
    
    
    def post_save_activation_receiver(sender, instance, created, *args, **kwargs):
        if created:
            #send email
            subject = 'Registration'
            message = "http://127.0.0.1:8000/activate/{0}".format(instance.key)
            from_email = settings.EMAIL_HOST_USER
            recipient_list = ['UserEmail']
            print(recipient_list)
    
            send_mail(subject, message, from_email, recipient_list, fail_silently=True)
    
    post_save.connect(post_save_activation_receiver, sender=ActivationProfile)
    
    
    
    
    class Profile(models.Model):
        user = models.OneToOneField(settings.AUTH_USER_MODEL)
        city = models.CharField(max_length=120, null=True, blank=True)
    
        def __str__(self):
            return str(self.user.username)
    
        def __unicode__(self):
            return str(self.user.username)
    
    
    def post_save_user_model_receiver(sender, instance, created, *args, **kwargs):
        if created:
            try:
                Profile.objects.create(user=instance)
                ActivationProfile.objects.create(user=instance)
            except:
                pass
    
    post_save.connect(post_save_user_model_receiver, sender=settings.AUTH_USER_MODEL)
    

    forms.py

    from django import forms
    
    from django.contrib.auth.forms import ReadOnlyPasswordHashField
    from django.contrib.auth import authenticate, get_user_model
    from django.core.validators import RegexValidator
    from django.db.models import Q
    
    from .models import USERNAME_REGEX
    
    
    
    User = get_user_model()
    
    
    class UserLoginForm(forms.Form):
        query = forms.CharField(label='Username / Email')
        password = forms.CharField(label='Password', widget=forms.PasswordInput)
    
        def clean(self, *args, **kwargs):
            query = self.cleaned_data.get("query")
            password = self.cleaned_data.get("password")
            user_qs_final = User.objects.filter(
                    Q(username__iexact=query)|
                    Q(email__iexact=query)
                ).distinct()
            if not user_qs_final.exists() and user_qs_final.count() != 1:
                raise forms.ValidationError("Invalid credentials -- user not exist")
            user_obj = user_qs_final.first()
            if not user_obj.check_password(password):
                    # log auth tries
                    raise forms.ValidationError("Invalid credentials -- passowrd invalid")
            if not user_obj.is_active:
                        raise forms.ValidationError("Inactive user. Please verify your email address.")
            self.cleaned_data["user_obj"] = user_obj
            return super(UserLoginForm, self).clean(*args, **kwargs)
    
    
    class UserCreationForm(forms.ModelForm):
        """A form for creating new users. Includes all the required
        fields, plus a repeated password."""
        password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
        password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)
    
        class Meta:
            model = User
            fields = ('username', 'email',)
    
        def clean_password2(self):
            # Check that the two password entries match
            password1 = self.cleaned_data.get("password1")
            password2 = self.cleaned_data.get("password2")
            if password1 and password2 and password1 != password2:
                raise forms.ValidationError("Passwords don't match")
            return password2
    
        def save(self, commit=True):
            # Save the provided password in hashed format
            user = super(UserCreationForm, self).save(commit=False)
            user.set_password(self.cleaned_data["password1"])
            user.is_active = False
            # create a new user hash for activating email.
    
            if commit:
                user.save()
            return user
    
    
    
    class UserChangeForm(forms.ModelForm):
        """A form for updating users. Includes all the fields on
        the user, but replaces the password field with admin's
        password hash display field.
        """
        password = ReadOnlyPasswordHashField()
    
        class Meta:
            model = User
            fields = ('username', 'email', 'password', 'is_staff', 'is_active', 'is_admin')
    
        def clean_password(self):
            # Regardless of what the user provides, return the initial value.
            # This is done here, rather than on the field, because the
            # field does not have access to the initial value
            return self.initial["password"]
    

    views.py

    from django.contrib.auth import login, get_user_model, logout
    from django.http import HttpResponseRedirect, Http404
    from django.shortcuts import render
    
    # Create your views here.
    
    User = get_user_model()
    
    from .forms import UserCreationForm, UserLoginForm
    from .models import ActivationProfile
    
    
    def home(request):
        if request.user.is_authenticated():
            print(request.user.profile.city)
        return render(request, "base.html", {})
    
    
    
    def register(request, *args, **kwargs):
        form = UserCreationForm(request.POST or None)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect("/login")
        return render(request, "accounts/register.html", {"form": form})
    
    
    def login_view(request, *args, **kwargs):
        form = UserLoginForm(request.POST or None)
        if form.is_valid():
            user_obj = form.cleaned_data.get('user_obj')
            login(request, user_obj)
            return HttpResponseRedirect("/")
        return render(request, "accounts/login.html", {"form": form})
    
    
    def logout_view(request):
        logout(request)
        return HttpResponseRedirect("/login")
    
    
    def activate_user_view(request, code=None, *args, **kwargs):
        if code:
            act_profile_qs = ActivationProfile.objects.filter(key=code)
            if act_profile_qs.exists() and act_profile_qs.count() == 1:
                act_obj = act_profile_qs.first()
                if not act_obj.expired:
                    user_obj = act_obj.user
                    user_obj.is_active = True
                    user_obj.save()
                    act_obj.expired = True
                    act_obj.save()
                    return HttpResponseRedirect("/login")
        # invalid code
        return HttpResponseRedirect("/login")
    

1 个答案:

答案 0 :(得分:1)

1)将recipient_list = ['UserEmail']替换为recipient_list = [instance.user.email]

2)发送邮件很复杂。 不,我撒谎,发送邮件很简单,让他们到达收件箱而不是垃圾邮件很复杂。 有多种因素可能会发生这种情况,但我会检查以下内容:

  • 我是否从正确的邮件服务器发送 - 例如,如果您启动了本地邮件服务器,但发件人电子邮件是" foo@gmail.com"然后到接收邮件服务器这将看起来很可疑,因为发件人不是gmail.com它有点复杂但这是简短的解释
  • 同时检查您要发送的内容 - 可以过滤包含垃圾话语(正文部分放大等)的邮件。