連絡先
`contacts.list`、`get`、`create`、`save`、`update`、`set_audiences`、`delete`、`delete_many`、`list_people`、`set_photo`、`remove_photo`、`block`、`unblock`、`list_threads`、`activity`。
すべてのメソッド
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 を使えば、連絡先がどのリストに入るかを 1 回の呼び出しで正確に指定できます。
アドレスは小文字に正規化して保存され、渡した値はクライアントがエンコードするので、[email protected] でも正しい行に届きます。アドレスが識別子なので update でアドレスを変更することはできません。連絡先の移動は delete と create です。
パラメーター: contacts.list
limitint- 1 ページあたりに返す連絡先の件数。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 はそれぞれ 1 件の ContactDetailResource、つまり同じ行に audiences を加えたものを返します。アドレス帳に上限はなく、だからこの経路は、黙って 200 件で止まるリストではなくページングを行います。
objectLiteral['contact']- 常に文字列 `contact` です。`get` のときだけでなく一覧の行でも同じです。
emailstr- アドレスです。書き込み時に小文字化されるので `[email protected]` と `[email protected]` は 1 件の連絡先になります。連絡先 id は公開されないため、すべての contacts メソッドが受け取るキーはこれです。行は書き込んだメンバーやキーではなくワークスペースに属するので、ワークスペース上のすべてのメンバーとすべてのキーが 1 つのアドレス帳を読み書きします。
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': [...]}) は、1 件の連絡先がどのオーディエンスに入るかを 1 回のリクエストで正確に指定します。連絡先は指定されたオーディエンスのうちまだ入っていないものすべてに参加し、それ以外のすべてから抜け、呼び出しは変更後の 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 は各行でそのルールを示します。
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 は 1 回の呼び出しで最大 200 件を削除します。
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 が必要です。
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'])リファレンス
contacts.list()完全なリファレンスcontacts.list_all()完全なリファレンスcontacts.iterate()完全なリファレンスcontacts.get()完全なリファレンスcontacts.create()完全なリファレンスcontacts.save()完全なリファレンスcontacts.update()完全なリファレンスcontacts.set_audiences()完全なリファレンスcontacts.delete()完全なリファレンスcontacts.delete_many()完全なリファレンスcontacts.list_people()完全なリファレンスcontacts.list_all_people()完全なリファレンスcontacts.iterate_people()完全なリファレンスcontacts.set_photo()完全なリファレンスcontacts.remove_photo()完全なリファレンスcontacts.block()完全なリファレンスcontacts.unblock()完全なリファレンスcontacts.list_threads()完全なリファレンスcontacts.list_all_threads()完全なリファレンスcontacts.iterate_threads()完全なリファレンスcontacts.activity()完全なリファレンス