문서로 건너뛰기
Python

연락처

`contacts.list`, `get`, `create`, `save`, `update`, `set_audiences`, `delete`, `delete_many`, `list_people`, `set_photo`, `remove_photo`, `block`, `unblock`, `list_threads`, `activity`.

모든 메서드

usage.py
from openemail import openemail page = openemail.contacts.list(limit=100)contact = openemail.contacts.get('[email protected]') saved = openemail.contacts.create({    'email': '[email protected]',    'name': 'Grace Hopper',    'notes': 'Met at the compiler workshop',}) openemail.contacts.update(saved['email'], {'notes': None})openemail.contacts.set_audiences(saved['email'], {    'audienceIds': ['aud_4c1b8e2a7d9f05c36b4e8a71'],})openemail.contacts.delete(saved['email']) print(len(page['items']), page['hasMore'], contact['source'], contact['lastSeenAt'])

가장 최근에 본 순서대로이며, 한 번도 메일을 보낸 적 없는 연락처가 뒤로 갑니다. source는 멤버가 앱 작성기에서 그 주소로 메시지를 보냈기 때문에 행이 기록된 경우 auto이며, 이는 누군가 직접 저장했다는 것과는 실질적으로 다른 주장입니다. 어떤 주소에서 메일이 도착해도 아무것도 기록되지 않고, 이 API를 통한 발송도 마찬가지입니다.

주소록은 한 사람이 아니라 워크스페이스에 속하므로, 어느 멤버가 저장한 연락처든 모든 멤버와 모든 키가 같은 연락처를 봅니다. create는 source를 manual로 기록하고, 저장하면서 연락처를 기본 오디언스에 넣습니다. 같은 호출에서 직접 만든 목록에 추가하려면 audienceIds에 지정하세요. 여기에는 audiences:write도 필요합니다. 아니면 나중에 openemail.audiences.add_contact로 추가하면 됩니다. set_audiences는 연락처가 어떤 목록에 속할지 한 번의 호출로 정확히 지정합니다.

주소는 소문자로 저장되고 클라이언트가 전달한 값을 인코딩하므로 [email protected]도 올바른 행에 도달합니다. 주소가 곧 신원이므로 update로는 주소를 바꿀 수 없습니다. 연락처를 옮기는 일은 delete와 create입니다.

매개변수: contacts.list

limitint
한 페이지에 반환할 연락처 수입니다. 1에서 200까지의 integer이고 기본값은 50입니다. 형 변환이 이루어지므로 쿼리 문자열에서 온 `'100'`도 괜찮으며, 범위를 벗어난 값은 잘려 들어가지 않고 422가 됩니다.
cursorstr
이전 페이지의 `nextCursor`입니다. 절대 직접 만들지 마세요. 더 이상 존재하지 않는 연락처를 가리키는 커서는 400 `invalid_cursor`이며, 이는 페이징 상태가 낡았으니 커서 없이 처음부터 다시 훑어야 한다는 뜻입니다.
sourceContactSource
누군가 의도적으로 저장한 연락처는 `'manual'`, 앱 작성기가 기록한 연락처는 `'auto'`입니다. 주소록 전체를 보려면 생략하세요.
qstr
이름과 주소를 최대 200자로 검색합니다. 첫 페이지에서 정확히 일치하는 것이 없으면 대신 비슷한 철자가 반환되고, 이후 페이지도 같은 방식으로 계속 일치시킵니다.

응답: ContactResource

contacts.list는 Page[ContactResource]를 반환하므로 행은 page['items']에 있고, page['hasMore']가 True인 동안 page['nextCursor']를 따라가며, list_all과 iterate가 이를 대신해 줍니다. get, create, save, update, set_audiences, set_photo, remove_photo는 각각 같은 행에 audiences가 더해진 ContactDetailResource 하나를 반환합니다. 주소록에는 상한이 없으며, 그래서 이 경로는 조용히 200행에서 멈추는 리스트 대신 페이징을 합니다.

