브로드캐스트
`broadcasts.preview`, `send`, `list`, `list_all`, `iterate`, `get`, `list_recipients`, `list_all_recipients`, `iterate_recipients`, `get_recipient`, `stats`, `analytics`, `cancel`.
모든 메서드
import time from openemail import openemailfrom openemail.types import BroadcastCreate draft: BroadcastCreate = { 'audienceIds': ['aud_4c1b8e2a7d9f05c36b4e8a71'], 'from': 'Acme <[email protected]>', 'subject': '{{firstName|Hello}}, the September release is out', 'html': '<p>Hi {{firstName|there}},</p><p>Here is what changed this month.</p>', 'text': 'Hi {{firstName|there}}, here is what changed this month. Unsubscribe: {{unsubscribeUrl}}', 'tags': {'campaign': 'release-2026-09'},} reach = openemail.broadcasts.preview(draft)print(reach['recipients'], reach['unsubscribed'], reach['suppressed']) broadcast = openemail.broadcasts.send(draft) latest = openemail.broadcasts.get(broadcast['id'])while latest['status'] in ('scheduled', 'queued', 'sending'): time.sleep(5) latest = openemail.broadcasts.get(broadcast['id']) for copy in openemail.broadcasts.iterate_recipients(broadcast['id']): print(copy['email'], copy['status'], copy['opens'], copy['clicks']) bounced = openemail.broadcasts.list_recipients(broadcast['id'], filter='bounced')if bounced['items']: content = openemail.broadcasts.get_recipient(broadcast['id'], bounced['items'][0]['emailId']) print(content['subject'], content['bouncedAt']) stats = openemail.broadcasts.stats(broadcast['id'], grain='day')print(stats['totals']['opened'], stats['totals']['clicked'], stats['totals']['unsubscribed']) lately = openemail.broadcasts.stats(broadcast['id'], days=1)print(lately['window']['opened'] if lately['window'] else None) month = openemail.broadcasts.analytics(days=30)for row in month['broadcasts']: print(row['subject'], row['sent'], row['opened']) later = openemail.broadcasts.send({**draft, 'scheduledAt': 'P1D'})openemail.broadcasts.cancel(later['id']) history = openemail.broadcasts.list(audience_id=draft['audienceIds'][0])print(latest['status'], latest['counts']['sent'], len(history['items']))브로드캐스트는 하나 이상의 오디언스에 있는 모든 사람에게 메시지 하나를 사람마다 별도의 사본으로 보냅니다. 각 사본의 받는 사람은 정확히 한 명이고 cc나 bcc가 없어서 누구도 또 누구에게 갔는지 볼 수 없으며, 각 사본은 자체 msg_ ID, 이벤트, 추적, 웹훅이 있는 일반 이메일입니다. list_recipients로 각각 어떻게 되었는지와 함께 나열합니다. 브로드캐스트 자체가 기록이므로 사본은 보낸편지함에 보관되지 않습니다.
send는 곧바로 queued 상태의 브로드캐스트를, scheduledAt을 주면 scheduled 상태로 반환하며 발송은 백그라운드에서 진행됩니다. send에는 emails:send와 audiences:read, preview에는 audiences:read, list, list_all, iterate, get, list_recipients, list_all_recipients, iterate_recipients, get_recipient, stats, analytics에는 emails:read, cancel에는 emails:send가 필요합니다.
모든 send에는 Idempotency-Key가 붙습니다. idempotency_key=로 준 것이거나 SDK가 만든 것이므로, 네트워크 장애 뒤의 재시도는 두 번 보내는 대신 첫 시도가 만든 브로드캐스트로 응답합니다. preview, get, cancel과 모든 읽기는 반복해도 안전하며 재시도됩니다.
병합 필드
subject, html, text는 사람마다 그 연락처에서 채워집니다. {{firstName}}은 연락처 이름의 첫 단어, {{lastName}}은 나머지, {{name}}은 전체 이름, {{email}}은 사본이 가는 주소, {{unsubscribeUrl}}은 그 사람의 구독을 해지하는 링크입니다.
각 필드는 막대 뒤에 대체 값을 받아 연락처에 값이 없을 때 쓰므로, 이름 없이 저장된 연락처에서 {{firstName|there}}는 "there"가 됩니다. html에서는 값이 이스케이프되고, 다른 {{…}}는 쓴 그대로 남습니다.
저장된 템플릿을 보내려면 html과 text 대신 template을 넘기세요. 같은 다섯 값이 프롭으로 가지만 템플릿이 선언한 프롭만이므로, firstName을 선언한 템플릿은 그 값을 받고 선언하지 않은 템플릿은 그 때문에 거절되지 않습니다. template.props에 있는 것은 모든 사본에 똑같이 들어갑니다.
구독 해지
모든 사본에 원클릭 구독 해지 헤더가 붙어 메일 클라이언트가 자체 구독 해지 버튼을 보여 줄 수 있으며, 대형 메일함 제공자가 대량 메일에 요구하는 것이 이것입니다. {{unsubscribeUrl}}을 직접 넣지 않은 html이나 text 본문에는 링크가 든 한 줄짜리 바닥글이 붙습니다. 템플릿은 그대로 보내지므로 템플릿에 {{unsubscribeUrl}}을 넣으세요.
구독을 해지하면 그 브로드캐스트가 간 모든 오디언스에서 그 사람이 구독 해지로 표시되고, AudienceContactResource.unsubscribedAt이 audiences.list_contacts에서 이를 보여 줍니다. 그 사람은 오디언스와 주소록에 남고, 다른 오디언스는 그대로이며, 한 통씩 보내는 메일은 계속 나갑니다. 오디언스에서 뺐다가 다시 넣으면 새로 구독 상태가 됩니다.
건너뛰는 대상
브로드캐스트는 audienceIds 중 적어도 하나에 있는 모든 연락처에, 몇 개에 있든 한 번 닿습니다. 그 오디언스 중 자신이 속한 모든 곳에서 구독을 해지한 연락처와, 바운스나 신고 때문에 또는 누가 추가해서 차단 목록에 있는 주소는 건너뜁니다. send 뒤 발송이 닿기 전에 오디언스에 추가된 연락처는 받습니다.
preview는 보내지 않고 같은 수, recipients, unsubscribed, suppressed를 돌려줍니다. 아무에게도 닿지 않을 send는 422 no_recipients를 발생시킵니다.
무엇이든 기록하기 전에 발송 전체가 요금제의 월간 발송량과 대조되므로, 할당량이 감당할 수 없는 브로드캐스트는 429 send_quota_exceeded를 발생시키고 아무것도 남기지 않습니다. 사본 한 통이 한 번의 발송으로 계산됩니다.
상태와 진행
get은 사본에서 counts를 바로 읽으므로 브로드캐스트가 발송되는 동안 폴링하세요. status는 scheduled나 queued에서 sending으로 가고, 넘긴 모든 사본이 나가거나 실패하면 sent에 머뭅니다. completedAt이 마지막 사람에게 닿았다고 알린 뒤에도 사본이 기다리는 동안에는 sending입니다. failed는 브로드캐스트 전체가 멈췄다는 뜻이며, lastError가 이유를 알려 줍니다. from 주소로 더 이상 보낼 수 없거나, 템플릿을 해석할 수 없게 되었거나, 요금제가 중간에 소진되었거나, 발송 자체가 계속 실패했거나, 사본을 한 통도 기록하지 못한 경우입니다.
cancel은 scheduled, queued, sending 상태인 브로드캐스트를 멈춥니다. 더 이상 아무도 추가되지 않고 아직 기다리는 모든 사본이 취소되지만, 나간 사본은 되돌릴 수 없습니다. 모든 사본이 나간 뒤의 cancel은 409 broadcast_not_cancellable을 발생시키고, 취소된 브로드캐스트를 취소하면 그 상태 그대로 반환합니다.
누구에게 닿았는지
list_recipients는 브로드캐스트를 받은 사람들을 사본마다 한 행씩 주소순으로 담은 페이지 하나를 items, hasMore, nextCursor가 있는 dict로 반환합니다. list_all_recipients는 모든 페이지를 훑어 리스트 하나로 모으고, iterate_recipients는 사본을 하나씩 내주며 루프가 요청할 때만 다음 페이지를 가져옵니다. limit은 1에서 200까지이고 기본값은 50이며, cursor는 같은 filter 및 q와 함께 돌려보냅니다.
| filter | 남기는 항목 |
|---|---|
| pending | 아직 대기열에 있거나 예약되었거나 발송 중인 사본. |
| sent | 발송된 사본. |
| delivered | 받는 서버가 수락한 사본. |
| opened | 한 번 이상 열린 사본. |
| not_opened | 발송되었지만 한 번도 열리지 않은 사본. |
| clicked | 추적된 클릭이 한 번 이상 있는 사본. |
| bounced | 반송된 사본. |
| complained | 받는 사람이 스팸으로 신고한 사본. |
| failed | 실패했거나 취소된 사본. |
| unsubscribed | 브로드캐스트 발송 후 수신 거부한 사람. |
BROADCAST_RECIPIENT_FILTERS가 각 필터의 이름을 정하고, q는 주소와 이름을 대소문자 구분 없이 검색합니다. 열람과 클릭에는 이미지 프록시와 링크 스캐너가 만든 것이 빠지며, 추적을 끄고 보낸 브로드캐스트에서는 0으로 유지됩니다.
get_recipient(id, email_id)는 사본 하나를 반환합니다. 같은 행에 그 사람이 받은 그대로의 subject, html, text가 병합 필드가 채워지고 그 사람만의 수신 거부 링크가 붙은 상태로 더해집니다. HTML은 열람 및 클릭 추적을 넣기 전의 것입니다. 이 브로드캐스트의 사본이 아닌 email_id는 404 recipient_not_found를, 알 수 없는 브로드캐스트는 404 broadcast_not_found를 발생시킵니다.
stats는 합계와 시계열을 반환합니다. totals는 sent, delivered, bounced, complained, failed 사본 수와 아직 대기 중인 사본을 나타내는 pending, 그리고 opened, clicked, unsubscribed한 사람 수를 세며, opens와 clicks는 이벤트 수입니다. series는 희소하며 오래된 순으로, 무언가 일어난 grain(minute, hour 또는 day, 기본값 hour)마다 버킷이 하나씩 있고, UTC 동쪽으로 offset_minutes만큼의 오프셋으로 나뉩니다. 각 사람은 그 일이 처음 일어난 시점에 한 번만 세어지므로, 합하면 합계와 같습니다.
특정 주소나 도메인으로 제한된 키는 자신이 가진 주소나 도메인에서 보낸 브로드캐스트에만 닿습니다. list, list_all, iterate는 나머지를 빼고, get, 수신자 메서드, stats, cancel은 그것들에 대해 404 broadcast_not_found를 발생시킵니다.
응답: BroadcastResource
get과 cancel은 각각 이것 하나를 반환하고, send는 SentBroadcastResource를 반환합니다. 이는 같은 필드에 replayed를 더한 것으로, 같은 멱등성 키로 이전에 한 호출이 만든 브로드캐스트가 응답으로 돌아왔을 때 True입니다. list는 이것들의 페이지를 items, hasMore, nextCursor가 있는 dict로 최신순으로 반환하고, list_all과 iterate는 모든 페이지를 훑습니다. preview는 audienceIds, recipients, unsubscribed, suppressed가 있는 BroadcastPreviewResource를 반환합니다. list_recipients는 BroadcastRecipientResource 행의 페이지를, get_recipient는 BroadcastRecipientContentResource를, stats는 BroadcastStatsResource를 반환합니다.
idstr- 영구적인 핸들로, `brd_` 뒤에 16진수 24자가 붙습니다.
statusBroadcastStatus- `scheduled`, `queued`, `sending`, `sent`, `cancelled`, `failed` 중 하나. `BROADCAST_STATUSES`가 각각에 이름을 붙입니다.
modeApiKeyMode- 만든 키에 따라 `live` 또는 `test`. 테스트 브로드캐스트의 사본은 보냄으로 표시되고 아무에게도 전달되지 않습니다.
sourceEmailSource | str- 시작된 곳: 키는 `api`, 연결된 앱은 `oauth`, 앱은 `composer`, 어시스턴트는 `mcp`.
audienceIdslist[str]- 보낸 오디언스, 각각 한 번씩.
fromstr- 모든 사본을 보내는 주소.
subjectstr- 병합 필드까지 쓴 그대로의 제목. 템플릿이 제목을 제공하면 비어 있습니다.
countsBroadcastCounts- `recipients`는 `send` 때 잡은 추정치입니다. `created`는 기록된 사본 수, `skipped`는 그때 주소가 차단되어 있어 건너뛴 사람 수, `failedToQueue`는 사본을 기록하지 못한 사람 수입니다. `queued`, `sending`, `sent`, `failed`, `cancelled`는 각 사본이 지금 있는 상태별 수입니다.
lastErrorstr | None- 브로드캐스트가 실패한 이유, 또는 기록하지 못한 가장 최근 사본과 그 이유. 문제가 없는 동안은 `None`입니다.
scheduledAtstr | None- ISO-8601 UTC, 발송이 시작될 예정 시각. 바로 보낸 브로드캐스트는 `None`입니다.
startedAtstr | None- ISO-8601 UTC, 발송이 처음 사람들에게 닿은 시각.
completedAtstr | None- ISO-8601 UTC, 마지막 사람에게 닿은 시각. 그 뒤에도 사본이 나가기를 기다릴 수 있습니다.
cancelledAtstr | None- ISO-8601 UTC, `cancel`이 멈춘 시각.
createdAtstr- ISO-8601 UTC, `send`를 호출한 시각. 목록 순서를 정합니다.
updatedAtstr- ISO-8601 UTC, 발송이 진행되면서 갱신됩니다.
응답: BroadcastRecipientResource
list_recipients, list_all_recipients, iterate_recipients의 각 행입니다. get_recipient가 반환하는 BroadcastRecipientContentResource는 여기에 subject, html, text를 더합니다.
emailIdstr- 이 사람의 사본의 `msg_` ID. `get_recipient`는 내용과 함께 읽고 `emails.get`은 보낸 이메일로 읽습니다.
contactIdstr | None- 사본을 받은 연락처. 그 뒤 연락처가 삭제되었으면 `None`입니다.
emailstr- 사본이 간 주소.
namestr | None- 연락처에 있는 이름.
statusstr- 사본의 상태: `queued`, `scheduled`, `sending`, `sent`, `failed` 또는 `cancelled`.
sentAtstr | None- ISO-8601 UTC, 사본이 발송된 시각.
deliveredAtstr | None- ISO-8601 UTC, 받는 서버가 수락한 시각으로, 첫 `email.delivered`입니다.
bouncedAtstr | None- ISO-8601 UTC, 반송된 시각으로, 첫 `email.bounced`입니다.
complainedAtstr | None- ISO-8601 UTC, 받는 사람이 스팸으로 신고한 시각으로, 첫 `email.complained`입니다.
failurestr | None- 사본이 실패했다면 그 이유.
opensint- 기록된 열람 수로, 이미지 프록시와 스캐너가 만든 것은 빠집니다. 추적이 꺼져 있었으면 0입니다.
firstOpenAtstr | None- ISO-8601 UTC, 첫 열람.
clicksint- 추적 링크에서 기록된 클릭 수로, 스캐너는 빠집니다.
firstClickAtstr | None- ISO-8601 UTC, 첫 클릭.
unsubscribedAtstr | None- ISO-8601 UTC, 발송 후 이 사람이 브로드캐스트의 오디언스 중 하나에서 링크를 통하거나 다른 방법으로 수신 거부한 시각.
레퍼런스
broadcasts.preview()전체 레퍼런스broadcasts.send()전체 레퍼런스broadcasts.list()전체 레퍼런스broadcasts.list_all()전체 레퍼런스broadcasts.iterate()전체 레퍼런스broadcasts.get()전체 레퍼런스broadcasts.list_recipients()전체 레퍼런스broadcasts.list_all_recipients()전체 레퍼런스broadcasts.iterate_recipients()전체 레퍼런스broadcasts.get_recipient()전체 레퍼런스broadcasts.stats()전체 레퍼런스broadcasts.analytics()전체 레퍼런스broadcasts.cancel()전체 레퍼런스