You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
orquestrador/app/services/integrations/providers.py

85 lines
2.7 KiB
Python

import httpx
from app.core.settings import settings
class IntegrationProviderError(RuntimeError):
"""Erro de transporte ou configuracao em providers externos."""
class BrevoEmailProvider:
provider_name = "brevo_email"
def __init__(self) -> None:
self.base_url = str(settings.brevo_base_url or "https://api.brevo.com/v3").rstrip("/")
self.api_key = str(settings.brevo_api_key or "").strip()
self.sender_email = str(settings.brevo_sender_email or "").strip()
self.sender_name = str(settings.brevo_sender_name or "Orquestrador").strip() or "Orquestrador"
self.timeout_seconds = max(1, int(settings.brevo_request_timeout_seconds or 10))
def is_configured(self) -> bool:
return bool(self.api_key and self.sender_email)
async def send_email(
self,
*,
to_email: str,
to_name: str | None,
subject: str,
body: str,
tags: list[str] | None = None,
) -> dict:
if not self.is_configured():
raise IntegrationProviderError(
"Brevo nao configurado. Defina BREVO_API_KEY e BREVO_SENDER_EMAIL para enviar emails."
)
payload = {
"sender": {
"email": self.sender_email,
"name": self.sender_name,
},
"to": [
{
"email": str(to_email or "").strip(),
**({"name": str(to_name).strip()} if str(to_name or "").strip() else {}),
}
],
"subject": str(subject or "").strip(),
"textContent": str(body or "").strip(),
}
if tags:
payload["tags"] = [str(tag).strip() for tag in tags if str(tag).strip()]
headers = {
"accept": "application/json",
"content-type": "application/json",
"api-key": self.api_key,
}
try:
async with httpx.AsyncClient(timeout=self.timeout_seconds) as client:
response = await client.post(
f"{self.base_url}/smtp/email",
headers=headers,
json=payload,
)
except httpx.HTTPError as exc:
raise IntegrationProviderError(f"Falha ao enviar email via Brevo: {exc}") from exc
if response.status_code >= 400:
raise IntegrationProviderError(
f"Brevo retornou erro {response.status_code}: {response.text[:300]}"
)
try:
data = response.json()
except ValueError:
data = {}
return {
"provider": self.provider_name,
"message_id": data.get("messageId"),
"response": data,
}