연락처, 오디언스, 브로드캐스트
주소록, 오디언스, 브로드캐스트, 발송 차단 목록을 위한 모든 명령과 실제 예제.
서로 어떻게 맞물리는지
네 네임스페이스가 메일을 보내는 사람들을 다룹니다. 연락처는 워크스페이스 주소록이고, 오디언스는 이름이 붙은 연락처 목록이며, 브로드캐스트는 몇몇 오디언스의 모두에게 메시지 하나를 보내고, 발송 차단 목록에는 워크스페이스가 보내지 않을 주소가 있습니다. 각 명령은 SDK 메서드 하나를 호출하므로, SDK 페이지에서 같은 호출을 더 깊이 설명합니다.
- 연락처에는 ID가 없습니다. 모든
contacts명령이 받는 키는 주소이며, 앞뒤 공백을 없애고 소문자로 바꾸므로[email protected]과[email protected]은 같은 연락처입니다. 오디언스에는aud_ID, 브로드캐스트에는brd_ID가 있고, 발송 차단 항목에는suppressions list가 출력하는 ID가 있습니다. - 모든 연락처는 존재하는 동안 기본 오디언스에 속합니다. 이 오디언스는 삭제하거나 비우거나 줄일 수 없으며,
builtin이default입니다. - 주소록은 워크스페이스에 속하므로, 모든 멤버와 모든 키가 같은 주소록을 읽고 씁니다.
- 각 네임스페이스는
openemail contact get처럼 단수형으로도 응답하며, 흔히 쓰는 별칭ls,show,new,edit,rm도 됩니다. 동사가add와remove인suppressions에서는new가add로,rm이remove로 이어집니다.
openemail <namespace> <verb> --help는 모든 플래그의 타입, 범위, 엔드포인트, 명령의 반환값을 보여 줍니다. --json을 붙이면 같은 페이지를 데이터로 받습니다.
연락처
워크스페이스 주소록입니다. 멤버가 앱의 작성기에서 메일을 보낸 사람들과 직접 저장한 사람들이 들어 있습니다. 도착하는 메일은 아무도 추가하지 않으며, API나 CLI를 통한 보내기도 마찬가지입니다.
| 명령 | 하는 일 |
|---|---|
| openemail contacts list | 저장된 연락처 한 페이지, 최근에 메일을 주고받은 순. --source는 manual 또는 auto 연락처만 남기고, --q는 이름과 주소를 검색합니다 |
| openemail contacts get <email> | 연락처 하나와 그 연락처가 속한 모든 오디언스 |
| openemail contacts create --email <value> | --name, --notes, --audience-ids와 함께 새 연락처를 저장합니다. 이미 주소록에 있는 주소는 409 contact_exists로 거부됩니다 |
| openemail contacts update <email> | --name이나 --notes를 바꾸며, null은 값을 지웁니다. 주소 자체는 바꿀 수 없습니다 |
| openemail contacts delete <email> | 연락처를 메모, 사진, 소속과 함께 삭제하고, 작성기가 다시 기록하지 않도록 주소를 숨깁니다 |
| openemail contacts set-audiences <email> --audience-ids <a,b> | 연락처가 속한 오디언스를 정확히 이 목록으로 맞춥니다. 기본 오디언스는 항상 유지됩니다 |
| openemail contacts list-people | 연락처 페이지의 모든 사람: 저장된 연락처와, threads:read가 있으면 메일에서 본 모든 주소를 스레드 수와 함께 보여 줍니다. --sort, --q, --email, --blocked로 좁힙니다 |
| openemail contacts save <email> | 주소를 저장하거나, 보내기에서 기록된 주소를 유지하거나, 삭제된 주소를 되살립니다. 주소가 어떤 상태든 오류가 나지 않습니다 |
| openemail contacts delete-many <emails...> | 호출 한 번으로 주소 1개에서 200개까지 삭제하고 숨깁니다 |
| openemail contacts set-photo <email> <data> | 파일에서, 또는 -로 stdin에서 사진을 업로드합니다. 최대 5 MB의 PNG, JPEG, WebP, GIF입니다 |
| openemail contacts remove-photo <email> | 사진을 떼고 저장된 이미지를 삭제합니다 |
| openemail contacts block <email> | 주소를 워크스페이스 차단 목록에 올려 그 주소에서 오는 메일을 거부합니다. 플러스 태그는 버립니다 |
| openemail contacts unblock <email> | 주소를 차단하는 차단 목록 규칙을 도메인 전체 규칙까지 포함해 모두 뺍니다 |
| openemail contacts list-threads <email> | 모든 폴더에서 그 주소가 작성했거나 그 주소로 작성된 스레드. --q로 그 안을 검색합니다 |
| openemail contacts activity <email> | 기간 동안 그 주소에서 받고 그 주소로 보낸 메일. --minutes로 달리 정하지 않으면 90일이며, 답장을 기다리는 스레드와 양방향 답장 시간의 중앙값이 함께 나옵니다 |
오디언스
이름이 붙은 연락처 목록이며, 워크스페이스에 최대 100개까지 둘 수 있습니다. 주소가 오디언스에 들어가려면 먼저 연락처여야 합니다. 예외는 import-contacts로, 새 주소를 저장하면서 넣습니다.
| 명령 | 하는 일 |
|---|---|
| openemail audiences list | 오디언스 한 페이지. 기본 오디언스가 먼저, 나머지는 최신순이며 각각 contactCount가 함께 나옵니다 |
| openemail audiences growth | 기간 동안 오디언스가 어떻게 늘었는지. --days나 --minutes로 달리 정하지 않으면 30일이며, 구간별 가입과 구독 해지, 그리고 합계입니다 |
| openemail audiences get <id> | 오디언스 하나와 새로 센 contactCount |
| openemail audiences create --name <value> | 빈 오디언스를 만들며, --description은 선택 사항입니다. 이름은 고유하지 않아도 됩니다 |
| openemail audiences update <id> | --name이나 --description을 바꿉니다. 소속은 건드리지 않습니다 |
| openemail audiences delete <id> | 오디언스를 삭제하고 연락처는 유지합니다. 기본 오디언스는 삭제할 수 없습니다 |
| openemail audiences empty <id> | 모든 연락처를 빼고 오디언스는 ID, 이름, 설명과 함께 유지합니다 |
| openemail audiences list-contacts <id> | 오디언스의 연락처 한 페이지. 각 연락처가 언제 들어왔는지와 구독을 해지했는지가 함께 나옵니다. --sort, --q, --source, --statuses로 좁힙니다 |
| openemail audiences add-contact <id> --email <value> | 기존 연락처 하나를 오디언스에 넣습니다. 이미 있는 사람을 넣으면 아무것도 바뀌지 않습니다 |
| openemail audiences remove-contact <id> <email> | 연락처 하나를 뺍니다. 오디언스에 없는 연락처는 404입니다 |
| openemail audiences add-contacts <id> --emails <a,b> | 기존 연락처를 최대 200개까지 넣고, 연락처가 아닌 주소는 missing에 보고합니다 |
| openemail audiences remove-contacts <id> --emails <a,b> | 연락처를 최대 200개까지 빼고, 오디언스에 없던 것을 보고합니다 |
| openemail audiences import-contacts <id> --contacts <json|@file|-> | { email, name } 행을 최대 500개까지 가져오며, 아직 연락처가 아닌 주소는 저장합니다 |
브로드캐스트
최대 10개 오디언스의 모두에게 보내는 메시지 하나로, 사람마다 별도 사본으로 보내며 병합 필드를 채우고 수신 거부 링크를 붙입니다. 각 사본은 자체 msg_ ID, 이벤트, 웹훅이 있는 일반 이메일입니다.
| 명령 | 하는 일 |
|---|---|
| openemail broadcasts preview --audience-ids <a,b> | 이 오디언스로 보내는 브로드캐스트가 누구에게 닿고, 구독 해지나 발송 차단으로 누구를 건너뛸지 셉니다. 아무것도 보내지 않습니다 |
| openemail broadcasts send --audience-ids <a,b> --from <value> | --subject와 --html 또는 --text, 또는 저장된 --template으로 지금이나 --scheduled-at에 보냅니다 |
| openemail broadcasts list | 브로드캐스트 한 페이지, 최신순이며 실시간 수치가 함께 나옵니다. --audience-id는 그 오디언스로 보낸 것만 남깁니다 |
| openemail broadcasts get <id> | 브로드캐스트 하나와 그 상태, 실시간 수치. 보내는 동안 폴링할 명령입니다 |
| openemail broadcasts stats <id> | 배달, 반송, 열람, 클릭, 구독 해지의 합계와 --grain 구간별 시계열. 지정하지 않으면 한 시간 단위입니다 |
| openemail broadcasts list-recipients <id> | 각 사본이 누구에게 갔고 어떻게 되었는지. --filter는 bounced나 not_opened 같은 한 그룹만 남깁니다 |
| openemail broadcasts get-recipient <id> <email-id> | 한 사람의 사본. 그 사람이 받은 그대로의 제목, HTML, 텍스트가 나옵니다 |
| openemail broadcasts cancel <id> | 예약되었거나 대기 중이거나 아직 보내는 중인 브로드캐스트를 멈춥니다. 이미 나간 사본은 회수할 수 없습니다 |
발송 차단
이 워크스페이스가 보내지 않을 주소입니다. 하드 바운스와 스팸 신고가 일어날 때 기록되며, 직접 추가한 주소도 있습니다. 이런 주소로 보내면 무엇이든 나가기 전에 그 받는 사람에 대해 거부됩니다.
| 명령 | 하는 일 |
|---|---|
| openemail suppressions list | 목록 한 페이지, 최신순. --reason은 bounce, complaint, manual만 남기고, --q는 검색합니다 |
| openemail suppressions get <id> | 행 하나: 주소, 사유, 반송이나 신고에 담긴 세부 내용, 그리고 제거할 수 있는지 여부 |
| openemail suppressions add --email <value> | 주소로 보내기를 멈춥니다. 이미 있는 주소를 추가하면 그 주소의 행을 반환합니다 |
| openemail suppressions remove <id> | 주소로 메일을 다시 허용합니다. 하드 바운스는 제거할 수 없습니다 |
발송 차단 목록과 차단 목록은 서로 다른 목록입니다. suppressions add는 주소로 나가는 메일을 멈추고, contacts block은 그 주소에서 들어오는 메일을 거부합니다.
범위
대부분의 명령에는 자기 네임스페이스의 읽기 또는 쓰기 범위가 필요합니다. 다른 것을 읽거나 바꾸기 때문에 다른 범위가 필요한 명령도 몇 개 있습니다:
| 범위 | 명령 |
|---|---|
| contacts:read | contacts list, get, list-people |
| contacts:write | contacts create, update, delete, save, delete-many, set-photo, remove-photo, 그리고 audiences:write와 함께 audiences import-contacts |
| audiences:read | audiences list, growth, get, list-contacts, 그리고 broadcasts preview. 그래서 보낼 수 없는 키도 인원수는 보여 줄 수 있습니다 |
| audiences:write | 나머지 모든 audiences 명령과 contacts set-audiences. contacts create --audience-ids에는 contacts:write와 함께 필요합니다 |
| threads:read | contacts list-threads, activity, 그리고 list-people의 메일에서 본 주소 |
| settings:read | suppressions list, get |
| settings:write | suppressions add, remove, 그리고 contacts block, unblock |
| emails:read | broadcasts list, get, stats, list-recipients, get-recipient |
| emails:send | audiences:read도 필요한 broadcasts send, 그리고 broadcasts cancel |
- 특정 주소나 도메인으로 제한된 키도 다른 모든 키와 같은 주소록을 읽고 씁니다. 그런 키는 자신이 가진 주소나 도메인에서 보낸 브로드캐스트만 보고,
list-people에서는 저장된 연락처만 받으며,contacts list-threads,activity,block,unblock과suppressions add,remove에서는 422capability_unsupported로 거부됩니다. - 일부 주소에만 닿는 멤버의 브라우저 로그인은 모든
contacts,audiences,broadcasts명령에서 422capability_unsupported로 거부됩니다.suppressions add는 워크스페이스 소유자가 아닌 사람의 브라우저 로그인을 거부합니다.
실제 예제
파일로 오디언스를 만든 뒤, 그 오디언스로 보내는 브로드캐스트가 누구에게 닿을지 셉니다. import-contacts는 아직 연락처가 아닌 주소를 저장하며, 다시 실행해도 아무것도 두 번 만들거나 넣지 않습니다.
[ { "email": "[email protected]", "name": "Ada Lovelace" }, { "email": "[email protected]", "name": "Grace Hopper" }, { "email": "[email protected]" }]AUDIENCE=$(openemail audiences create --name 'Product updates' --json | jq -r .id)openemail audiences import-contacts "$AUDIENCE" --contacts @contacts.jsonopenemail broadcasts preview --audience-ids "$AUDIENCE"요청을 출력하고 아무것도 보내지 않는 --dry-run으로 브로드캐스트를 확인한 뒤 보냅니다. 브로드캐스트는 즉시 만들어지고 백그라운드에서 보내지므로, get을 폴링해 진행을 따라가세요. 이 본문에는 {{unsubscribeUrl}}이 없으므로 모든 사본에 한 줄짜리 수신 거부 푸터가 붙습니다.
{ "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>", "scheduledAt": "2026-10-01T09:00:00Z"}openemail broadcasts send --data @broadcast.json --dry-runBROADCAST=$(openemail broadcasts send --data @broadcast.json --yes --json | jq -r .id)openemail broadcasts get "$BROADCAST"openemail broadcasts stats "$BROADCAST" --grain day브로드캐스트가 누구에게 닿지 않았는지 봅니다. --ndjson은 한 줄에 받는 사람 하나를, --all --json은 모든 페이지를 담은 문서 하나를 출력합니다.
openemail broadcasts list-recipients brd_5a8c1e3f7b2d94a06c8e1f3b --filter bounced --ndjson | jq -r .emailopenemail broadcasts list-recipients brd_5a8c1e3f7b2d94a06c8e1f3b --filter not_opened --all --json | jq ".items | length"openemail suppressions list --reason bounce --all --max 50한 오디언스의 구독 중인 멤버를 다른 오디언스로 복사합니다. jq가 스트림을 add-contacts가 받는 본문으로 바꾸고, --data -가 stdin에서 읽습니다. --max 200은 호출 한 번이 받는 주소 200개로 맞춥니다.
openemail audiences list-contacts aud_9f2c4b7e1a0d63d84c5f2e7b --statuses subscribed --max 200 --ndjson \ | jq -s '{ emails: map(.email) }' \ | openemail audiences add-contacts aud_1c4e7a9b2d0f36e85a7c1b4d --data -작성기가 한 도메인에서 기록한 연락처를 모두 삭제합니다. delete-many는 호출마다 주소를 최대 200개 받으므로, 더 긴 목록은 xargs -n 200으로 나눕니다. 되돌릴 수 없으니 먼저 --dry-run으로 묶음을 확인하세요.
openemail contacts list --source auto --all --ndjson \ | jq -r 'select(.email | endswith("@old-vendor.example")) | .email' > leaving.txtxargs -n 200 openemail contacts delete-many --dry-run < leaving.txtxargs -n 200 openemail contacts delete-many --yes < leaving.txt주소로 보내기를 멈추고, 주소를 다시 허용하고, 보낸 사람을 차단합니다. removable은 suppressions remove가 어떤 행을 받을지 알려 줍니다.
openemail suppressions add --email [email protected]openemail suppressions list --q [email protected] --json | jq -r '.items[] | select(.removable) | .id'openemail suppressions remove 7b1e2c3d-4f5a-4b6c-8d7e-9f0a1b2c3d4e --yesopenemail contacts block [email protected]확인과 인증 코드
다음 명령은 실행하기 전에 터미널에서 확인을 요청합니다:
| 네임스페이스 | 확인 요청 |
|---|---|
| contacts | delete, delete-many, remove-photo, unblock |
| audiences | delete, empty, remove-contact, remove-contacts |
| broadcasts | send, cancel |
| suppressions | remove |
--yes가 대신 확인합니다.--json이나--no-input을 주었거나, CI이거나, 터미널이 없는 무인 실행에서는 확인을 물었을 명령이Refusing to run unattended. Pass --yes to confirm.와 종료 코드2로 멈춥니다.--dry-run은 명령이 보낼 요청을 출력하고, 묻지도 바꾸지도 않고 코드0으로 종료합니다.- 브라우저 로그인에서는
audiences delete가 웹 앱처럼 먼저 인증 코드를 요구합니다.--yes는 이를 절대 건너뛰지 않으며, 무인 실행에서는 명령이 종료 코드4로 멈춥니다. 미리openemail verify를 실행하거나, 코드를 요구받지 않는 API 키를 쓰세요. audiences empty는 인증 코드를 요구하지 않으므로,--yes를 넘기기 전에 ID를 확인하세요.
페이지 넘기기
목록을 보여 주는 명령은 모두 한 페이지를 읽습니다. 더 남아 있으면 출력된 커서를 같은 필터와 함께 --cursor에 넘기거나, 전부 읽으세요:
--all은 모든 페이지를 읽어 항목을 스트리밍합니다. 터미널에서는 표로, 파이프로 보내거나--ndjson을 주면 한 줄에 JSON 객체 하나로 출력합니다.--max <n>은 그 개수만큼 읽고 멈추며,--all을 포함합니다.--json은--all일 때도{ items, hasMore, nextCursor }문서 하나를 출력합니다.- 형식이 잘못되었거나 오래된 커서는 400
invalid_cursor입니다. 커서 없이 다시 시작하세요.
| 명령 | 페이지 크기 |
|---|---|
| openemail contacts list | 1에서 200, --limit로 달리 정하지 않으면 50 |
| openemail contacts list-people | 1에서 100, --limit로 달리 정하지 않으면 25 |
| openemail contacts list-threads | 1에서 100, --limit로 달리 정하지 않으면 25 |
| openemail audiences list | 1에서 100, --limit로 달리 정하지 않으면 25 |
| openemail audiences list-contacts | 1에서 200, --limit로 달리 정하지 않으면 50 |
| openemail broadcasts list | 1에서 100, --limit로 달리 정하지 않으면 25 |
| openemail broadcasts list-recipients | 1에서 200, --limit로 달리 정하지 않으면 50 |
| openemail suppressions list | 1에서 100, --limit로 달리 정하지 않으면 25 |
알아 두면 좋은 점
contacts create는 이미 주소록에 있는 주소를 409contact_exists로 거부하므로, 재시도가 누군가 고친 이름을 덮어쓰는 일은 없습니다.contacts save는 절대 거부하지 않습니다. 주소가 어떤 상태든 저장하거나, 유지하거나, 되살립니다.contacts delete는 메일에서만 본 주소도 받으며, 그러면 그 사람이list-people에서 빠집니다. 메일은 남습니다. 되돌릴 수 없습니다. 주소를 다시 저장하면 이름, 메모, 기본 오디언스 외의 오디언스가 없는 연락처로 새로 시작합니다.- 주소는 연락처의 신원이므로
contacts update로 바꿀 수 없습니다. 연락처를 옮기려면delete와create를 합니다. contacts set-photo는 파일에서, 또는-로 stdin에서 이미지를 읽습니다.image/jpeg같은--content-type을 넘기세요. 없으면 이미지가application/octet-stream으로 갈 수 있고, 서버는 이를 422invalid_image로 거부합니다.broadcasts send --scheduled-at은2026-10-01T09:00:00Z같은 ISO 8601 시각이나PT2H,P1D같은 ISO 8601 기간을 받으며, 365일 뒤까지 가능합니다.send --at이 받는2h같은 짧은 지연은 여기서 거부됩니다.- 병합 필드는
--subject,--html,--text에서 동작합니다.{{firstName}},{{lastName}},{{name}},{{email}},{{unsubscribeUrl}}이며,{{firstName|there}}처럼 세로 막대 뒤에 대체 값을 둘 수 있습니다.{{unsubscribeUrl}}이 없는 본문에는 한 줄짜리 수신 거부 푸터가 붙습니다. 템플릿은 그대로 보내지므로 링크는 템플릿에 넣으세요. - 브로드캐스트는 무엇이든 기록하기 전에 요금제의 월간 발송량과 대조되며, 사본 한 통이 발송 한 번으로 계산됩니다. 할당량이 감당할 수 없는 브로드캐스트는 429
send_quota_exceeded로 거부되고 아무것도 남지 않습니다. - 스크립트가 같은 단계를 다시 실행할 수 있다면
broadcasts send에 직접 정한--idempotency-key를 넘기세요. 같은 키는 새로 보내는 대신 이미 만든 브로드캐스트로 응답합니다. - 브로드캐스트에서 구독을 해지한 연락처는
unsubscribedAt이 설정된 채 오디언스에 남으며, 이후 그 오디언스로 보내는 브로드캐스트는 그 연락처를 건너뜁니다.audiences list-contacts --statuses unsubscribed가 그들을 나열합니다. - 하드 바운스는 발송 차단 목록에 남습니다.
suppressions remove는 이를 409suppression_not_removable로 거부하며, 각 행의removable이 이를 미리 알려 줍니다.