objectLiteral['contact']
목록 행에서도 `get`에서도 항상 문자열 `contact`입니다.
emailstr
주소이며, 저장 시 소문자로 바뀌므로 `[email protected]`과 `[email protected]`은 하나의 연락처입니다. 연락처 id는 노출되지 않으므로 모든 contacts 메서드가 받는 키가 바로 이 값입니다. 행은 그것을 기록한 멤버나 키가 아니라 워크스페이스에 속하므로, 워크스페이스의 모든 멤버와 모든 키가 하나의 주소록을 읽고 씁니다.
namestr | None
해당 주소에 대해 이름이 기록된 적이 없으면 `None`입니다. 자동 기록은 헤더가 주소 자체가 아닌 무언가를 제공했을 때만 이름을 담으며, 사용자가 입력한 이름을 덮어쓰는 일은 결코 없습니다.
sourceContactSource | str
`auto`는 사용자가 그 주소로 메일을 보냈기 때문에 행이 기록되었다는 뜻이고, `manual`은 누군가 직접 입력했다는 뜻으로 실질적으로 다른 주장이며, upsert가 `manual`을 `auto`로 되돌리는 일은 없습니다. 어떤 주소에서 메일이 도착해도 행은 전혀 기록되지 않는데 이는 의도된 것이므로, 당신에게 메일을 보내기만 한 사람은 여기에 없습니다. 이 컬럼은 기본값이 `manual`인 자유 텍스트이므로 유니온은 열려 있습니다.
notesstr | None
앱에서든 `update`를 통해서든 누군가 이 사람에 대해 적은 자유 텍스트이며, 자동 생성되지 않습니다. 아무도 적지 않았으면 `None`이고, `update`에서 명시적으로 `None`을 주면 지워집니다.
lastSeenAtstr | None
ISO-8601 UTC로, 멤버가 앱 작성기에서 그 주소로 보낼 때마다 갱신됩니다. 그 주소에서 메일이 도착할 때는 아무것도 기록되지 않으므로 갱신되지 않습니다. `create`로 저장했고 한 번도 메일을 보내지 않은 연락처에서는 `None`이며, 이 경로가 반환하는 `lastSeenAt` 내림차순 정렬에서 그런 연락처는 맨 뒤로 갑니다.
audienceslist[ContactAudienceResource]
목록 행에는 없고 `get`, `create`, `save`, `update`, `set_audiences`, `set_photo`, `remove_photo`에만 있습니다. 연락처가 속한 모든 오디언스를 기본 오디언스까지 포함해 `id`, `name`, `builtin`이 있는 dict로 담습니다. `builtin`은 모든 연락처가 속하는 오디언스에서 `default`이고 누군가 만든 오디언스에서는 `None`이므로, 누구나 바꿀 수 있는 이름이 아니라 이 값으로 분기하세요.
photoUrlstr | None
연락처 사진이 제공되는 위치이며, 사진이 없으면 `None`입니다. `set_photo`로 설정하고, 올릴 때마다 새 URL을 받습니다.

연락처의 오디언스 지정하기

set_audiences(email, {'audienceIds': [...]})는 연락처 하나가 어떤 오디언스에 속할지 한 번의 요청으로 정확히 지정합니다. 연락처는 나열된 오디언스 중 아직 속하지 않은 곳에 모두 들어가고 나머지에서는 모두 빠지며, 호출은 변경 후의 ContactDetailResource를 반환합니다. 연락처가 아니라 멤버십을 쓰므로 audiences:write가 필요하고, 반복해도 아무것도 바뀌지 않습니다.

기본 오디언스는 항상 유지되므로 {'audienceIds': []}를 보내면 연락처는 기본 오디언스에만 남습니다. ID는 최대 100개까지 받습니다. 이 워크스페이스의 어떤 오디언스도 가리키지 않는 ID는 404 audience_not_found가 되고 아무것도 바뀌지 않으며, 연락처가 아닌 주소는 404 contact_not_found가 됩니다.

연락처 페이지의 모든 사람

