10

Using Django 1.7 and Python 2.7.

I want to test if the mail was sent and if the content of the mail is correct.

I've tried using outbox from django.core.mail, but to no avail. Also could I just get the stdout (since I can see the mail in the console when I run my tests)?

models.py

class User(AbstractBaseUser, PermissionsMixin):
    USERNAME_FIELD = 'email'

    email = models.EmailField(max_length=255, unique=True)
    is_staff =  models.BooleanField(default=False)
    org = models.ForeignKey('Org', null=True, blank=True,
        on_delete=models.SET_NULL)

    def __unicode__(self):
        return self.email

    @staticmethod
    def send_password_token(email):
        user = get_object_or_404(User, email=email)
        token = Token.objects.get(user=user)
        message_body = 'Your password reset token:\n\n\t%s' % token.key
        send_mail('Password reset:', message_body,
            settings.FROM_EMAIL, [email], fail_silently=False)

tests.py

class UserModelTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(email='user@info.com',
            password='0000')

    @override_settings(EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend')
    def test_send_password_token(self):
        """
        Sends a password reset mail with users authentication token.
        """
        token = Token.objects.get(user=self.user)
        User.send_password_token(self.user.email)
Moe Far
  • 2,742
  • 2
  • 23
  • 41
Saša Kalaba
  • 4,241
  • 6
  • 29
  • 52
  • 4
    Have you seen the [example in the docs](https://docs.djangoproject.com/en/1.9/topics/testing/tools/#email-services)? You should remove the `override_settings` decorator. Then Django will automatically use the `locmem` email backend and put the email in the outbox for you to check. – Alasdair Feb 12 '16 at 14:08
  • 1
    When you use the console backend, mails will only be sent to stdout, and not be available from the django.core.mail mailbox. Use the locmem backend. https://docs.djangoproject.com/en/1.9/topics/email/#in-memory-backend – Håken Lid Feb 12 '16 at 14:13

1 Answers1

15

Thanks for @Alasdair for the solution. Turns out it was quite simple. Just remove override_settings and import outbox.

tests.py

from django.core.mail import outbox

class UserModelTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(email='user@info.com',
            password='0000')

    def test_send_password_token(self):
        """
        Sends a password reset mail with users authentication token.
        """
        token = Token.objects.get(user=self.user)
        User.send_password_token(self.user.email)
        self.assertEqual(len(outbox), 1)
        self.assertEqual(outbox[0].subject, 'Password reset:')
        self.assertEqual(outbox[0].from_email, <insert_from_email>)
        self.assertEqual(outbox[0].to, [<insert_list_of_to_emails>])
        self.assertEqual(outbox[0].body,
            'Your password reset token:\n\n\t%s' % token.key)
Alasdair
  • 298,606
  • 55
  • 578
  • 516
Saša Kalaba
  • 4,241
  • 6
  • 29
  • 52
  • 9
    This may have changed in Django 2 -- now the import seems to be `from django.core import mail` and the outbox is inspected like `mail.outbox` – Mark Chackerian Feb 07 '18 at 19:59