ドキュメント本文へスキップ
Python

設定

クライアントを作る 3 つの方法、すべてのオプション、そしてリクエスト送信前に拒否されるもの。

オプション

clients.py
import os from openemail import AsyncOpenEmail, OpenEmail, init, openemail init(os.environ['OPENEMAIL_API_KEY'])openemail.me.ping() billing = OpenEmail(os.environ['BILLING_API_KEY']) pinned = OpenEmail('oe_live_...', base_url='https://api.openemail.uk') background = AsyncOpenEmail()
エントリーポイント得られるもの
init(...)共有クライアントを設定して返します。以後 openemail はどのモジュールでもそのクライアントになり、省略したものは環境変数から読まれます。
openemail共有クライアント。init より前に使うと、最初の呼び出し時に OPENEMAIL_API_KEY と OPENEMAIL_BASE_URL から自分を組み立てます。
OpenEmail(...)別のクライアント。共有クライアントの隣でもう 1 つのキーを使うときや、自分のモジュールがエクスポートするインスタンスを作るときに使います。省略したものは init と同じく環境変数から読まれます。create_client は同じクラスの別名です。
AsyncOpenEmail(...)同じオプションを持ち、すべてのメソッドを await で呼び出す、別の非同期クライアント。共有の openemail は同期クライアントなので、こちらは自分で作成します。
get_client() と reset_client()get_client は共有クライアントそのものを返し、init が実行されていなければ環境変数からそれを作成します。reset_client はそれを破棄するので、次に使うときに新しいクライアントが作られます。
options.py
import httpxfrom openemail import init init(    'oe_live_...',    base_url='https://api.openemail.uk',    timeout=30,    max_retries=2,    http_client=httpx.Client(proxy='http://proxy.internal:3128'),    headers={'X-Team': 'billing'},    user_agent='billing-service/1.4',    disable_update_notice=True,)
オプション既定値備考
api_keyOPENEMAIL_API_KEYinit と OpenEmail が環境変数から読みます。oe_live_ または oe_test_ で始まる必要があります。
access_tokenOPENEMAIL_ACCESS_TOKENapi_key の代わりに使う OAuth アクセストークン、またはそれを返す関数。下の「OAuthアクセストークン」を参照してください。
base_urlhttps://api.openemail.ukまたは OPENEMAIL_BASE_URL。末尾のスラッシュは取り除かれ、init と OpenEmail はホスト名だけの値には https:// を、このマシン上のホスト(localhost、127.x.x.x のアドレス、::1)には http:// を前置します。認証情報がそれ以外のホストへ暗号化されていない http で送られることはありません。また 0.0.0.0 や [::] はクライアントの作成時に例外を送出します。これらはサーバーが待ち受けるアドレスであり、リクエストの送信先ではないからです。
timeout30秒単位で、呼び出し単位ではなく試行単位です。ヘッダーだけでなくボディの読み取りも対象になります。0 で無効化されます。files.upload は、呼び出しで独自の timeout を渡さない限り、少なくとも 600 秒待ちます。
max_retries2繰り返しても安全な呼び出しについて、初回のあとの追加試行回数です。呼び出しごとではなくクライアントに設定します。
http_client新しい httpx.Clientプロキシ、独自の TLS 設定、マウントしたトランスポート、テスト用のダブルを使うときは、自分で作ったものを渡してください。OpenEmail には httpx.Client を、AsyncOpenEmail には httpx.AsyncClient を渡します。クライアントを閉じても、渡したものは開いたまま残ります。
headers{}すべてのリクエストに付与されます。
user_agentopenemail-python/<version>すべてのリクエストに付与されます。
disable_update_noticeFalsePyPI 上の新しいバージョンをプロセスごとに 1 回確認する処理を省きます。確認は出力がターミナルに向いているときだけ走り、OPENEMAIL_DISABLE_UPDATE_NOTICE でも無効にできます。

送信前に拒否されるもの

これらは、最初の送信時に分かりにくい失敗として表面化するのではなく、リクエストが送られる前に ValueError、または表にそう記載されている場合は TypeError を送出します。メッセージには何が誤っていて、代わりに何を渡すべきかが書かれています。