list_people은 앱의 연락처 페이지가 보여 주는 사람을 나열합니다. 저장된 연락처와 메일에서 본 모든 주소이며, 각각 saved, threads, lastAt을 가집니다. list는 저장된 연락처뿐입니다. 메일에서 본 주소는 키가 threads:read도 가진 경우에만 오며, 왔는지는 page['seen']이 알려 줍니다. sort는 recent, name, threads 중 하나이고, q는 이름, 주소, 메모를 검색하며, blocked=True는 워크스페이스 차단 목록이 차단하는 사람만 남기고 도메인 전체 규칙도 포함합니다. blockedBy는 각 행에서 그 규칙을 알려 줍니다.

people.py
from openemail import openemail page = openemail.contacts.list_people(sort='threads', limit=50) for person in page['items']:    if not person['saved'] and (person['threads'] or 0) > 5:        openemail.contacts.save(person['email']) blocked = openemail.contacts.list_all_people(blocked=True)

list_all_people과 iterate_people은 모든 페이지를 훑습니다. 커서는 불투명하므로 nextCursor를 받은 그대로, 같은 sort, q, blocked와 함께 다시 보내세요.

저장, 삭제, 사진

save(email, {'name': ..., 'notes': ...})는 연락처에 추가와 연락처에 유지입니다. 아직 연락처가 아닌 주소를 저장하고, 발송에서 기록된 주소는 직접 저장한 것으로 유지하며, 삭제된 주소를 되돌립니다. delete는 삭제입니다. 저장된 연락처를 없애고 주소를 숨겨 작성기가 다시 기록하지 않게 하며, 메일에서만 본 주소도 받습니다. 어느 쪽이었는지는 wasSaved가 알려 줍니다. delete_many는 한 번의 호출로 최대 200개를 삭제합니다.

photo.py
from pathlib import Path from openemail import openemail openemail.contacts.save('[email protected]', {'name': 'Grace Hopper'}) photo = Path('grace.jpg').read_bytes()contact = openemail.contacts.set_photo('[email protected]', photo, content_type='image/jpeg') openemail.contacts.remove_photo('[email protected]')openemail.contacts.delete_many(['[email protected]', '[email protected]'])

set_photo는 이미지 바이트를 그대로 보냅니다. PNG, JPEG, WebP, GIF 중 하나로 최대 5 MB이며, 512픽셀 정사각형에 맞춰집니다. 바이트에는 자체 형식 정보가 없으므로 content_type=을 넘기세요. 넘기지 않으면 application/octet-stream으로 업로드되어 422 invalid_image로 거부됩니다. 주소는 먼저 저장된 연락처여야 합니다.

차단

block(email)은 주소를 워크스페이스 차단 목록에 올려 그 주소의 메일을 거부하며 플러스 태그는 버리고, unblock(email)은 그 주소를 차단하는 모든 규칙을 뺍니다. 둘 다 연락처가 아니라 차단 목록을 바꾸므로 settings:write가 필요하며, 어느 쪽도 주소가 연락처일 필요는 없습니다.

unblock이 도메인 전체 규칙을 풀면 removed는 그 규칙을 list가 blockedDomains인 항목으로 나열하며, 그 도메인의 모든 사람의 차단이 함께 해제됩니다.

대화와 활동

list_threads(email)은 그 주소가 쓰거나 그 주소로 쓴 스레드를 모든 폴더에서 한 페이지씩 넘기고, list_all_threads와 iterate_threads는 전부를 훑습니다. activity(email)은 연락처 활동 탭 뒤의 숫자를 돌려줍니다. 구간별로 받은 메일과 보낸 메일, 답장을 기다리는 스레드, 양방향 답장 시간의 중앙값입니다. 둘 다 threads:read가 필요합니다.

activity.py
import time from openemail import openemail threads = openemail.contacts.list_threads('[email protected]', q='invoice') activity = openemail.contacts.activity(    '[email protected]',    minutes=30 * 24 * 60,    grain='day',    offset_minutes=time.localtime().tm_gmtoff // 60,) print(len(threads['items']), activity['totals']['waiting'])

레퍼런스