refactor(email): improve email service implementation and templates

- Remove strip_tags usage and use explicit fallback text for HTML emails
- Use named parameters in EmailMultiAlternatives for better clarity
- Add fail_silently=False to email.send() for explicit error handling
- Rename variables (html_content -> html_message, email_msg -> email)
- Remove action buttons from appointment email templates

These changes improve code readability and provide a clearer fallback
message for non-HTML email clients instead of relying on stripped HTML.
This commit is contained in:
saani 2025-11-23 00:27:44 +00:00
parent 1fc91d5949
commit d670baf594
3 changed files with 24 additions and 67 deletions

View File

@ -1,6 +1,5 @@
from django.core.mail import EmailMultiAlternatives from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.html import strip_tags
from django.conf import settings from django.conf import settings
class EmailService: class EmailService:
@ -16,20 +15,19 @@ class EmailService:
'admin_dashboard_url': f"{settings.FRONTEND_URL}/admin/appointments" if hasattr(settings, 'FRONTEND_URL') else '/admin/' 'admin_dashboard_url': f"{settings.FRONTEND_URL}/admin/appointments" if hasattr(settings, 'FRONTEND_URL') else '/admin/'
} }
html_content = render_to_string('emails/admin_notification.html', context) html_message = render_to_string('emails/admin_notification.html', context)
text_content = strip_tags(html_content)
admin_email = getattr(settings, 'ADMIN_EMAIL', 'hello@attunehearttherapy.com') admin_email = getattr(settings, 'ADMIN_EMAIL', 'hello@attunehearttherapy.com')
try: try:
email_msg = EmailMultiAlternatives( email = EmailMultiAlternatives(
subject, subject=subject,
text_content, body="Please view this email in an HTML-compatible client.", # Fallback text
settings.DEFAULT_FROM_EMAIL, from_email=settings.DEFAULT_FROM_EMAIL,
[admin_email] to=[admin_email],
) )
email_msg.attach_alternative(html_content, "text/html") email.attach_alternative(html_message, "text/html")
email_msg.send() email.send(fail_silently=False)
return True return True
except Exception as e: except Exception as e:
print(f"Failed to send admin notification: {e}") print(f"Failed to send admin notification: {e}")
@ -45,18 +43,17 @@ class EmailService:
'user_dashboard_url': f"{settings.FRONTEND_URL}/dashboard" if hasattr(settings, 'FRONTEND_URL') else '/dashboard/' 'user_dashboard_url': f"{settings.FRONTEND_URL}/dashboard" if hasattr(settings, 'FRONTEND_URL') else '/dashboard/'
} }
html_content = render_to_string('emails/appointment_scheduled.html', context) html_message = render_to_string('emails/appointment_scheduled.html', context)
text_content = strip_tags(html_content)
try: try:
email_msg = EmailMultiAlternatives( email = EmailMultiAlternatives(
subject, subject=subject,
text_content, body="Please view this email in an HTML-compatible client.", # Fallback text
settings.DEFAULT_FROM_EMAIL, from_email=settings.DEFAULT_FROM_EMAIL,
[appointment.email] to=[appointment.email],
) )
email_msg.attach_alternative(html_content, "text/html") email.attach_alternative(html_message, "text/html")
email_msg.send() email.send(fail_silently=False)
return True return True
except Exception as e: except Exception as e:
print(f"Failed to send scheduled notification: {e}") print(f"Failed to send scheduled notification: {e}")
@ -72,18 +69,17 @@ class EmailService:
'user_dashboard_url': f"{settings.FRONTEND_URL}/dashboard" if hasattr(settings, 'FRONTEND_URL') else '/dashboard/' 'user_dashboard_url': f"{settings.FRONTEND_URL}/dashboard" if hasattr(settings, 'FRONTEND_URL') else '/dashboard/'
} }
html_content = render_to_string('emails/appointment_rejected.html', context) html_message = render_to_string('emails/appointment_rejected.html', context)
text_content = strip_tags(html_content)
try: try:
email_msg = EmailMultiAlternatives( email = EmailMultiAlternatives(
subject, subject=subject,
text_content, body="Please view this email in an HTML-compatible client.", # Fallback text
settings.DEFAULT_FROM_EMAIL, from_email=settings.DEFAULT_FROM_EMAIL,
[appointment.email] to=[appointment.email],
) )
email_msg.attach_alternative(html_content, "text/html") email.attach_alternative(html_message, "text/html")
email_msg.send() email.send(fail_silently=False)
return True return True
except Exception as e: except Exception as e:
print(f"Failed to send rejection notification: {e}") print(f"Failed to send rejection notification: {e}")

View File

@ -287,13 +287,6 @@
<li>Check back next month for updated availability</li> <li>Check back next month for updated availability</li>
</ul> </ul>
</div> </div>
<!-- Action Button -->
<div class="action-section">
<a href="{{ user_dashboard_url }}" class="button">
Submit New Request
</a>
</div>
</div> </div>
<!-- Footer --> <!-- Footer -->

View File

@ -266,38 +266,6 @@
<div class="therapist-info">With: Nathalie (Therapist)</div> <div class="therapist-info">With: Nathalie (Therapist)</div>
</div> </div>
<div class="">
<div class="">
<div class="detail-icon"></div>
<div class="detail-label">Duration</div>
<div class="detail-value">
{{ appointment.meeting_duration_display }}
</div>
</div>
<div class="">
<div class="detail-label">Session Type</div>
<div class="detail-value">Virtual Meeting</div>
</div>
</div>
<!-- Preparation Tips -->
<div class="">
<div class="">📋 To Prepare for Your Session</div>
<ul class="">
<li>Find a quiet, comfortable space for our session</li>
<li>Test your internet connection and audio/video</li>
<li>Have any notes or questions ready</li>
<li>Join the meeting 5 minutes early to get settled</li>
<li>Ensure you're in a private, distraction-free environment</li>
</ul>
</div>
<!-- Action Button -->
<div class="action-section">
<a href="{{ user_dashboard_url }}" class="button">
View in Dashboard
</a>
</div>
</div> </div>
<!-- Footer --> <!-- Footer -->