Невозможно отправить почту в докеризованном Django-приложении, если настройки почты заданы из среды docker
Я работаю над докеризованным проектом django store с Celery и Redis. Когда покупатель делает заказ, Celery отправляет ему письмо об этом. Когда я задаю настройки почты в django напрямую, все работает нормально:
EMAIL_USE_SSL = True
EMAIL_HOST = "smtp.yandex.ru"
EMAIL_HOST_USER = "mymail@yandex.ru"
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST_PASSWORD = "password"
EMAIL_PORT = 465
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
SERVER_EMAIL = EMAIL_HOST_USER
EMAIL_ADMIN = EMAIL_HOST_USER
Но когда я устанавливаю те же переменные из окружения docker-compose:
EMAIL_USE_SSL = os.getenv("EMAIL_USER_SSL")
EMAIL_HOST = os.getenv("EMAIL_HOST")
EMAIL_HOST_USER = os.getenv("EMAIL_HOST_USER")
EMAIL_BACKEND = os.getenv("EMAIL_BACKEND")
EMAIL_HOST_PASSWORD = os.getenv("EMAIL_HOST_PASSWORD")
EMAIL_PORT = os.getenv("EMAIL_PORT")
DEFAULT_FROM_EMAIL = os.getenv("EMAIL_HOST_USER")
SERVER_EMAIL = os.getenv("EMAIL_HOST_USER")
EMAIL_ADMIN = os.getenv("EMAIL_HOST_USER")
Я получаю следующую ошибку от Celery:
celery-1 | [2024-09-23 12:48:48,816: ERROR/ForkPoolWorker-2] Task orders.tasks.send_order_email[243058c7-6fc2-47a2-9f36-7e0e1b00cd9d] raised unexpected: AttributeError("'NoneType' object has no attribute 'rsplit'")
celery-1 | Traceback (most recent call last):
celery-1 | File "/usr/local/lib/python3.11/site-packages/celery/app/trace.py", line 453, in trace_task
celery-1 | R = retval = fun(*args, **kwargs)
celery-1 | ^^^^^^^^^^^^^^^^^^^^
celery-1 | File "/usr/local/lib/python3.11/site-packages/celery/app/trace.py", line 736, in __protected_call__
celery-1 | return self.run(*args, **kwargs)
celery-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^
celery-1 | File "/usr/src/bookstore/orders/tasks.py", line 7, in send_order_email
celery-1 | send_mail(
celery-1 | File "/usr/local/lib/python3.11/site-packages/django/core/mail/__init__.py", line 77, in send_mail
celery-1 | connection = connection or get_connection(
celery-1 | ^^^^^^^^^^^^^^^
celery-1 | File "/usr/local/lib/python3.11/site-packages/django/core/mail/__init__.py", line 51, in get_connection
celery-1 | klass = import_string(backend or settings.EMAIL_BACKEND)
celery-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
celery-1 | File "/usr/local/lib/python3.11/site-packages/django/utils/module_loading.py", line 25, in import_string
celery-1 | module_path, class_name = dotted_path.rsplit(".", 1)
celery-1 | ^^^^^^^^^^^^^^^^^^
celery-1 | AttributeError: 'NoneType' object has no attribute 'rsplit'
docker-compose.yml
version: '3.8'
services:
django:
build: .
container_name: django
volumes:
- .:/usr/src/bookstore/
ports:
- "8000:8000"
command: >
sh -c "python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py loaddata fixtures/books.json
python3 manage.py loaddata fixtures/stores.json
python3 manage.py runserver 0.0.0.0:8000"
environment:
- DEBUG=1
- DJANGO_ALLOWED_HOSTS=localhost, 127.0.0.1
- CELERY_BROKER=redis://redis:6379/0
- CELERY_BACKEND=redis://redis:6379/0
- DB_HOST=pgdb
- DB_NAME=bookstore
- DB_USER=bookstore
- DB_PASS=bookstore
- EMAIL_USE_SSL=True
- EMAIL_HOST=smtp.yandex.ru
- EMAIL_HOST_USER=mymail@yandex.ru
- EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
- EMAIL_HOST_PASSWORD=password
- EMAIL_PORT=465
depends_on:
- pgdb
- redis
celery:
build: .
command: celery -A bookstore worker -l INFO
volumes:
- .:/usr/src/bookstore
depends_on:
- django
- pgdb
- redis
pgdb:
image: postgres
environment:
- POSTGRES_DB=bookstore
- POSTGRES_USER=bookstore
- POSTGRES_PASSWORD=bookstore
volumes:
- pgdata:/var/lib/postgresql/data/
redis:
image: "redis:alpine"
volumes:
pgdata:
Celery в settings.py
CELERY_BROKER_URL = os.getenv("CELERY_BROKER", "redis://redis:6379/0")
CELERY_RESULT_BACKEND = os.getenv("CELERY_BACKEND", "redis://redis:6379/0")
tasks.py (задача сельдерея)
from django.core.mail import send_mail
from bookstore import celery_app
@celery_app.task
def send_order_email(email_host_user, user_email):
send_mail(
"New order",
"You have successfully placed your order!",
email_host_user,
[user_email],
fail_silently=False
)
Вызов задачи
from .tasks import send_order_email
from django.conf import settings
def post(self, request):
...
send_order_email.delay(settings.EMAIL_HOST_USER, request.user.email)
Я попытался добавить те же переменные окружения к сервису celery в файле docker-compose, ошибка исчезла, контейнер celery выводит:
celery-1 | [2024-09-23 12:24:43,178: INFO/MainProcess] Task orders.tasks.send_order_email[4663168e-08a6-44e0-b0e1-f75c01fd37cf] received
но сообщение электронной почты все еще не отправлено.