拒否される条件理由
キーがまったくないapi_key も OPENEMAIL_API_KEY も設定されておらず、認証に使えるものがありません。
セッションクッキーまたはセッショントークンここで認証できるのは oe_live_ と oe_test_ だけで、API 側も同じことを言います。チェックは接頭辞だけなので、失効したキーは通信時に失敗します。
http でも https でもない base_urlそれ以外は取得できないため、クライアントは最初のリクエストで失敗するのではなく、作成時にこれを拒否します。
0.0.0.0 または [::] を指す base_urlサーバーが待ち受けるアドレスであり、リクエストの送信先ではありません。メッセージでは代わりに、同じポートの 127.0.0.1 または [::1] が示されます。
暗号化されていない http で送られる認証情報サーバーがこのマシン上にある場合を除き、リクエストが出ていく前に、呼び出しの時点で拒否されます。ネットワーク上の誰もがそれを読めてしまうからです。
どのメソッドでも空、またはドットだけの idメソッド呼び出し時に送出されます。ドットだけのパスセグメントはどの URL パーサーでも除去されるため、リクエストが別のエンドポイントに届いてしまいます。
種類の誤った http_clientクライアントの作成時に TypeError になります。OpenEmail は httpx.Client を、AsyncOpenEmail は httpx.AsyncClient を受け取ります。
JSON で表せないボディの値その型を名指しする TypeError になります。JSON の型はそのまま通り、datetime、date、set は自動で変換されます。

test_mode オプションはありませんし、今後も作られません。キーのスキーム自体がヒントではなく認証情報の一部なので、モードはキーの性質です。client.mode は接頭辞を読むだけで、何も決めません。

1 つのクライアント、複数のキー

クライアントは一度作って共有してください。リクエストごとに新しいインスタンスを作るのは、コネクションプールと設定を無駄に捨てる行為であり、そこに載っている状態はどれも呼び出し元ごとのものではありません。

1 つのクライアントはスレッド間で安全に共有できます。close() を呼ぶか with ブロックを抜けると、クライアントが開いたコネクションプールが閉じられます。渡した http_client は開いたまま残るので、自分で閉じてください。

複数のワークスペースを代行して送信するジョブなど、そうしなければキーごとに 1 インスタンスを強いられる場合には、api_key を呼び出しに渡してください。そのリクエストに限って Authorization ヘッダーを差し替え、クライアントには何も残しません。

per_call_key.py
from openemail.types import EmailSend workspace_key = 'oe_live_...' message: EmailSend = {'from': sender, 'to': recipient, 'subject': subject, 'text': text} client.emails.send(message) client.emails.send(message, api_key=workspace_key) client.threads.list(folder='inbox', api_key=workspace_key)client.webhooks.list(api_key=workspace_key)

temp_mail 以外のすべてのメソッドが、timeout と並ぶキーワード引数としてこれを受け取ります。コンストラクターと同じ規則でリクエスト送信前に検査されるので、タイプミスは、後から探しに行かなければならない認証情報についての 401 ではなく、api_key= on this call を名指しする ValueError になります。再試行された呼び出しは、渡されたキーを保持します。

timeout は秒単位で、その 1 回の呼び出しに限り、各試行でクライアントのタイムアウトを置き換えます。

client.mode はクライアントが構築されたときのキーを表し、上書きには追随しません。1 つのクライアントが複数のキーを扱うようになれば、報告すべき単一のモードは存在しないので、渡したキーから読み取ってください。

どのメソッドもラップしていないエンドポイント

client.raw.request は、クライアントの認証情報、ベース URL、タイムアウト、再試行ポリシーを適用してリクエストを送り、パース済みの JSON を返します。受け取るのは method、query、body、api_key、timeout です。repeatable=True を渡さない限り、GET は再試行し、それ以外は 1 回だけ送ります。idempotent=True を指定すると Idempotency-Key が付与されます。キーは idempotency_key として渡したもの、なければ新しく生成したものです。

raw_request.py
result = client.raw.request('/something-new', method='POST', body={'name': 'Invoices'})

パスは 1 つの / で始まる必要があります。//host/x のようにそれ以外の形で始まるパスは、リクエストが送られる前に例外を送出します。完成した URL がベース URL のオリジンから外れるパスも同様なので、リクエストに載せた認証情報が別のホストに届くことはありません。

使い捨て受信トレイ

create_temp_mail() は API キーを持たないクライアントを作り、create_async_temp_mail() はその非同期版です。匿名で受信箱を作り、読み取りのたびに create が返した受信箱トークン、または extend が返したより新しいトークンを、呼び出しごとの inbox_token として、あるいは一度だけ create_temp_mail(inbox_token=...) として送ります。

temp_mail.py
from openemail import create_temp_mail temp_mail = create_temp_mail() inbox = temp_mail.create()messages = temp_mail.list_messages(inbox['id'], inbox_token=inbox['token']) print(messages['items'], messages['expiresAt'])

OAuthアクセストークン

未リリース

コマンドラインツールやエージェントなど、本人が OAuth で接続したアプリは、API キーではなくアクセストークンを持ちます。それを access_token として渡します。トークンそのものか、トークンを返す関数のどちらかで、AsyncOpenEmail ではこの関数を async にできます。関数は呼び出しごとに 1 回呼ばれ、その呼び出しの再試行は関数が返した値を使い回します。期限が近づいたら関数の中でトークンを更新すれば、クライアントを作り直す必要はありません。

