feat: Configure all email services to use Zoho Mail
Some checks failed
CI / Frontend Lint & Type Check (push) Has been cancelled
CI / Frontend Build (push) Has been cancelled
CI / Backend Lint (push) Has been cancelled
CI / Backend Tests (push) Has been cancelled
CI / Docker Build (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
Deploy / Build & Push Images (push) Has been cancelled
Deploy / Deploy to Server (push) Has been cancelled
Deploy / Notify (push) Has been cancelled

Email Service (email_service.py):
- Updated SMTP defaults for Zoho (smtp.zoho.eu:465)
- Added SSL support (use_ssl parameter) for port 465
- Updated send_email() to handle both SSL (port 465) and STARTTLS (port 587)
- Changed default sender from noreply@pounce.ch to hello@pounce.ch
- Updated contact email to hello@pounce.ch

Configuration Files:
- env.example: Complete Zoho configuration with SSL
- env.example.txt: Updated with Zoho defaults
- README.md: Updated email setup documentation with Zoho instructions

Zoho Configuration:
- Host: smtp.zoho.eu
- Port: 465 (SSL)
- SSL: true, TLS: false
- Sender: hello@pounce.ch

Supported Email Types:
- Domain availability alerts
- Price change notifications
- Subscription confirmations
- Password reset
- Email verification
- Contact form (send + confirmation)
- Newsletter welcome
- Weekly digests
This commit is contained in:
yves.gugger
2025-12-08 15:41:05 +01:00
parent 9745d1851f
commit 225d720e8a
4 changed files with 88 additions and 55 deletions

View File

@ -407,13 +407,15 @@ This ensures identical prices on:
| `SITE_URL` | Frontend URL (for email links) | `http://localhost:3000` |
| `REQUIRE_EMAIL_VERIFICATION` | Require email verification | `false` |
| `SCHEDULER_CHECK_INTERVAL_HOURS` | Domain check interval | `24` |
| **SMTP Settings** | | |
| `SMTP_HOST` | Email server host | Optional |
| `SMTP_PORT` | Email server port | `587` |
| `SMTP_USER` | Email username | Optional |
| `SMTP_PASSWORD` | Email password | Optional |
| `SMTP_FROM_EMAIL` | Sender email | `noreply@pounce.ch` |
| `CONTACT_EMAIL` | Contact form recipient | `support@pounce.ch` |
| **SMTP Settings (Zoho)** | | |
| `SMTP_HOST` | Email server host | `smtp.zoho.eu` |
| `SMTP_PORT` | Email server port | `465` |
| `SMTP_USER` | Email username | `hello@pounce.ch` |
| `SMTP_PASSWORD` | Email password | **Required** |
| `SMTP_FROM_EMAIL` | Sender email | `hello@pounce.ch` |
| `SMTP_USE_SSL` | Use SSL (port 465) | `true` |
| `SMTP_USE_TLS` | Use STARTTLS (port 587) | `false` |
| `CONTACT_EMAIL` | Contact form recipient | `hello@pounce.ch` |
| **Stripe Settings** | | |
| `STRIPE_SECRET_KEY` | Stripe API secret key | Optional |
| `STRIPE_WEBHOOK_SECRET` | Stripe webhook secret | Optional |
@ -570,15 +572,30 @@ The scraper architecture supports multiple sources:
pounce supports automated email notifications for domain availability and price changes.
### Setup
### Setup (Zoho Mail)
Configure SMTP settings in your `.env`:
```env
# Zoho Mail Configuration (Recommended)
SMTP_HOST=smtp.zoho.eu
SMTP_PORT=465
SMTP_USER=hello@pounce.ch
SMTP_PASSWORD=your-zoho-app-password
SMTP_FROM_EMAIL=hello@pounce.ch
SMTP_FROM_NAME=pounce
SMTP_USE_TLS=false
SMTP_USE_SSL=true
CONTACT_EMAIL=hello@pounce.ch
```
Alternative providers:
```env
# Gmail (port 587, STARTTLS)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_USE_SSL=false
SMTP_USE_TLS=true
```
### Notification Types

View File

@ -32,19 +32,20 @@ from jinja2 import Template
logger = logging.getLogger(__name__)
# SMTP Configuration from environment
# SMTP Configuration from environment (Zoho defaults)
SMTP_CONFIG = {
"host": os.getenv("SMTP_HOST"),
"port": int(os.getenv("SMTP_PORT", "587")),
"username": os.getenv("SMTP_USER"),
"host": os.getenv("SMTP_HOST", "smtp.zoho.eu"),
"port": int(os.getenv("SMTP_PORT", "465")),
"username": os.getenv("SMTP_USER", "hello@pounce.ch"),
"password": os.getenv("SMTP_PASSWORD"),
"from_email": os.getenv("SMTP_FROM_EMAIL", "noreply@pounce.ch"),
"from_email": os.getenv("SMTP_FROM_EMAIL", "hello@pounce.ch"),
"from_name": os.getenv("SMTP_FROM_NAME", "pounce"),
"use_tls": os.getenv("SMTP_USE_TLS", "true").lower() == "true",
"use_tls": os.getenv("SMTP_USE_TLS", "false").lower() == "true",
"use_ssl": os.getenv("SMTP_USE_SSL", "true").lower() == "true",
}
# Contact email - where contact form submissions are sent
CONTACT_EMAIL = os.getenv("CONTACT_EMAIL", "support@pounce.ch")
CONTACT_EMAIL = os.getenv("CONTACT_EMAIL", "hello@pounce.ch")
# Base email wrapper template
@ -388,13 +389,26 @@ class EmailService:
msg.attach(MIMEText(html_content, "html"))
# Send via SMTP
async with aiosmtplib.SMTP(
hostname=SMTP_CONFIG["host"],
port=SMTP_CONFIG["port"],
use_tls=SMTP_CONFIG["use_tls"],
) as smtp:
await smtp.login(SMTP_CONFIG["username"], SMTP_CONFIG["password"])
await smtp.send_message(msg)
# Zoho uses SSL on port 465 (not STARTTLS on 587)
if SMTP_CONFIG["use_ssl"]:
# SSL connection (port 465)
async with aiosmtplib.SMTP(
hostname=SMTP_CONFIG["host"],
port=SMTP_CONFIG["port"],
use_tls=True, # Start with TLS/SSL
start_tls=False, # Don't upgrade, already encrypted
) as smtp:
await smtp.login(SMTP_CONFIG["username"], SMTP_CONFIG["password"])
await smtp.send_message(msg)
else:
# STARTTLS connection (port 587)
async with aiosmtplib.SMTP(
hostname=SMTP_CONFIG["host"],
port=SMTP_CONFIG["port"],
start_tls=SMTP_CONFIG["use_tls"],
) as smtp:
await smtp.login(SMTP_CONFIG["username"], SMTP_CONFIG["password"])
await smtp.send_message(msg)
logger.info(f"Email sent to {to_email}: {subject}")
return True

View File

@ -41,36 +41,34 @@ STRIPE_PRICE_TRADER=price_xxxxxxxxxxxxxx
STRIPE_PRICE_TYCOON=price_xxxxxxxxxxxxxx
# =================================
# SMTP Email Configuration
# SMTP Email Configuration (Zoho)
# =================================
# Gmail Example:
# Zoho Mail (recommended):
# SMTP_HOST=smtp.zoho.eu
# SMTP_PORT=465
# SMTP_USE_SSL=true
# SMTP_USE_TLS=false
#
# Gmail Example (port 587, STARTTLS):
# SMTP_HOST=smtp.gmail.com
# SMTP_PORT=587
# SMTP_USE_SSL=false
# SMTP_USE_TLS=true
# SMTP_USER=your-email@gmail.com
# SMTP_PASSWORD=your-app-password (not your Gmail password!)
#
# Mailgun Example:
# SMTP_HOST=smtp.mailgun.org
# SMTP_PORT=587
# SMTP_USER=postmaster@your-domain.com
# SMTP_PASSWORD=your-mailgun-smtp-password
#
# AWS SES Example:
# SMTP_HOST=email-smtp.eu-central-1.amazonaws.com
# SMTP_PORT=587
# SMTP_USER=your-ses-smtp-user
# SMTP_PASSWORD=your-ses-smtp-password
# SMTP_PASSWORD=your-app-password
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=noreply@pounce.ch
# Zoho Configuration (Default)
SMTP_HOST=smtp.zoho.eu
SMTP_PORT=465
SMTP_USER=hello@pounce.ch
SMTP_PASSWORD=your-zoho-app-password
SMTP_FROM_EMAIL=hello@pounce.ch
SMTP_FROM_NAME=pounce
SMTP_USE_TLS=true
SMTP_USE_TLS=false
SMTP_USE_SSL=true
# Email for contact form submissions
CONTACT_EMAIL=support@pounce.ch
CONTACT_EMAIL=hello@pounce.ch
# =================================
# Scheduler Settings

View File

@ -1,23 +1,27 @@
# Database
DATABASE_URL=sqlite+aiosqlite:///./domainwatch.db
# For PostgreSQL in production:
# DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/domainwatch
# DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/pounce
# JWT Settings
SECRET_KEY=your-super-secret-key-change-in-production
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=1440
ACCESS_TOKEN_EXPIRE_MINUTES=10080
# App Settings
APP_NAME=DomainWatch
APP_NAME=pounce
DEBUG=True
# Email Settings (optional)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=your-email@example.com
SMTP_PASSWORD=your-password
EMAIL_FROM=noreply@domainwatch.com
# Email Settings (Zoho)
SMTP_HOST=smtp.zoho.eu
SMTP_PORT=465
SMTP_USER=hello@pounce.ch
SMTP_PASSWORD=your-zoho-password
SMTP_FROM_EMAIL=hello@pounce.ch
SMTP_FROM_NAME=pounce
SMTP_USE_TLS=false
SMTP_USE_SSL=true
CONTACT_EMAIL=hello@pounce.ch
# Scheduler Settings
CHECK_HOUR=6