Sending email via Django gives me (_ssl.c:3895) error

1k Views Asked by At

It looks like there is a problem with the ssl certificate when trying to send emails using django.core.mail.backends.smtp.EmailBackend.

Settings.py

EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 587
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_USE_TLS = True
EMAIL_SSL_CERTFILE = certifi.where()
EMAIL_SSL_CA_BUNDLE = certifi.where()

The password is an app password I created in my google account. I even tried to use third party services like Elastic Email and SendGrid, but it still gives me an error. Removing the EMAIL_SSL_CERTFILE and EMAIL_SSL_CA_BUNDLE will then give me a (_ssl.c:997) error.

views.py

@api_view(["POST"])
def signupUser(request):
    serializer = UserSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save()
        return Response(serializer.data)
    else:
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


Serializers.py

import random

from user_api.models import CustomUser
from django.contrib.auth.hashers import make_password
from django.core.mail import EmailMessage
from django.core.mail import send_mail

from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = CustomUser
        fields = ['username', 'email', 'password', 'profile_image', 'api_key']
        extra_kwargs = {'password': {'write_only': True}, 'id': {'read_only': True}}

    def update(self, instance, validated_data):
        instance.username = validated_data['username']
        instance.email = validated_data['email']
        instance.api_key = validated_data['api_key']
        instance.profile_image = validated_data['profile_image']

        instance.save()
        return instance

    def create(self, validated_data):
        verification_code = random.randint(100000, 999999)
        user = CustomUser.objects.create(username=validated_data['username'],email=validated_data['email'], password=make_password(validated_data['password']), verification_code=verification_code)
        user.set_password(validated_data['password'])
        user.save()

        email = EmailMessage(
            'Hello',
            f'This is your verification code : {verification_code}',
            '[email protected]',
            [validated_data['email']]
        )

        email.fail_silently=False
        email.send()
        
        return user

I also tried switching the EMAIL_BACKEND to django.core.mail.backends.console.EmailBackend. It works well and I see the email being logged in the console.

1

There are 1 best solutions below

3
Saxtheowl On

It could be related to using TLS instead of SSL, or could be caused by incorrect handling of the SSL certificates.

First we try with TLS, by changing your EMAIL_USE_TLS setting to False and set EMAIL_USE_SSL to True. Also, change EMAIL_PORT to 465

Or we could remove the EMAIL_SSL_CERTFILE and EMAIL_SSL_CA_BUNDLE, your email settings should be like that:

EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = '[email protected]'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_PORT = 465
EMAIL_USE_TLS = False
EMAIL_USE_SSL = True
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'