목록과 단건 조회
`emails.list`, `emails.list_all`, `emails.iterate`, `emails.get`, `emails.list_events`.
emails.list
filters = {status: ["queued", "scheduled"], from: "[email protected]"} first = client.emails.list(**filters, limit: 50)second = client.emails.list(**filters, limit: 50, cursor: first.next_cursor) if first.next_cursor p first.items.size, second&.items&.size페이지는 items, has_more?, next_cursor를 가진 OpenEmail::Page입니다. 그다음 페이지를 받으려면 같은 필터와 함께 next_cursor를 cursor:로 돌려보내세요.
emails.iterate와 emails.list_all
client.emails.iterate(status: "failed") do |email| warn "#{email[:id]} #{email[:lastError]}"end failures = client.emails.list_all(status: "failed", from: "[email protected]")puts failures.size둘 다 next_cursor를 대신 따라갑니다. iterate는 순회가 해당 페이지에 도달할 때에만 가져오므로 블록 안의 break, 또는 블록 없이 반환된 Enumerator에 대한 first나 find가 요청을 멈추며, list_all은 하나의 Array를 반환하기 전에 모든 페이지를 훑으므로 끝이 있는 필터를 주어야 합니다. 어느 쪽이든 키셋 페이징이므로, 반복 중에 도착한 메시지가 오프셋 방식처럼 행을 건너뛰게 만들 수 없습니다.
emails.get과 emails.list_events
email = client.emails.get("msg_3f9a1c07d2b84e6a9c5b1f20")puts email[:status]p email[:recipients] events = client.emails.list_all_events("msg_3f9a1c07d2b84e6a9c5b1f20")events.each { |event| puts "#{event[:type]} #{event[:createdAt]}" }recipients를 반환하는 호출은 get뿐이며, 주소마다 하나의 Hash로 각각 고유한 status, error, deliveredAt을 가집니다. 50개의 메시지가 각각 수신자를 달고 오는 목록은 아무도 원하지 않는 보고서 한 페이지입니다.
list_events는 한 발송의 이벤트 기록을 오래된 순서로 읽습니다: email.accepted, email.queued, email.sent, email.delivered, email.bounced, email.opened 등이며, 각각 type에 따라 형태가 정해지는 data Hash를 가집니다. list_all_events와 iterate_events는 기록 전체를 대신 순회합니다. 웹훅은 같은 이벤트의 일부를 발생 시점에 전달하므로, 웹훅을 놓쳤을 때 확인할 곳이 여기입니다.
매개변수
statusString or Array<String>- 상태 하나 또는 여럿(`queued`, `scheduled`, `sending`, `sent`, `partial`, `bounced`, `cancelled`, `failed`)이며, 주어진 것 중 아무거나 일치하면 됩니다. `bounced`는 메시지가 간 모든 수신자에게서 반송되었다는 뜻이며, 일부에게서 반송되고 나머지에게는 도달한 메시지는 `partial`입니다. 서버가 쉼표로 나누므로 gem은 Array를 쉼표로 이어 붙인 하나의 값으로 보내며, 그 집합을 벗어난 값은 알 수 없는 값을 지목하는 422입니다.
broadcast_idString- 브로드캐스트 하나의 사본만이며, `broadcasts.send`에서 받은 `brd_` id를 씁니다. 브로드캐스트가 닿은 사람은 모두 자기 메시지를 받으므로, 이것으로 누구에게 갔고 각 사본이 어떻게 되었는지 나열합니다. `broadcasts.list_recipients`는 같은 사람들을 열람, 클릭, 수신 거부와 함께 나열합니다.
fromString- 기록된 그대로의 발신 주소에 대한 정확한 일치이며, 그 값은 소문자로 된 `addr@host`입니다. 행은 표시 이름이 제거된 채로 기록되므로 `Acme <[email protected]>` 같은 꺾쇠 주소는 아무것도 일치시키지 못합니다. 전달한 값은 비교 전에 소문자로 바뀌며, 접두사나 도메인 일치가 아니라 동등 비교입니다.
scheduled_fromTime, DateTime or String- 이 시각 또는 그 이후로 예약된 메시지만입니다. `scheduled_to:`와 `status: ["scheduled", "queued"]`와 함께 쓰면, 앱의 캘린더처럼 어떤 기간에 발송을 기다리는 것을 나열합니다. `scheduledAt`이 없는 메시지는 제외됩니다. Time, DateTime, 또는 오프셋이 있는 ISO 8601 시각을 전달하세요: Ruby의 Date는 날짜만 있는 값으로 전송되며, 이 두 필터는 그것을 거부합니다.
scheduled_toTime, DateTime or String- 이 시각 또는 그 이전으로 예약된 메시지만입니다. `scheduled_from:`이 `scheduled_to:`보다 늦으면 422 `invalid_parameter`입니다.
limitInteger- 이 페이지의 행 수이며 1에서 100까지, 기본값은 25입니다. 범위를 벗어난 값은 잘려 들어가지 않고 422로 거부됩니다. `list_all`과 `iterate`에서는 각 페이지를 가져오는 크기입니다.
cursorString- 페이징 기준이 될 메시지 id(`msg_…`)입니다. 오프셋이 아니라 키셋입니다: 그 메시지의 `createdAt`보다 엄격히 오래된 행이 돌아오므로, 페이지 중간에 도착한 발송이 행을 밀어낼 수 없습니다. 이 워크스페이스에 없는 메시지를 가리키는 id는 400 `invalid_cursor`입니다.
api_keyString- 클라이언트의 키 대신 이 키로 목록을 가져옵니다.
일부 주소로 제한된 키는 자신이 다루는 주소에서 보낸 메시지만 읽으며, 페이지는 그 필터를 적용한 뒤에 나뉘므로 마지막 페이지를 제외한 모든 페이지는 limit개의 행을 담습니다. 키가 다루지 않는 from:은 403이 아니라 빈 마지막 페이지를 반환합니다.
응답: OpenEmail::Page
itemsArray<Hash>- `createdAt` 기준 최신순으로 정렬된 메시지 한 페이지이며, API의 `data` 봉투에서 꺼낸 값입니다. 목록 행에는 주소별 `recipients` 내역이 담기지 않습니다. 그것은 `get`에 있습니다.
has_more?Boolean- 이 페이지 너머에 필터와 일치하는 행이 더 있는지 여부입니다. 별도의 count 쿼리가 아니라 `limit`보다 한 행을 더 가져와서 판단합니다.
next_cursorString or nil- `cursor:`로 돌려보낼 id이며, 마지막 페이지에서는 nil입니다. `iterate`와 `list_all`은 이 값이 nil이거나 `has_more?`가 false이면 멈춥니다. 커서를 주지 않으면서 더 있다고 주장하는 페이지는 영원히 반복될 테니까요.
각 항목
objectString- 이 목록의 행에서는 항상 `email`입니다.
idString- 이 API 자체의 id인 `msg_…`입니다. 다른 모든 emails 호출이 받는 값이자 커서가 가리키는 값입니다.
statusString- 메시지가 생애의 어느 지점에 있는지입니다. `partial`은 failed의 변종이 아니라 그 자체로 하나의 상태입니다. 일부 수신자는 이미 메시지를 받았고 되돌릴 수 없으므로 재시도는 잘못된 대응입니다. `bounced`는 보낸 뒤 모든 수신자에게서 반송되어 아무도 받지 못했다는 뜻이며, `get`의 각 수신자에 그 이유가 나옵니다.
modeString- 보낸 키에서 가져온 `live` 또는 `test`입니다. 테스트 발송은 여기에 기록되며 결코 전송되지 않습니다.
fromString- 발송이 인가된 주소이며, 소문자로 주소만 저장됩니다. 따라서 `from`에 준 표시 이름은 실제 전송에는 나가지만 여기에는 보관되지 않습니다. Hash가 아니라 평범한 String인 이유는 이것이 인가된 신원이기 때문입니다: 키의 발송 범위를 벗어난 주소, 즉 키가 보유한 도메인에 속하지도 않고 키에 지정되지도 않은 주소는 403으로 거부되며, 사용할 수 있는 주소로 조용히 바뀌는 일은 결코 없습니다.
subjectString or nil- 저장된 그대로의 제목입니다. 제목 없이 기록된 메시지에서는 nil입니다.
messageIdString or nil- 이 API의 id가 아니라 RFC 5322의 Message-ID입니다. MIME이 만들어지기 전까지는 nil이고 발송 서비스가 나가는 길에 다시 씁니다. 따라서 이후의 반송이나 DSN은 다른 id를 담으며, 대조는 대신 `id`로 합니다.
threadIdString or nil- 이 메시지가 속한 스레드이며, 주어졌거나 배정된 경우에 한합니다. 그 외에는 nil입니다.
transportString or nil- 바이트가 어떤 경로로 나갔는지입니다. 발송 전에는 nil입니다. 저장된 레코드에는 더 이상 쓰이지 않는 전송 경로의 이름이 남아 있을 수 있으므로, 모르는 값은 오류가 아니라 정보로 취급하세요.
attemptsInteger- 이 메시지에 대한 발송 시도 횟수이며, 첫 시도 전에는 0입니다.
lastErrorString or nil- 가장 최근의 발송 오류로, 사람이 읽도록 쓰여 있습니다. 실패한 것이 없으면 nil입니다.
scheduledAtString or nil- 메시지가 나갈 예정 시각이며 ISO 8601 시각입니다. 취소 시간이 없는 즉시 발송에서만 nil입니다: 취소 시간은 짧은 지연일 뿐이므로 `cancellableForSeconds`도 이 값을 채우며, 그 행의 `status`는 `scheduled`가 아니라 `queued`입니다.
cancellableUntilString or nil- 메시지가 나갈 예정 시각으로, 지연된 발송에서는 `scheduledAt`과 같은 값을 담고 지연되지 않은 발송에서는 nil입니다. 서버가 실제로 하는 검사가 아니라 화면에 표시할 시각입니다: `cancel`은 `status`로 분기하며, 메시지가 아직 `queued`나 `scheduled`일 때만 중단합니다.
sentAtString or nil- 실제로 나간 시각입니다. 발송이 완료되기 전까지는 nil이며, 그래서 분기해야 할 필드는 이것이 아니라 `status`입니다.
tagsHash- 발송할 때 준 라벨로, 그대로 돌려주며 해석하지 않습니다. 항상 Hash이며, 아무것도 설정하지 않으면 비어 있을 뿐 nil이 되지는 않고, 돌려주기만 합니다: 이 목록은 `status`, `from`, `broadcast_id`와 예약 기간으로 필터링하므로, 태그는 메시지에서 읽는 것이지 메시지를 찾는 방법이 아닙니다.
broadcastIdString or nil- 이 메시지가 사본인 `brd_` 브로드캐스트, 또는 단독으로 보낸 메시지라면 nil.
sourceString- 어떤 표면이 발송을 요청했는지입니다. `composer`, `api`, `mcp`, `ai`, `queue` 중 하나이며, `api`가 이 클라이언트입니다.
createdAtString- 발송 기록이 쓰인 시각이며, 이는 실제 발송보다 앞섭니다. 이 목록이 정렬하는 필드이자 커서가 비교하는 필드입니다.
trackingHash- 참여 지표 요약이며, 추적된 메시지의 행에만 있고 그 외에는 없습니다. “이 메시지가 추적되었는가”에 대한 답이 바로 그 없음이며, `openCount`가 0이면 “아무도 열지 않았다”로 읽힐 것입니다.
translationHash- 목록 행에는 결코 없습니다. 번역 기록은 저장된 요청 안에 있고, 목록은 의도적으로 그것을 가져오지 않습니다. 여기에 없다는 사실은 메시지가 번역되었는지에 대해 아무것도 말해 주지 않습니다. `get`에 물어보세요.
항목의 추적
opensBoolean- 이 메시지가 픽셀과 함께 나갔는지 여부입니다. 계정 설정이 지금 무엇인지가 아니라, 이 메시지에 적용된 값입니다.
clicksBoolean- 이 메시지의 링크가 재작성되었는지 여부입니다. 본문에 재작성할 링크가 없었다면 false인데, 그때는 바뀐 것이 없기 때문입니다.
openedBoolean- 집계된 열람이 하나라도 기록되었는지 여부이며, `openCount`가 0보다 큰지에서 파생됩니다.
clickedBoolean- 집계된 클릭이 하나라도 기록되었는지 여부이며, `clickCount`가 0보다 큰지에서 파생됩니다.
openCountInteger- 사람이 발생시킨 것으로 보이는 열람을 메시지의 모든 사본에 대해 합한 값입니다. 스캐너와 프라이버시 프록시는 기록되지만 제외되며, 30초 이내의 반복 요청은 하나로 합쳐집니다.
clickCountInteger- 사본 전체에 대해 합한 집계 클릭 수입니다. 메시지 단위가 아니라 링크 단위로 중복 제거되는데, 몇 초 간격으로 두 링크를 따라간 것은 반복이 아니라 두 번의 행위이기 때문입니다.
firstOpenAtString or nil- 사본 전체에서 가장 이른 집계 열람이며, 없으면 nil입니다. 기계에 의한 요청은 이 값을 움직이지 않습니다.