문서로 건너뛰기
Ruby

목록과 단건 조회

`emails.list`, `emails.list_all`, `emails.iterate`, `emails.get`, `emails.list_events`.

emails.list

list_emails.rb
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

iterate_emails.rb
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

get_email.rb
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입니다. 기계에 의한 요청은 이 값을 움직이지 않습니다.