Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions backend/services/email_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from typing import Optional, Dict, Any
import os
import logging
from datetime import datetime
from dotenv import load_dotenv

load_dotenv()
Expand Down Expand Up @@ -50,6 +51,16 @@ def _load_template(self, template_name: str) -> Template:
except Exception as e:
logger.error(f"Failed to load template {template_name}: {str(e)}")
raise

def _format_datetime_for_email(self, raw_value: Any) -> str:
if not raw_value:
return "N/A"

try:
parsed = datetime.fromisoformat(str(raw_value).replace("Z", "+00:00"))
return parsed.strftime("%d/%m/%Y à %H:%M")
except ValueError:
return str(raw_value)

def send_email(self, to_email: str, subject: str, html_content: str, text_content: Optional[str] = None) -> bool:
if not all([self.smtp_username, self.smtp_password]):
Expand All @@ -73,14 +84,16 @@ def send_email(self, to_email: str, subject: str, html_content: str, text_conten

def send_event_approval_email(self, event_data: Dict[str, Any], approve_url: str, reject_url: str) -> bool:
admin_email = os.getenv("ADMIN_EMAIL", "admin@crealab.com")
formatted_start = self._format_datetime_for_email(event_data.get('startStr') or event_data.get('start'))
formatted_end = self._format_datetime_for_email(event_data.get('endStr') or event_data.get('end'))

html_template = self._load_template('event_approval.html')

html_content = html_template.render(
event_title=event_data.get('title', 'N/A'),
event_user=event_data.get('user', 'N/A'),
event_start=event_data.get('startStr', 'N/A'),
event_end=event_data.get('endStr', 'N/A'),
event_start=formatted_start,
event_end=formatted_end,
event_duration=event_data.get('duration', 'N/A'),
approve_url=approve_url,
reject_url=reject_url
Expand All @@ -92,12 +105,14 @@ def send_event_approval_email(self, event_data: Dict[str, Any], approve_url: str

def send_event_acceptance_email(self, event_data: Dict[str, Any], user_email: str, user_name: str) -> bool:
html_template = self._load_template('event_accepted.html')
formatted_start = self._format_datetime_for_email(event_data.get('startStr') or event_data.get('start'))
formatted_end = self._format_datetime_for_email(event_data.get('endStr') or event_data.get('end'))

html_content = html_template.render(
user_name=user_name,
event_title=event_data.get('title', 'N/A'),
event_start=event_data.get('startStr', 'N/A'),
event_end=event_data.get('endStr', 'N/A'),
event_start=formatted_start,
event_end=formatted_end,
event_duration=event_data.get('duration', 'N/A')
)

Expand All @@ -107,12 +122,14 @@ def send_event_acceptance_email(self, event_data: Dict[str, Any], user_email: st

def send_event_rejection_email(self, event_data: Dict[str, Any], user_email: str, user_name: str) -> bool:
html_template = self._load_template('event_rejected.html')
formatted_start = self._format_datetime_for_email(event_data.get('startStr') or event_data.get('start'))
formatted_end = self._format_datetime_for_email(event_data.get('endStr') or event_data.get('end'))

html_content = html_template.render(
user_name=user_name,
event_title=event_data.get('title', 'N/A'),
event_start=event_data.get('startStr', 'N/A'),
event_end=event_data.get('endStr', 'N/A'),
event_start=formatted_start,
event_end=formatted_end,
event_duration=event_data.get('duration', 'N/A')
)

Expand Down
50 changes: 26 additions & 24 deletions backend/templates/event_accepted.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html lang="fr">

<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
Expand All @@ -13,60 +14,60 @@
color: #333333;
background-color: #f4f4f4;
}

.email-container {
max-width: 600px;
margin: 20px auto;
background-color: #ffffff;
border: 1px solid #dddddd;
}

.header {
background-color: #059669;
padding: 25px;
text-align: center;
}

.header h1 {
margin: 0;
color: #ffffff;
font-size: 20px;
font-weight: normal;
}

.content {
padding: 30px;
}

.content p {
margin: 0 0 16px 0;
color: #555555;
}

.event-info {
background-color: #f0fdf4;
border: 1px solid #bbf7d0;
border-left: 4px solid #059669;
padding: 20px;
margin: 20px 0;
}

.event-info h2 {
margin: 0 0 15px 0;
color: #047857;
font-size: 18px;
font-weight: bold;
}

.event-info p {
margin: 5px 0;
color: #374151;
}

.event-info strong {
color: #065f46;
}

.success-message {
background-color: #d1fae5;
border: 1px solid #6ee7b7;
Expand All @@ -77,7 +78,7 @@
text-align: center;
border-radius: 4px;
}

.info-note {
background-color: #fef3c7;
border: 1px solid #f59e0b;
Expand All @@ -86,7 +87,7 @@
color: #92400e;
font-size: 12px;
}

.footer {
background-color: #f9fafb;
padding: 20px;
Expand All @@ -95,54 +96,55 @@
color: #6b7280;
font-size: 12px;
}

.footer p {
margin: 3px 0;
}

@media only screen and (max-width: 600px) {
.email-container {
margin: 10px;
border: none;
}

.content {
padding: 20px;
}
}
</style>
</head>

<body>
<div class="email-container">
<div class="header">
<h1>✅ Événement Approuvé</h1>
</div>

<div class="content">
<p>Bonjour {{ user_name }},</p>
<p>Bonne nouvelle ! Votre événement a été <strong>approuvé</strong> par l'administration CreaLab.</p>
<p>Bonne nouvelle ! Votre événement a été <strong>approuvé</strong>.</p>

<div class="success-message">
Votre événement est maintenant confirmé et visible dans le calendrier !
Votre événement est confirmé et visible dans le calendrier !
</div>

<div class="event-info">
<h2>{{ event_title }}</h2>
<p><strong>Début :</strong> {{ event_start }}</p>
<p><strong>Fin :</strong> {{ event_end }}</p>
<p><strong>Durée :</strong> {{ event_duration }}</p>
</div>

<p>Votre événement est maintenant visible pour tous les utilisateurs du CreaLab. Vous pouvez accéder au calendrier pour voir votre événement confirmé.</p>


<div class="info-note">
Si vous avez des questions concernant votre événement, n'hésitez pas à contacter l'administration.
Si vous avez des questions concernant votre événement, n'hésitez pas à contacter le bureau coding (302).
</div>
</div>

<div class="footer">
<p><strong>Gestion des Événements CreaLab</strong></p>
<p>Ceci est une notification automatisée. Veuillez ne pas répondre à cet email.</p>
</div>
</div>
</body>

</html>
Loading
Loading