diff --git a/backend/app/api/notification.py b/backend/app/api/notification.py index f521c86..04c1248 100644 --- a/backend/app/api/notification.py +++ b/backend/app/api/notification.py @@ -10,6 +10,7 @@ from ..schemas.notification import ( NotificationCreate, NotificationResponse, NotificationListResponse, NotificationMarkRead ) +from ..services.email_service import send_notification_email from .auth import get_current_user router = APIRouter(prefix="/notifications", tags=["notifications"]) @@ -29,7 +30,7 @@ def create_notification( related_id: Optional[int] = None, related_type: Optional[str] = None ) -> Notification: - """Create a new notification""" + """Create a new notification and send email""" notification = Notification( user_id=user_id, notification_type=notification_type, @@ -42,6 +43,23 @@ def create_notification( db.add(notification) db.commit() db.refresh(notification) + + # Send email notification (background thread, non-blocking) + try: + user = db.query(User).filter(User.id == user_id).first() + if user and user.email: + send_notification_email( + to_email=user.email, + notification_type=notification_type, + title=title, + message=message, + link=link, + user_name=user.name, + user_country=user.country, + ) + except Exception as e: + print(f"[WARN] Email notification failed for user {user_id}: {e}") + return notification diff --git a/backend/app/services/email_service.py b/backend/app/services/email_service.py new file mode 100644 index 0000000..c1cd87a --- /dev/null +++ b/backend/app/services/email_service.py @@ -0,0 +1,187 @@ +""" +Email Notification Service +Sends email notifications to users for important events (recommendations, shipping, payments, etc.) +Reuses existing SMTP configuration (Gmail). +""" +import smtplib +import threading +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from typing import Optional + +from ..config import get_settings + +settings = get_settings() + +# Notification types that should trigger email +EMAIL_ENABLED_TYPES = { + "vehicle_recommended", + "shipping_update", + "payment_confirmed", + "withdrawal_processed", + "inquiry_reply", + "dealer_approved", + "dealer_rejected", + "referral_reward", + "share_purchased", +} + + +def get_user_language(country: Optional[str]) -> str: + """Detect language from user's country""" + if not country: + return "en" + c = country.lower().strip() + if c in ("korea", "south korea", "kr", "한국"): + return "ko" + if c in ("mongolia", "mn", "монгол"): + return "mn" + if c in ("russia", "ru", "россия"): + return "ru" + return "en" + + +def _build_email_content( + notification_type: str, + title: str, + message: str, + link: Optional[str], + user_name: Optional[str], + language: str, +) -> tuple[str, str]: + """Build email subject and HTML body for a notification. + Returns (subject, html_body). + """ + base_url = "https://autonetsellcar.com" + full_link = f"{base_url}{link}" if link else base_url + + # Greeting by language + greetings = { + "en": f"Hi {user_name}," if user_name else "Hello,", + "ko": f"{user_name}님, 안녕하세요." if user_name else "안녕하세요,", + "mn": f"Сайн байна уу, {user_name}." if user_name else "Сайн байна уу,", + "ru": f"Здравствуйте, {user_name}." if user_name else "Здравствуйте,", + } + + button_labels = { + "en": "View Details", + "ko": "자세히 보기", + "mn": "Дэлгэрэнгүй үзэх", + "ru": "Подробнее", + } + + footers = { + "en": "You received this email because you have an account on AutonetSellCar.com", + "ko": "AutonetSellCar.com 계정이 있어 이 이메일을 받으셨습니다", + "mn": "Та AutonetSellCar.com-д бүртгэлтэй тул энэ имэйлийг хүлээн авлаа", + "ru": "Вы получили это письмо, так как у вас есть аккаунт на AutonetSellCar.com", + } + + greeting = greetings.get(language, greetings["en"]) + button_label = button_labels.get(language, button_labels["en"]) + footer = footers.get(language, footers["en"]) + + subject = f"AutonetSellCar - {title}" + + html_body = f"""\ + + +
+ +| + + |