feat: add email system with multi-provider support
Implements a comprehensive email system with: - Multi-provider support (SMTP, SendGrid, Mailgun, Amazon SES) - Database-stored templates with i18n (EN, FR, DE, LB) - Jinja2 template rendering with variable interpolation - Email logging for debugging and compliance - Debug mode for development (logs instead of sending) - Welcome email integration in signup flow New files: - models/database/email.py: EmailTemplate and EmailLog models - app/services/email_service.py: Provider abstraction and service - scripts/seed_email_templates.py: Template seeding script - tests/unit/services/test_email_service.py: 28 unit tests - docs/features/email-system.md: Complete documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,12 +22,14 @@ from app.exceptions import (
|
||||
ResourceNotFoundException,
|
||||
ValidationException,
|
||||
)
|
||||
from app.services.email_service import EmailService
|
||||
from app.services.stripe_service import stripe_service
|
||||
from middleware.auth import AuthManager
|
||||
from models.database.company import Company
|
||||
from models.database.subscription import (
|
||||
SubscriptionStatus,
|
||||
TierCode,
|
||||
TIER_LIMITS,
|
||||
VendorSubscription,
|
||||
)
|
||||
from models.database.user import User
|
||||
@@ -467,6 +469,62 @@ class PlatformSignupService:
|
||||
|
||||
return setup_intent.client_secret, stripe_customer_id
|
||||
|
||||
# =========================================================================
|
||||
# Welcome Email
|
||||
# =========================================================================
|
||||
|
||||
def send_welcome_email(
|
||||
self,
|
||||
db: Session,
|
||||
user: User,
|
||||
vendor: Vendor,
|
||||
tier_code: str,
|
||||
language: str = "fr",
|
||||
) -> None:
|
||||
"""
|
||||
Send welcome email to new vendor.
|
||||
|
||||
Args:
|
||||
db: Database session
|
||||
user: User who signed up
|
||||
vendor: Vendor that was created
|
||||
tier_code: Selected tier code
|
||||
language: Language for email (default: French)
|
||||
"""
|
||||
try:
|
||||
# Get tier name
|
||||
tier_enum = TierCode(tier_code)
|
||||
tier_name = TIER_LIMITS.get(tier_enum, {}).get("name", tier_code.title())
|
||||
|
||||
# Build login URL
|
||||
login_url = f"https://{settings.platform_domain}/vendor/{vendor.vendor_code}/dashboard"
|
||||
|
||||
email_service = EmailService(db)
|
||||
email_service.send_template(
|
||||
template_code="signup_welcome",
|
||||
language=language,
|
||||
to_email=user.email,
|
||||
to_name=f"{user.first_name} {user.last_name}",
|
||||
variables={
|
||||
"first_name": user.first_name,
|
||||
"company_name": vendor.name,
|
||||
"email": user.email,
|
||||
"vendor_code": vendor.vendor_code,
|
||||
"login_url": login_url,
|
||||
"trial_days": settings.stripe_trial_days,
|
||||
"tier_name": tier_name,
|
||||
},
|
||||
vendor_id=vendor.id,
|
||||
user_id=user.id,
|
||||
related_type="signup",
|
||||
)
|
||||
|
||||
logger.info(f"Welcome email sent to {user.email}")
|
||||
|
||||
except Exception as e:
|
||||
# Log error but don't fail signup
|
||||
logger.error(f"Failed to send welcome email to {user.email}: {e}")
|
||||
|
||||
# =========================================================================
|
||||
# Signup Completion
|
||||
# =========================================================================
|
||||
@@ -543,6 +601,15 @@ class PlatformSignupService:
|
||||
else datetime.now(UTC) + timedelta(days=30)
|
||||
)
|
||||
|
||||
# Get user for welcome email
|
||||
user_id = session.get("user_id")
|
||||
user = db.query(User).filter(User.id == user_id).first() if user_id else None
|
||||
|
||||
# Send welcome email
|
||||
if user and vendor:
|
||||
tier_code = session.get("tier_code", TierCode.ESSENTIAL.value)
|
||||
self.send_welcome_email(db, user, vendor, tier_code)
|
||||
|
||||
# Clean up session
|
||||
self.delete_session(session_id)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user