 
  After upgrading Django to version 5.0 and updating other libraries, an error occurred when executing the following email sending code:
message = EmailMessage(
    subject='Verification Email',
    body='This is a verification email. Please ignore it.',
    from_email='developer@example.com',
    to=['test-user@example.com'],
    reply_to=['developer@example.com'],
)
send_result = message.send()The following error message was displayed:
Traceback (most recent call last):
  File "<...>python3.11/site-packages/django/core/management/base.py", line 413, in run_from_argv
    self.execute(*args, **cmd_options)
  File "<...>python3.11/site-packages/django/core/management/base.py", line 459, in execute
    output = self.handle(*args, **options)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<...>management/commands/send_test_mail.py", line 34, in handle
    send_result = message.send()
                  ^^^^^^^^^^^^^^
  File "<...>python3.11/site-packages/django/core/mail/message.py", line 300, in send
    return self.get_connection(fail_silently).send_messages([self])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<...>python3.11/site-packages/django/core/mail/backends/smtp.py", line 128, in send_messages
    new_conn_created = self.open()
                       ^^^^^^^^^^^
  File "<...>python3.11/site-packages/django/core/mail/backends/smtp.py", line 93, in open
    self.connection.starttls(context=self.ssl_context)
  File "<...>lib/python3.11/smtplib.py", line 790, in starttls
    self.sock = context.wrap_socket(self.sock,
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<...>lib/python3.11/ssl.py", line 517, in wrap_socket
    return self.sslsocket_class._create(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<...>lib/python3.11/ssl.py", line 1108, in _create
    self.do_handshake()
  File "<...>lib/python3.11/ssl.py", line 1379, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self-signed certificate (_ssl.c:1006)The SMTP server being connected to is one created by installing Postfix on an EC2 instance.
It seems that this error occurs because the self-signed certificate cannot be verified.
Incidentally, when using the same server with smtplib:
s = smtplib.SMTP(...)
s.starttls()
s.ehlo()
s.login(...)
s.sendmail(...)The above error does not occur.
As a temporary measure, by modifying the following part of the email sending code:
self.connection.starttls(context=self.ssl_context)If you pass ssl._create_unverified_context() to context, it will work. (By default, ssl.create_default_context() is used.)
However, skipping certificate verification is not a good practice.
For instance, creating a function like the one below and using it in place of EmailMessage.send will allow sending the email while skipping the verification and issuing a warning:
def send_message_use_unverified_backend(email_message, *, fail_silently=False):
    if not email_message.recipients():
        return 0
    connection = email_message.get_connection(fail_silently=fail_silently)
    connection.ssl_context = ssl._create_unverified_context()
    return connection.send_messages([email_message])
message = EmailMessage(...)
send_message_use_unverified_backend(message)Ideally, instead of the above workaround, it's better to use managed SMTP services like Amazon SES or Sendgrid.