Fixed static and template email files for container
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
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")
|
||||
break
|
||||
except:
|
||||
messages.error(request=request, message="Cannot Load CantorAir Logo")
|
||||
return
|
||||
|
||||
# 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}")
|
||||
|
||||
# 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"Email Sent To: {student.surname} {student.name[0].upper()}. -> {mail.to.pop()}")
|
||||
messages.success(request=request, message=f"Successfully sent {len(mails)} messages")
|
||||
|
||||
return
|
||||
@@ -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
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
admin: CantorAir2k25
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
<h1 id="site-name">
|
||||
<a href="{% url 'admin:index' %}" style="color: #0b1728;">
|
||||
<img src="{% static 'cantorair_blue.jpg' %}"
|
||||
height="60px"
|
||||
<img src="{% static 'cantorair.png' %}"
|
||||
height="70px"
|
||||
style="margin-right: 20px;"/>
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
3
note.txt
3
note.txt
@@ -3,3 +3,6 @@ OK aereo assegnato allo studente di fianco al numero della missione per PPL, inv
|
||||
OK le missioni ripetute su piu' giorni hanno una cella per giorno (non unite)
|
||||
OK lo studente vede solo le missioni della sua fase PPL->PPL ATPL-> tutto
|
||||
OK ogni richiesta ha un colore diverso che cicla con delle tinte pastello
|
||||
|
||||
|
||||
password: CantorAir2k25
|
||||
|
||||
Reference in New Issue
Block a user