Files
notify/src/presentation/messaging/code.py
2026-07-01 18:47:26 +03:00

92 lines
2.8 KiB
Python

from fastapi import Depends
from faststream.rabbit.fastapi import RabbitRouter, RabbitMessage
from src.infrastructure.config import settings
from src.infrastructure.logger import logger
from src.infrastructure.mail import TemplateRenderer, get_email_sender, get_renderer
from src.infrastructure.mail.assets import EXA_LOGO_CID, get_exa_logo_png
from src.infrastructure.mail.sender import EmailSender
from datetime import datetime
from typing import Literal, Optional
from pydantic import BaseModel, EmailStr, Field
from src.infrastructure.rabbit.broker import email_code_queue
from src.infrastructure.metrics import observe_notify
code_broker = RabbitRouter(settings.RABBIT_URL)
class Metadata(BaseModel):
trace_id: Optional[str] = None
source: str
timestamp: datetime
message_id: str
class Payload(BaseModel):
email: EmailStr
code: str = Field(min_length=1, max_length=64)
ttl_seconds: int = Field(gt=0, lt=24 * 3600)
class LoginCodeCreated(BaseModel):
event: Literal['login', 'registration', 'bank_details_update', 'change_password', 'forgot_password']
payload: Payload
metadata: Metadata
@code_broker.subscriber(email_code_queue)
async def consume_email_code(
msg_body: LoginCodeCreated,
message: RabbitMessage,
sender: EmailSender = Depends(get_email_sender),
renderer: TemplateRenderer = Depends(get_renderer),
):
trace_id = (
(message.headers or {}).get("trace_id")
or message.correlation_id
or msg_body.metadata.trace_id
)
logger.info(
f"received event={msg_body.event} "
f"email={msg_body.payload.email} "
f"ttl={msg_body.payload.ttl_seconds} "
f"trace_id={trace_id}"
)
logo_png = get_exa_logo_png()
logo_src = f'cid:{EXA_LOGO_CID}' if logo_png else ''
html = renderer.render(
'email_code.html',
subject='Экса — код подтверждения',
code=msg_body.payload.code,
ttl_minutes=msg_body.payload.ttl_seconds // 60,
brand='Экса',
logo_src=logo_src,
trace_id=trace_id,
year=datetime.now().year,
)
text = renderer.render(
'email_code.txt',
code=msg_body.payload.code,
ttl_minutes=msg_body.payload.ttl_seconds // 60,
brand='Экса',
trace_id=trace_id,
year=datetime.now().year,
)
observe_notify('email', msg_body.event, 'received')
try:
await sender.send(
to=msg_body.payload.email,
subject='Экса — код подтверждения',
body=html,
plain=text,
inline_png=(EXA_LOGO_CID, logo_png) if logo_png else None,
)
except Exception:
observe_notify('email', msg_body.event, 'error')
raise
observe_notify('email', msg_body.event, 'sent')