pdf-quiz-generator/backend/app/services/email_service.py
ifedan-ed b876f13fac Initial commit: PDF Quiz Generator app
- FastAPI backend with JWT auth, roles (admin/moderator/user)
- PDF upload (up to 500MB) with streaming, PyMuPDF text extraction
- ChromaDB vectorization per page with metadata
- LiteLLM AI question extraction from PDF (not generation)
- Image extraction from PDF pages, graceful fallback
- Quiz modes: timed (countdown timer) + learning (answers shown inline)
- Page-by-page question navigation with dot navigator
- TTS endpoint using LiteLLM (Google Vertex / OpenAI voices)
- Admin dashboard: AI model management per task, user role management
- Moderator role: upload PDFs, create sections, generate quizzes
- Spaced repetition reminders via SMTP email (SM-2 intervals)
- APScheduler daily reminder jobs
- Celery + Redis for background PDF processing
- React frontend with all pages
- Docker Compose deployment (nginx + backend + celery + redis)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:04:53 +00:00

64 lines
2.1 KiB
Python

import logging
from fastapi_mail import FastMail, MessageSchema, MessageType, ConnectionConfig
from app.config import settings
logger = logging.getLogger(__name__)
def get_mail_config() -> ConnectionConfig:
return ConnectionConfig(
MAIL_USERNAME=settings.MAIL_USERNAME,
MAIL_PASSWORD=settings.MAIL_PASSWORD,
MAIL_FROM=settings.MAIL_FROM,
MAIL_PORT=settings.MAIL_PORT,
MAIL_SERVER=settings.MAIL_SERVER,
MAIL_STARTTLS=settings.MAIL_STARTTLS,
MAIL_SSL_TLS=settings.MAIL_SSL_TLS,
USE_CREDENTIALS=bool(settings.MAIL_USERNAME and settings.MAIL_PASSWORD),
)
async def send_reminder_email(
email: str,
user_name: str,
quiz_title: str,
score: float,
next_date: str,
):
"""Send a spaced-repetition reminder email."""
html = f"""
<html>
<body style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">
<h2 style="color: #2563eb;">Quiz Reminder</h2>
<p>Hi {user_name},</p>
<p>It's time to review <strong>{quiz_title}</strong>!</p>
<p>Your last score was <strong>{score:.0f}%</strong>.
{'Great progress! Keep it up.' if score >= 70 else 'Practice makes perfect — give it another try!'}</p>
<div style="background: #f3f4f6; padding: 16px; border-radius: 8px; margin: 16px 0;">
<p style="margin: 0;"><strong>Tip:</strong> Spaced repetition helps you remember more over time.
Each review strengthens your memory!</p>
</div>
<p>Log in to take the quiz again.</p>
<p style="color: #6b7280; font-size: 12px;">
You're receiving this because you have active quiz reminders.
</p>
</body>
</html>
"""
message = MessageSchema(
subject=f"Quiz Reminder: {quiz_title}",
recipients=[email],
body=html,
subtype=MessageType.html,
)
try:
conf = get_mail_config()
fm = FastMail(conf)
await fm.send_message(message)
logger.info(f"Reminder sent to {email} for quiz '{quiz_title}'")
except Exception as e:
logger.error(f"Failed to send reminder to {email}: {e}")