# backend/app/connectors/mail/outbound.py — 발송 대기 메일 실제 처리 (phase-16+) # 결재 승인(approval.executed) 시 호출. 연결된 real 계정으로만 실제 발송한다. # (mock 가짜 발송 제거: 미연결이면 failed 로 둔다.) from datetime import UTC, datetime from sqlmodel import Session from ...models import ConnectorAccount, ConnectorMode, ConnState, OutboundMail def send_outbound(session: Session, ob: OutboundMail) -> OutboundMail: """대기 메일 1건 발송. status: pending → sent(실발송) | failed.""" if ob.status != "pending": return ob acct: ConnectorAccount | None = ( session.get(ConnectorAccount, ob.connector_account_id) if ob.connector_account_id else None ) if not (acct and acct.mode == ConnectorMode.real and acct.state == ConnState.connected): ob.status = "failed" ob.error_detail = "연결된 메일 계정이 없어요" session.add(ob) session.commit() session.refresh(ob) return ob try: from ..registry import ConnectorRegistry ConnectorRegistry.get(session, acct).send_mail( session, to=ob.to, subject=ob.subject, body=ob.body, cc=ob.cc or "", bcc=ob.bcc or "", attachments=ob.attachments or [], ) ob.status = "sent" ob.sent_at = datetime.now(UTC) ob.error_detail = "" except Exception as e: # 발송 실패도 서버 안 죽음 — 결재는 이미 승인됨, 발송만 failed ob.status = "failed" ob.error_detail = f"{type(e).__name__}: {e}" session.add(ob) session.commit() session.refresh(ob) return ob