İlk commit: Stepstead backend (FastAPI)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
jts 2026-07-11 11:30:24 +03:00
commit ea049b8ccd
45 changed files with 6751 additions and 0 deletions

65
email_utils.py Normal file
View file

@ -0,0 +1,65 @@
import asyncio
import smtplib
import ssl
from email.message import EmailMessage
from config import settings
def _send_sync(to: str, subject: str, body: str, html: str | None = None) -> None:
msg = EmailMessage()
msg["Subject"] = subject
msg["From"] = settings.SMTP_FROM
msg["To"] = to
msg.set_content(body)
if html:
msg.add_alternative(html, subtype="html")
with smtplib.SMTP(settings.SMTP_HOST, settings.SMTP_PORT, timeout=15) as s:
s.ehlo()
if settings.SMTP_TLS:
ctx = ssl.create_default_context()
s.starttls(context=ctx)
s.ehlo()
if settings.SMTP_USER:
s.login(settings.SMTP_USER, settings.SMTP_PASSWORD)
s.send_message(msg)
async def send_email(to: str, subject: str, body: str, html: str | None = None) -> None:
await asyncio.to_thread(_send_sync, to, subject, body, html)
def verify_email_template(verify_url: str) -> tuple[str, str]:
body = (
f"Stepstead'e hoş geldin!\n\n"
f"E-postanı doğrulamak için aşağıdaki bağlantıya tıkla:\n{verify_url}\n\n"
f"Bağlantı 24 saat geçerlidir.\n"
)
html = f"""
<html><body style="font-family:sans-serif;max-width:600px;margin:auto;background:#f5f3ee;padding:24px">
<h2 style="color:#3a5a40">Stepstead E-posta Doğrulama</h2>
<p>Hoş geldin! Yolculuğa başlamak için e-postanı doğrula.</p>
<p><a href="{verify_url}" style="background:#3a5a40;color:#fff;padding:12px 24px;text-decoration:none;border-radius:6px">E-postamı Doğrula</a></p>
<p style="color:#666;font-size:12px">Buton çalışmazsa: <code>{verify_url}</code></p>
<p style="color:#666;font-size:12px">Bu bağlantı 24 saat geçerlidir.</p>
</body></html>
"""
return body, html
def password_reset_template(reset_url: str) -> tuple[str, str]:
body = (
f"Stepstead — Şifre sıfırlama talebin alındı.\n\n"
f"Yeni şifre belirlemek için:\n{reset_url}\n\n"
f"Bağlantı 1 saat geçerlidir. Talep sana ait değilse bu e-postayı yok say.\n"
)
html = f"""
<html><body style="font-family:sans-serif;max-width:600px;margin:auto;background:#f5f3ee;padding:24px">
<h2 style="color:#3a5a40">Stepstead Şifre Sıfırlama</h2>
<p>Şifre sıfırlama talebin alındı.</p>
<p><a href="{reset_url}" style="background:#3a5a40;color:#fff;padding:12px 24px;text-decoration:none;border-radius:6px">Şifremi Sıfırla</a></p>
<p style="color:#666;font-size:12px">Bağlantı 1 saat geçerlidir.</p>
</body></html>
"""
return body, html