연락처
`contacts.list`, `get`, `create`, `save`, `update`, `set_audiences`, `delete`, `delete_many`, `list_people`, `set_photo`, `remove_photo`, `block`, `unblock`, `list_threads`, `activity`.
모든 메서드
page = client.contacts.list(limit: 100)contact = client.contacts.get("[email protected]") saved = client.contacts.create( email: "[email protected]", name: "Grace Hopper", notes: "Met at the compiler workshop") client.contacts.update("[email protected]", notes: nil)client.contacts.set_audiences("[email protected]", audienceIds: ["aud_4c1b8e2a7d9f05c36b4e8a71"])client.contacts.delete("[email protected]") puts page.items.size, page.has_more?, contact[:source], contact[:lastSeenAt], saved[:source]list는 가장 최근에 본 연락처부터 반환하며, 한 번도 메일을 보낸 적 없는 연락처가 뒤로 갑니다. source는 멤버가 앱 작성기에서 그 주소로 메시지를 보냈기 때문에 행이 기록된 경우 auto이며, 이는 누군가 직접 저장했다는 것과는 실질적으로 다른 주장입니다. 어떤 주소에서 메일이 도착해도 아무것도 기록되지 않고, 이 API를 통한 발송도 마찬가지입니다.
주소록은 한 사람이 아니라 워크스페이스에 속하므로, 어느 멤버가 저장한 연락처든 모든 멤버와 모든 키가 같은 연락처를 봅니다. create는 source를 manual로 기록하고, 저장하면서 연락처를 기본 오디언스에 넣습니다. 같은 호출에서 직접 만든 목록에 추가하려면 audienceIds에 지정하세요. 여기에는 audiences:write도 필요합니다. 아니면 나중에 audiences.add_contact로 추가하면 되며, 이는 오디언스 페이지에서 다룹니다. set_audiences는 연락처가 어떤 목록에 속할지 한 번의 호출로 정확히 지정합니다.
주소는 소문자로 저장되고 gem이 전달한 값을 인코딩하므로 [email protected]도 올바른 행에 도달합니다. nil이나 빈 주소는 무엇이든 보내기 전에 ArgumentError를 발생시킵니다. 주소가 곧 신원이므로 update로는 주소를 바꿀 수 없습니다: 연락처를 옮기는 일은 delete와 create입니다.
매개변수: contacts.list
limitInteger- 한 페이지에 반환할 연락처 수입니다: 1에서 200까지의 정수이고 기본값은 50입니다. 형 변환이 이루어지므로 쿼리 문자열에서 읽은 `"100"` 같은 String도 괜찮으며, 범위를 벗어난 값은 잘려 들어가지 않고 422가 됩니다.
cursorString- 이전 페이지의 `next_cursor`입니다. 절대 직접 만들지 마세요: 더 이상 존재하지 않는 연락처를 가리키는 커서는 `OpenEmail::InvalidRequestError`로 발생하는 400 `invalid_cursor`이며, 이는 페이징 상태가 낡았으니 커서 없이 처음부터 다시 훑어야 한다는 뜻입니다.
sourceString- 누군가 의도적으로 저장한 연락처는 `manual`, 앱 작성기가 기록한 연락처는 `auto`입니다. 주소록 전체를 보려면 생략하세요.
qString- 이름과 주소를 최대 200자로 검색합니다. 첫 페이지에서 정확히 일치하는 것이 없으면 대신 비슷한 철자가 반환되고, 이후 페이지도 같은 방식으로 계속 일치시킵니다.
응답: 연락처
contacts.list는 OpenEmail::Page를 반환하므로 행은 page.items에 있고, page.has_more?가 true인 동안 page.next_cursor를 따라갑니다. list_all은 모든 행을 하나의 Array로 반환하고, iterate는 하나씩 yield합니다. get, create, update, save, set_audiences는 각각 같은 행에 audiences가 더해진 연락처 하나를 Symbol 키의 Hash로 반환합니다. 주소록에는 상한이 없으며, 그래서 이 경로는 조용히 200행에서 멈추는 Array 대신 페이징을 합니다.
objectString- 목록 행에서도 `get`에서도 항상 문자열 `contact`입니다.
emailString- 주소이며, 저장 시 소문자로 바뀌므로 `[email protected]`과 `[email protected]`은 하나의 연락처입니다. 연락처 id는 노출되지 않으므로 모든 contacts 메서드가 받는 키가 바로 이 값입니다. 행은 그것을 기록한 멤버나 키가 아니라 워크스페이스에 속하므로, 워크스페이스의 모든 멤버와 모든 키가 하나의 주소록을 읽고 씁니다.
nameString or nil- 표시 이름입니다. 해당 주소에 대해 이름이 기록된 적이 없으면 nil입니다. 자동 기록은 헤더가 주소 자체가 아닌 무언가를 제공했을 때만 이름을 담으며, 사용자가 입력한 이름을 덮어쓰는 일은 결코 없습니다.
sourceString- `auto`는 사용자가 그 주소로 메일을 보냈기 때문에 행이 기록되었다는 뜻이고, `manual`은 누군가 직접 입력했다는 뜻으로 실질적으로 다른 주장이며, upsert가 `manual`을 `auto`로 되돌리는 일은 없습니다. 어떤 주소에서 메일이 도착해도 행은 전혀 기록되지 않는데 이는 의도된 것이므로, 당신에게 메일을 보내기만 한 사람은 여기에 없습니다. 이 컬럼은 기본값이 `manual`인 자유 텍스트이므로, 값은 열린 String으로 취급하세요.
notesString or nil- 앱에서든 `update`를 통해서든 누군가 이 사람에 대해 적은 자유 텍스트이며, 자동 생성되지 않습니다. 아무도 적지 않았으면 nil이고, `update`에서 `notes: nil`을 주면 지워집니다.
lastSeenAtString or nil- ISO 8601 UTC 문자열로, 멤버가 앱 작성기에서 그 주소로 보낼 때마다 갱신됩니다. 그 주소에서 메일이 도착할 때는 아무것도 기록되지 않으므로 갱신되지 않습니다. `create`로 저장했고 한 번도 메일을 보내지 않은 연락처에서는 nil이며, 이 경로가 반환하는 `lastSeenAt` 내림차순 정렬에서 그런 연락처는 맨 뒤로 갑니다.
audiencesArray<Hash>- 목록 행에는 없고 `get`, `create`, `update`, `save`, `set_audiences`에만 있습니다. 연락처가 속한 모든 오디언스를 기본 오디언스까지 포함해 `id`, `name`, `builtin`이 있는 Hash로 담습니다. `builtin`은 모든 연락처가 속하는 오디언스에서 `default`이고 누군가 만든 오디언스에서는 nil이므로, 누구나 바꿀 수 있는 이름이 아니라 이 값으로 분기하세요.
photoUrlString or nil- 연락처 사진이 제공되는 위치이며, 사진이 없으면 nil입니다. `set_photo`로 설정하고, 올릴 때마다 새 URL을 받습니다.
연락처의 오디언스 설정하기
set_audiences(email, audienceIds: [...])는 연락처 하나가 어떤 오디언스에 속할지 한 번의 요청으로 정확히 지정합니다. 연락처는 나열된 오디언스 중 아직 속하지 않은 곳에 모두 들어가고 나머지에서는 모두 빠지며, 호출은 변경 후의 연락처를 audiences와 함께 반환합니다. 연락처가 아니라 멤버십을 쓰므로 audiences:write가 필요하고, 반복해도 아무것도 바뀌지 않으므로 gem은 네트워크 장애 후에 이를 재시도합니다.
기본 오디언스는 항상 유지되므로 audienceIds: []를 보내면 연락처는 기본 오디언스에만 남습니다. id는 최대 100개까지 받습니다. 이 워크스페이스의 어떤 오디언스도 가리키지 않는 id는 404 audience_not_found가 되고 아무것도 바뀌지 않으며, 연락처가 아닌 주소는 404 contact_not_found가 됩니다. 둘 다 OpenEmail::NotFoundError를 발생시킵니다.
연락처 페이지의 모든 사람
list_people은 앱의 연락처 페이지가 보여 주는 사람을 나열합니다: 저장된 연락처와 메일에서 본 모든 주소이며, 각각 saved, threads, lastAt을 가집니다. list는 저장된 연락처뿐입니다. OpenEmail::PeoplePage를 반환하며, 이는 items, has_more?, next_cursor에 seen을 더한 것입니다. 메일에서 본 주소는 키가 threads:read도 가진 경우에만 오며, 왔는지는 page.seen이 알려 줍니다. sort:는 recent, name, threads 중 하나이며, OpenEmail::PEOPLE_SORTS가 이들을 정의합니다. q:는 이름, 주소, 메모를 검색하며, blocked: true는 워크스페이스 차단 목록이 차단하는 사람만 남기고 도메인 전체 규칙도 포함합니다. blockedBy는 각 행에서 그 규칙을 알려 줍니다.
page = client.contacts.list_people(sort: "threads", limit: 50) page.items.each do |person| client.contacts.save(person[:email]) if !person[:saved] && person[:threads].to_i > 5end blocked = client.contacts.list_all_people(blocked: true)puts page.seen, blocked.sizelist_all_people은 모든 페이지를 하나의 Array로 반환하고, iterate_people은 각 사람을 블록에 yield하거나 블록이 없으면 Enumerator를 반환합니다. 둘 다 seen을 알려 주지 않으므로, 그것을 알려면 list_people로 한 페이지를 읽으세요. 커서는 불투명하므로, next_cursor를 받은 그대로 같은 sort:, q:, blocked:와 함께 cursor:로 돌려보내세요.
저장, 삭제, 사진
선택적인 name:과 notes:를 받는 save(email)은 “연락처에 추가”와 “연락처에 유지”에 해당합니다: 아직 연락처가 아닌 주소를 저장하고, 발송에서 기록된 주소는 직접 저장한 것으로 유지하며, 삭제된 주소를 되돌립니다. delete는 “삭제”에 해당합니다: 저장된 연락처를 없애고 주소를 숨겨 작성기가 다시 기록하지 않게 하며, 메일에서만 본 주소도 받습니다. 반환하는 Hash의 wasSaved가 어느 쪽이었는지 알려 줍니다. delete_many는 한 번의 호출로 최대 200개를 삭제합니다.
client.contacts.save("[email protected]", name: "Grace Hopper") contact = client.contacts.set_photo("[email protected]", File.binread("photo.jpg"), content_type: "image/jpeg")puts contact[:photoUrl] client.contacts.set_photo("[email protected]", Pathname("photo.png")) client.contacts.remove_photo("[email protected]")client.contacts.delete_many(["[email protected]", "[email protected]"])set_photo는 이미지 바이트를 그대로 보냅니다: 최대 5 MB의 PNG, JPEG, WebP, GIF이며, 512픽셀 정사각형에 맞춰집니다. 바이트는 바이너리 String, IO, Pathname 중 하나입니다. content_type:을 전달하거나, 자체 유형을 가진 바이트를 전달하세요: Rails 업로드처럼 content_type에 응답하는 객체, 또는 이름이 .png, .jpg, .jpeg, .webp, .gif로 끝나는 File이나 Pathname입니다. 유형이 없으면 바이트는 application/octet-stream으로 전송되고, 서버는 이를 422 invalid_image로 거부합니다. OpenEmail::CONTACT_PHOTO_TYPES가 네 가지 유형을 정의합니다. 주소는 먼저 저장된 연락처여야 합니다.
차단
block(email)은 주소를 워크스페이스 차단 목록에 올려 그 주소의 메일을 거부하며 플러스 태그는 버리고, unblock(email)은 그 주소를 차단하는 모든 규칙을 뺍니다. 둘 다 연락처가 아니라 차단 목록을 바꾸므로 settings:write가 필요하며, 어느 쪽도 주소가 연락처일 필요는 없습니다.
unblock이 도메인 전체 규칙을 풀면 removed는 그 규칙을 list가 blockedDomains인 항목으로 나열하며, 그 도메인의 모든 사람의 차단이 함께 해제됩니다. OpenEmail::CONTACT_BLOCK_LISTS가 두 목록을 정의합니다.
대화와 활동
list_threads(email)은 그 주소가 쓰거나 그 주소로 쓴 스레드를 모든 폴더에서 한 페이지씩 넘기고, list_all_threads와 iterate_threads는 전부를 훑습니다. activity(email)은 연락처의 활동 탭 뒤에 있는 숫자를 반환합니다: 구간별로 받은 메일과 보낸 메일, 답장을 기다리는 스레드, 양방향 답장 시간의 중앙값입니다. 둘 다 threads:read가 필요합니다.
threads = client.contacts.list_threads("[email protected]", q: "invoice") activity = client.contacts.activity( "[email protected]", minutes: 30 * 24 * 60, grain: "day", offset_minutes: Time.now.utc_offset / 60) puts threads.items.size, activity.dig(:totals, :waiting)activity는 snake_case 키워드 인자를 받습니다. minutes:는 기간을 정하며, 생략하면 90일입니다. grain:은 구간의 폭을 정합니다: minute, hour, day 중 하나입니다. offset_minutes:는 하루가 나뉘는 기준을 UTC에서 동쪽으로 몇 분 옮길지 정합니다. Time.now.utc_offset / 60이 현지 오프셋이며, gem은 이를 API의 offsetMinutes로 보냅니다.