mail config 적용 .
parent
dc50fc6d8c
commit
7185cfbb72
|
|
@ -50,7 +50,14 @@ ANTHROPIC_MODEL=claude-opus-4-8
|
|||
GOOGLE_API_KEY=
|
||||
GOOGLE_MODEL=gemini-2.5-flash
|
||||
|
||||
# ── 외부 연동: 이메일 (SMTP, 실연동) ──
|
||||
# ── 외부 연동: 이메일 ──
|
||||
# 1순위: Azure Communication Services(ACS) Email (endpoint + accesskey)
|
||||
# AZURE_ACS_SENDER 는 검증된 MailFrom 주소(예: donotreply@triplepick.o2o.kr)
|
||||
AZURE_ACS_ENDPOINT=https://o2o-common-acs.korea.communication.azure.com/
|
||||
AZURE_ACS_ACCESSKEY=
|
||||
AZURE_ACS_SENDER=donotreply@triplepick.o2o.kr
|
||||
|
||||
# 2순위(폴백): SMTP — ACS 미설정 시 사용
|
||||
SMTP_HOST=
|
||||
SMTP_PORT=587
|
||||
SMTP_USER=
|
||||
|
|
|
|||
|
|
@ -89,7 +89,13 @@ class Settings(BaseSettings):
|
|||
google_api_key: str = ""
|
||||
google_model: str = "gemini-2.5-flash"
|
||||
|
||||
# ── 외부 연동: 이메일 (SMTP, 실연동) ─────────────────────
|
||||
# ── 외부 연동: 이메일 ─────────────────────────────────────
|
||||
# 1순위: Azure Communication Services(ACS) Email — endpoint + accesskey.
|
||||
# AZURE_ACS_SENDER 는 검증된 MailFrom 주소(예: donotreply@triplepick.o2o.kr).
|
||||
azure_acs_endpoint: str = ""
|
||||
azure_acs_accesskey: str = ""
|
||||
azure_acs_sender: str = ""
|
||||
# 2순위(폴백): SMTP — ACS 미설정 시 사용.
|
||||
smtp_host: str = ""
|
||||
smtp_port: int = 587
|
||||
smtp_user: str = ""
|
||||
|
|
@ -97,6 +103,12 @@ class Settings(BaseSettings):
|
|||
smtp_from: str = "TriplePick <no-reply@triplepick.app>"
|
||||
smtp_starttls: bool = True
|
||||
|
||||
@property
|
||||
def acs_configured(self) -> bool:
|
||||
return bool(
|
||||
self.azure_acs_endpoint and self.azure_acs_accesskey and self.azure_acs_sender
|
||||
)
|
||||
|
||||
@property
|
||||
def cors_origin_list(self) -> list[str]:
|
||||
if self.cors_origins.strip() == "*":
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
"""결과 이메일 발송 — SMTP 실연동 (aiosmtplib).
|
||||
"""결과 이메일 발송.
|
||||
|
||||
SMTP 설정이 없으면 EmailUnavailable 을 던진다(조용한 실패 0).
|
||||
1순위: Azure Communication Services(ACS) Email (endpoint + accesskey).
|
||||
2순위(폴백): SMTP (aiosmtplib).
|
||||
둘 다 미설정이면 EmailUnavailable 을 던진다(조용한 실패 0).
|
||||
경기 종료 후 워커가 구독자(notify=True + email)에게 개인화 결과 메일 발송.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
|
@ -17,13 +19,23 @@ class EmailUnavailable(RuntimeError):
|
|||
pass
|
||||
|
||||
|
||||
def _ensure_configured() -> None:
|
||||
if not settings.smtp_host:
|
||||
raise EmailUnavailable("SMTP_HOST 미설정")
|
||||
async def _send_acs(to: str, subject: str, html: str, text: str) -> None:
|
||||
"""Azure Communication Services Email — 키(accesskey) 인증."""
|
||||
from azure.communication.email.aio import EmailClient
|
||||
|
||||
conn = f"endpoint={settings.azure_acs_endpoint};accesskey={settings.azure_acs_accesskey}"
|
||||
message = {
|
||||
"senderAddress": settings.azure_acs_sender,
|
||||
"recipients": {"to": [{"address": to}]},
|
||||
"content": {"subject": subject, "plainText": text, "html": html},
|
||||
}
|
||||
async with EmailClient.from_connection_string(conn) as client:
|
||||
poller = await client.begin_send(message)
|
||||
await poller.result()
|
||||
log.info("email sent via ACS → %s (%s)", to, subject)
|
||||
|
||||
|
||||
async def send_email(to: str, subject: str, html: str, text: str) -> None:
|
||||
_ensure_configured()
|
||||
async def _send_smtp(to: str, subject: str, html: str, text: str) -> None:
|
||||
import aiosmtplib
|
||||
|
||||
msg = EmailMessage()
|
||||
|
|
@ -41,7 +53,20 @@ async def send_email(to: str, subject: str, html: str, text: str) -> None:
|
|||
password=settings.smtp_password or None,
|
||||
start_tls=settings.smtp_starttls,
|
||||
)
|
||||
log.info("email sent → %s (%s)", to, subject)
|
||||
log.info("email sent via SMTP → %s (%s)", to, subject)
|
||||
|
||||
|
||||
async def send_email(to: str, subject: str, html: str, text: str) -> None:
|
||||
if settings.acs_configured:
|
||||
await _send_acs(to, subject, html, text)
|
||||
return
|
||||
if settings.smtp_host:
|
||||
await _send_smtp(to, subject, html, text)
|
||||
return
|
||||
# ACS endpoint/accesskey 만 있고 sender 누락 시 명확히 안내
|
||||
if settings.azure_acs_endpoint and not settings.azure_acs_sender:
|
||||
raise EmailUnavailable("AZURE_ACS_SENDER(검증된 MailFrom 주소) 미설정")
|
||||
raise EmailUnavailable("이메일 미설정 — ACS(endpoint+accesskey+sender) 또는 SMTP 필요")
|
||||
|
||||
|
||||
def build_result_email(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ pydantic-settings==2.7.1
|
|||
email-validator==2.2.0
|
||||
apscheduler==3.11.0
|
||||
aiosmtplib==3.0.2
|
||||
azure-communication-email==1.0.0
|
||||
aiohttp==3.10.11
|
||||
httpx==0.27.2
|
||||
anthropic==0.69.0
|
||||
openai==1.59.6
|
||||
|
|
|
|||
Loading…
Reference in New Issue