diff --git a/server/routers/authentication.py b/server/routers/authentication.py index e612e57..75ce470 100644 --- a/server/routers/authentication.py +++ b/server/routers/authentication.py @@ -1,5 +1,6 @@ import os import html +from pathlib import Path from dotenv import load_dotenv from datetime import datetime, timedelta, timezone, UTC, date from secrets import token_urlsafe @@ -27,6 +28,7 @@ from ..utils.email_service import send_email from ..utils.audit_log import write_audit_log + EMAIL_VALIDATION_ENABLED = True ALGORITHM = 'HS256' ACCESS_TOKEN_EXPIRE_MINUTES = 30 @@ -207,7 +209,7 @@ def _send_validation_email(user: UserAccount, token: str): validation_url = f"{BACKEND_URL}/validate-email?token={token}" - logo_url = f"{BACKEND_URL}/static/images/wellai-logo.png" + logo_path = Path(__file__).resolve().parent.parent / "static" / "images" / "wellai-logo.png" email_subject = "Verify your WellAI account" @@ -236,7 +238,7 @@ def _send_validation_email(user: UserAccount, token: str): border-bottom: 1px solid #eeeeee; "> WellAI diff --git a/server/routers/users.py b/server/routers/users.py index 5251620..e39c1b1 100644 --- a/server/routers/users.py +++ b/server/routers/users.py @@ -1446,7 +1446,7 @@ def send_patient_request_email(email: str, patient: Patient, clinic: str, reques family_name = sanitizer.sanitize(patient.FamilyName) clinic_name = sanitizer.sanitize(clinic) - url = f"http://localhost:3000/accept-access-request/{sanitized_token}" + url = f"https://wellai.app/prediction/accept-access-request/{sanitized_token}" subject = "Patient Access Request for WellAI Smart Health Predictive" content = f""" diff --git a/server/utils/email_service.py b/server/utils/email_service.py index 2b2319f..4db0f88 100644 --- a/server/utils/email_service.py +++ b/server/utils/email_service.py @@ -4,16 +4,20 @@ from pathlib import Path from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +from email.mime.image import MIMEImage from dotenv import load_dotenv BASE_DIR = Path(__file__).resolve().parent.parent load_dotenv(BASE_DIR / ".env") + def send_email( recipient: str, subject: str, content: str, - content_type: str = "plainText" + content_type: str = "plainText", + inline_image_path: str = None, + inline_image_cid: str = None ): """ Sends an email using Brevo SMTP. @@ -22,6 +26,8 @@ def send_email( :param subject: Email subject. :param content: Email body. :param content_type: 'plainText' or 'html'. + :param inline_image_path: Optional path to an image embedded in the email. + :param inline_image_cid: Optional Content-ID used by the HTML image src. :return: True if sent successfully, otherwise None. """ @@ -45,16 +51,55 @@ def send_email( if not sender_email: raise ValueError("SMTP_FROM_EMAIL is not configured") - message = MIMEMultipart("alternative") + # Use mixed when an inline image is attached. + if inline_image_path: + message = MIMEMultipart("mixed") + + # Alternative part contains plain text / HTML versions. + alternative = MIMEMultipart("alternative") + message.attach(alternative) + + if content_type.lower() == "html": + alternative.attach(MIMEText(content, "html")) + else: + alternative.attach(MIMEText(content, "plain")) + + # Attach the image inline using Content-ID. + image_path = Path(inline_image_path) + + if not image_path.exists(): + raise FileNotFoundError( + f"Inline image not found: {image_path}" + ) + + with open(image_path, "rb") as image_file: + image = MIMEImage(image_file.read()) + + image.add_header( + "Content-ID", + f"<{inline_image_cid}>" + ) + image.add_header( + "Content-Disposition", + "inline", + filename=image_path.name + ) + + message.attach(image) + + else: + # Keep the existing behavior for normal emails. + message = MIMEMultipart("alternative") + + if content_type.lower() == "html": + message.attach(MIMEText(content, "html")) + else: + message.attach(MIMEText(content, "plain")) + message["Subject"] = subject message["From"] = f"{sender_name} <{sender_email}>" message["To"] = recipient - if content_type.lower() == "html": - message.attach(MIMEText(content, "html")) - else: - message.attach(MIMEText(content, "plain")) - print("===== BREVO EMAIL =====") print(f"Sending email to: {recipient}") print(f"Subject: {subject}")