diff --git a/cntmanage/cntmanage/settings.py b/cntmanage/cntmanage/settings.py index ee47d6b..82efb31 100644 --- a/cntmanage/cntmanage/settings.py +++ b/cntmanage/cntmanage/settings.py @@ -154,4 +154,4 @@ EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend" -EMAIL_FILE_PATH = "/tmp/app-messages" # change this to a proper location +EMAIL_FILE_PATH = "/mnt/d/Test/flightslot-mail" # change this to a proper location diff --git a/cntmanage/cntmanage/settings_prod.py b/cntmanage/cntmanage/settings_prod.py index 686b723..50d50cc 100644 --- a/cntmanage/cntmanage/settings_prod.py +++ b/cntmanage/cntmanage/settings_prod.py @@ -75,7 +75,7 @@ ROOT_URLCONF = 'cntmanage.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': ['/var/www/templates'], + 'DIRS': ['/var/www/templates', '/app/templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -139,6 +139,9 @@ USE_TZ = True # https://docs.djangoproject.com/en/5.1/howto/static-files/ STATIC_URL = "static/" STATIC_ROOT = "/var/www/static/" +STATICFILES_DIRS = [ + "/app/static/" +] STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" # Default primary key field type @@ -155,4 +158,4 @@ EMAIL_PORT = 587 EMAIL_USE_TLS = True # Use dummy backed for testing -EMAIL_BACKEND = "django.core.mail.backends..dummy.EmailBackend" +EMAIL_BACKEND = "django.core.mail.backends.dummy.EmailBackend" diff --git a/cntmanage/docker/flightslot.Dockerfile b/cntmanage/docker/flightslot.Dockerfile index 7fea967..fb8d0d6 100644 --- a/cntmanage/docker/flightslot.Dockerfile +++ b/cntmanage/docker/flightslot.Dockerfile @@ -19,11 +19,12 @@ FROM python:3.12-slim AS deploy WORKDIR /app # Copy application custom static files RUN mkdir -p static -COPY ./static/cantorair.jpg ./static -COPY ./static/cantorair_blue.jpg ./static +COPY ./static/* ./static # Copy application custom templates for admin page RUN mkdir -p /templates/admin +RUN mkdir -p /templates/email COPY ./templates/admin/* ./templates/admin/ +COPY ./templates/email/* ./templates/email/ # Copy and install application wheel package COPY --from=builder /build/dist/*.whl ./ RUN pip install --no-cache-dir *.whl diff --git a/cntmanage/flightslot/actions/send_email.py b/cntmanage/flightslot/actions/send_email.py index 06a6a35..b5569b9 100644 --- a/cntmanage/flightslot/actions/send_email.py +++ b/cntmanage/flightslot/actions/send_email.py @@ -1,6 +1,6 @@ -from django.conf import settings +from django.contrib.staticfiles import finders from django.contrib import messages -from django.core.mail import EmailMultiAlternatives +from django.core.mail import EmailMultiAlternatives, get_connection from django.http import HttpRequest from django.db.models.query import QuerySet from django.utils.safestring import SafeText @@ -11,24 +11,27 @@ from ..models.students import Student from smtplib import SMTPException from email.mime.image import MIMEImage -import os +from typing import List def send_mail_password(request: HttpRequest, queryset: QuerySet[Student]) -> None: img: MIMEImage | None = None - try: - for d in settings.STATICFILES_DIRS: - filename = os.path.join(d, "cantorair.png") - if not os.path.exists(filename): - continue - with open(filename, "rb") as f: - img = MIMEImage(f.read()) - img.add_header("Content-ID", "logo_image") - img.add_header("Content-Disposition", "inline", filename="cantorair.png") - break - except: + filename: str + candidates = finders.find("cantorair.png") + if not candidates: messages.error(request=request, message="Cannot Load CantorAir Logo") return + elif isinstance(candidates, list): + filename = candidates.pop() + else: + filename = candidates + with open(filename, "rb") as f: + img = MIMEImage(f.read()) + img.add_header("Content-ID", "logo_image") + img.add_header("Content-Disposition", "inline", filename="cantorair.png") + + # build mail list filling template + mails: List[EmailMultiAlternatives] = [] for student in queryset: if not student.user or not student.email: # skip student if has not an associated user continue @@ -52,11 +55,19 @@ def send_mail_password(request: HttpRequest, queryset: QuerySet[Student]) -> Non ) mail.attach(filename=img) mail.attach_alternative(content=html_message, mimetype="text/html") - mail.send() - except SMTPException as e: - messages.error(request=request, message=f"Send Mail error: {e.strerror}") + mails.append(mail) except Exception as e: messages.error(request=request, message=f"General Error: {e}") - else: - messages.success(request=request, message=f"Email Sent To: {student.surname} {student.name[0].upper()}. -> {mail.to.pop()}") - return + + # Open only one conenction and send mass email + try: + with get_connection() as conn: + conn.send_messages(mails) + except SMTPException as e: + messages.error(request=request, message=f"Send Mail SMTP error: {e.strerror}") + except Exception as e: + messages.error(request=request, message=f"Send Mail General error: {e}") + else: + messages.success(request=request, message=f"Successfully sent {len(mails)} messages") + + return \ No newline at end of file diff --git a/cntmanage/flightslot/admins/student_adm.py b/cntmanage/flightslot/admins/student_adm.py index 3cd85f1..0e99952 100644 --- a/cntmanage/flightslot/admins/student_adm.py +++ b/cntmanage/flightslot/admins/student_adm.py @@ -115,9 +115,9 @@ class StudentAdmin(ImportMixin, AdminConfirmMixin, AdminActionFormsMixin, admin. i, ac_types = assign_aircraft(queryset=queryset, data=data) messages.success(request, f"{i} Students updated to {ac_types}") - @admin.action(description="Send Access Credentials e-mail") @confirm_action - def send_mail(self, request: HttpRequest, queryset: QuerySet[Student], data: Any) -> None: + @admin.action(description="Send Access Credentials e-mail") + def send_mail(self, request: HttpRequest, queryset: QuerySet[Student], *args: Any) -> None: send_mail_password(request=request, queryset=queryset) # Return the initial form for import confirmations, request course to user diff --git a/cntmanage/static/password b/cntmanage/static/password deleted file mode 100644 index 520af21..0000000 --- a/cntmanage/static/password +++ /dev/null @@ -1 +0,0 @@ -admin: CantorAir2k25 diff --git a/cntmanage/templates/admin/base_site.html b/cntmanage/templates/admin/base_site.html index d4e9d88..1ed4a89 100644 --- a/cntmanage/templates/admin/base_site.html +++ b/cntmanage/templates/admin/base_site.html @@ -8,8 +8,8 @@