diff --git a/django/core/mail/backends/filebased.py b/django/core/mail/backends/filebased.py index b30bb67e92..498d86fba8 100644 --- a/django/core/mail/backends/filebased.py +++ b/django/core/mail/backends/filebased.py @@ -17,9 +17,6 @@ class EmailBackend(ConsoleEmailBackend): self.file_path = file_path else: self.file_path = getattr(settings, 'EMAIL_FILE_PATH', None) - # Make sure self.file_path is a string. - if not isinstance(self.file_path, str): - raise ImproperlyConfigured('Path for saving emails is invalid: %r' % self.file_path) self.file_path = os.path.abspath(self.file_path) try: os.makedirs(self.file_path, exist_ok=True) diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index d67d706d66..97b1584765 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1283,6 +1283,10 @@ Default: Not defined The directory used by the :ref:`file email backend ` to store output files. +.. versionchanged:: 3.1 + + Support for :class:`pathlib.Path` was added. + .. setting:: EMAIL_HOST ``EMAIL_HOST`` diff --git a/docs/releases/3.1.txt b/docs/releases/3.1.txt index 1a965b41b5..a35ae79ea9 100644 --- a/docs/releases/3.1.txt +++ b/docs/releases/3.1.txt @@ -119,7 +119,8 @@ CSRF Email ~~~~~ -* ... +* The :setting:`EMAIL_FILE_PATH` setting, used by the :ref:`file email backend + `, now supports :class:`pathlib.Path`. File Storage ~~~~~~~~~~~~ diff --git a/docs/topics/email.txt b/docs/topics/email.txt index bc983b4f2e..37db613f82 100644 --- a/docs/topics/email.txt +++ b/docs/topics/email.txt @@ -527,6 +527,10 @@ To specify this backend, put the following in your settings:: This backend is not intended for use in production -- it is provided as a convenience that can be used during development. +.. versionchanged:: 3.1 + + Support for :class:`pathlib.Path` was added. + .. _topic-email-memory-backend: In-memory backend diff --git a/tests/mail/tests.py b/tests/mail/tests.py index 6de819965a..567a012b8d 100644 --- a/tests/mail/tests.py +++ b/tests/mail/tests.py @@ -12,6 +12,7 @@ from email.header import Header from email.mime.text import MIMEText from email.utils import parseaddr from io import StringIO +from pathlib import Path from smtplib import SMTP, SMTPAuthenticationError, SMTPException from ssl import SSLError from unittest import mock @@ -567,6 +568,10 @@ class MailTests(HeadersCheckMixin, SimpleTestCase): mail.get_connection('django.core.mail.backends.filebased.EmailBackend', file_path=tmp_dir), filebased.EmailBackend ) + + msg = 'expected str, bytes or os.PathLike object, not object' + with self.assertRaisesMessage(TypeError, msg): + mail.get_connection('django.core.mail.backends.filebased.EmailBackend', file_path=object()) self.assertIsInstance(mail.get_connection(), locmem.EmailBackend) @override_settings( @@ -1154,7 +1159,7 @@ class FileBackendTests(BaseEmailBackendTests, SimpleTestCase): def setUp(self): super().setUp() - self.tmp_dir = tempfile.mkdtemp() + self.tmp_dir = self.mkdtemp() self.addCleanup(shutil.rmtree, self.tmp_dir) self._settings_override = override_settings(EMAIL_FILE_PATH=self.tmp_dir) self._settings_override.enable() @@ -1163,6 +1168,9 @@ class FileBackendTests(BaseEmailBackendTests, SimpleTestCase): self._settings_override.disable() super().tearDown() + def mkdtemp(self): + return tempfile.mkdtemp() + def flush_mailbox(self): for filename in os.listdir(self.tmp_dir): os.unlink(os.path.join(self.tmp_dir, filename)) @@ -1209,6 +1217,12 @@ class FileBackendTests(BaseEmailBackendTests, SimpleTestCase): connection.close() +class FileBackendPathLibTests(FileBackendTests): + def mkdtemp(self): + tmp_dir = super().mkdtemp() + return Path(tmp_dir) + + class ConsoleBackendTests(BaseEmailBackendTests, SimpleTestCase): email_backend = 'django.core.mail.backends.console.EmailBackend'