File indexing completed on 2026-04-27 07:41:44
0001 """Notification channels. Email (SES) first; Mattermost etc. can slot in here.
0002
0003 Channels take an Alarm + EmailConfig (+ future per-channel config) and return
0004 True on successful send, False on any failure. Failures must be logged but
0005 must not raise — a stuck channel should not block other channels or future
0006 alarms.
0007 """
0008 from __future__ import annotations
0009
0010 import logging
0011 from dataclasses import dataclass
0012
0013 import boto3
0014 from botocore.exceptions import BotoCoreError, ClientError
0015
0016
0017 log = logging.getLogger(__name__)
0018
0019
0020 @dataclass
0021 class Alarm:
0022 alarm_name: str
0023 dedupe_key: str
0024 subject: str
0025 body: str
0026 recipients: list[str]
0027 data: dict
0028
0029
0030 def send_email_ses(alarm: Alarm, *, region: str, from_addr: str) -> bool:
0031 ses = boto3.client("ses", region_name=region)
0032 try:
0033 resp = ses.send_email(
0034 Source=from_addr,
0035 Destination={"ToAddresses": alarm.recipients},
0036 Message={
0037 "Subject": {"Data": alarm.subject, "Charset": "UTF-8"},
0038 "Body": {"Text": {"Data": alarm.body, "Charset": "UTF-8"}},
0039 },
0040 )
0041 log.info("SES send OK: MessageId=%s to=%s", resp.get("MessageId"),
0042 ",".join(alarm.recipients))
0043 return True
0044 except (BotoCoreError, ClientError) as e:
0045 log.error("SES send FAILED for %s to %s: %s",
0046 alarm.dedupe_key, alarm.recipients, e)
0047 return False