access_token.py
from openemail import OpenEmail client = OpenEmail(access_token=session.fresh_access_token) me = client.me.get() if me['object'] == 'oauth_token':    print(me['clientId'], me['expiresAt'])
ケース起きること
api_key と access_token の両方、またはどちらもなしコンストラクターが ValueError を送出します。どちらもない場合、メッセージは OPENEMAIL_API_KEY と OPENEMAIL_ACCESS_TOKEN を挙げます。
トークンではない値トークンは 1〜512 文字で、oe_ で始まりません。これは is_access_token が行うチェックです。これを満たさない文字列はコンストラクターで例外になり、そのような値を返す関数は、何も送信されないうちに呼び出しを失敗させます。
OPENEMAIL_ACCESS_TOKENどちらの資格情報も渡さず、OPENEMAIL_API_KEY も設定されていないとき、init、OpenEmail、共有の openemail が読み込みます。つまり環境変数のキーが優先されます。
例外を送出する関数呼び出しはその例外を手を加えずにそのまま送出し、何も送信されません。
awaitable を返す関数を OpenEmail に渡した場合同期クライアントはそれを待てないため、ValueError になります。AsyncOpenEmail では関数を async にできます。
呼び出しごとの api_keyその 1 回のリクエストだけトークンを置き換え、関数は呼ばれません。
modeトークンでは常に live です。
create_temp_mail()環境に何があっても、資格情報は送信しません。
me.get() と me.ping()トークンの場合、get は object が oauth_token、id と roleId が None、接続したアプリの clientId、そして本人がアプリに与えた承認の期限である expiresAt を返します。ping は kind が oauth、keyId が None、そして clientId を返します。KeyResource と PingResource はユニオン型なので、clientId や expiresAt を読む前に object か kind で区別してください。

トークンは本人に代わって動き、本人と同じようにメールを読めます。キーと同じくサーバーに置いてください。

確認コード

未リリース

ドメインの削除や Webhook の変更などの重要な変更の前に、API はアクセストークンに対し、Web アプリが本人に求めるのと同じ確認コードを求めます。呼び出しは is_step_up_required が True の OpenEmailApiError を送出し、何も変更されていません。コードを求め、本人から受け取ったコードを確認してから、もう一度呼び出してください。API キーが求められることはありません。

step_up.py
from openemail import OpenEmailApiError try:    client.domains.delete(domain_id)except OpenEmailApiError as error:    if not error.is_step_up_required:        raise     challenge = client.security.begin_step_up()     if challenge['method'] == 'email':        prompt = f'Enter the code we emailed to {challenge.get("sentTo")}: '    else:        prompt = 'Enter the code from your authenticator app, or a backup code: '     client.security.verify_step_up({'code': input(prompt)})    client.domains.delete(domain_id)
メソッド機能
security.step_up_status()アプリがいま確認済みかどうか(elevated、elevatedUntil)、次のコードの確認方法(method、email または totp)、そして確認が有効な時間の長さである minutes。何も送信せず、一時停止も報告しません。
security.begin_step_up(body=None)確認を開始します。email の場合は本人がサインインに使うアドレスへ 6 桁のコードが送られ、sentTo にマスクされたアドレスが表示されます。totp の場合は本人が認証アプリのコードかリカバリーコードを使います。まだ開いていて試行回数が残っている確認は、{'resend': True} を渡さない限り再利用され、ロックされたか期限切れの確認は単純な呼び出しで置き換えられます。各アプリは本人ごとに 1 時間に 5 回、24 時間に 20 回まで開始でき、それを超えると 429 step_up_throttled を送出します。
security.verify_step_up({'code': code})コードを確認し、このアプリの重要な変更を 60 分間、elevatedUntil まで、REST と、同じ変更を行う MCP ツールの両方で解除します。このアプリから 24 時間に 10 回、または本人のすべてのアプリから合わせて 20 回誤ると、この呼び出しと begin_step_up は、確認がいつ再開するかを示すメッセージとともに 429 step_up_locked を送出します。

クライアントが自分からコードを求めたり、呼び出しをやり直したりすることはありません。begin_step_up も verify_step_up も自動では再試行されません。応答が失われたあとの再試行で、2 通目のメールが送られたり、試行回数を余分に消費したりするおそれがあるからです。スコープは不要で、API キーでどちらかを呼ぶと 400 step_up_not_applicable が返ります。STEP_UP_ERROR_CODES は確認が失敗するすべての理由を挙げており、それぞれの対処は API のエラーページにあります。