92 lines
2.8 KiB
Python
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') |