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

設定

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

オプション

clients.php
use OpenEmail\OpenEmail; $client = new OpenEmail(); OpenEmail::init(timeout: 10);OpenEmail::getClient()->me->ping(); $billing = new OpenEmail(apiKey: (string) getenv('OPENEMAIL_BILLING_API_KEY')); echo $client->mode, ' ', $billing->mode, PHP_EOL;
エントリーポイント得られるもの
new OpenEmail(...)渡した名前付き引数から作られるクライアント。省略したものは環境変数から読まれます。資格情報を渡さなければキーを OPENEMAIL_API_KEY から、またはトークンを OPENEMAIL_ACCESS_TOKEN から読み、ベース URL を渡さなければ OPENEMAIL_BASE_URL から読みます。
OpenEmail::createClient(...)new OpenEmail(...) と同じクライアント。ファクトリを呼ぶ書き方を好むコード向けです。
OpenEmail::init(...)クライアントを作り、共有クライアントとして保持して返します。同じ名前付き引数を受け取ります。
OpenEmail::getClient()プロセス内のどこからでも使える共有クライアント。init より前に呼ぶと、最初の呼び出し時に環境変数からクライアントを作ります。
OpenEmail::resetClient()共有クライアントを破棄し、次の getClient() で新しいクライアントが作られるようにします。テストのケース間で必要になるのはこれです。

getenv() を文字列にキャストしているのは意図的です。設定されていない変数は空のキーになり、クライアントは必要な変数名を示すメッセージとともにそれを拒否します。null だと、何も言わずに OPENEMAIL_API_KEY にフォールバックしてしまいます。

options.php
use OpenEmail\Http\CurlHttpClient;use OpenEmail\OpenEmail; $client = new OpenEmail(    apiKey: (string) getenv('OPENEMAIL_API_KEY'),    baseUrl: 'https://api.openemail.uk',    httpClient: new CurlHttpClient(),    maxRetries: 2,    timeout: 30,    userAgent: 'billing-service/1.4',    headers: ['X-Team' => 'billing'],    disableUpdateNotice: true,);
オプション既定値備考
apiKey:OPENEMAIL_API_KEYoe_live_ か oe_test_ で始まる必要があります。apiKey: も accessToken: も渡さないときに限り、環境変数から読まれます。
accessToken:OPENEMAIL_ACCESS_TOKENOAuth アクセストークン、またはそれを返す callable。下の「OAuth アクセストークン」を参照してください。キーかトークンのどちらか一方を渡し、両方は渡さないでください。
baseUrl:https://api.openemail.ukまたは OPENEMAIL_BASE_URL。末尾のスラッシュは取り除かれ、ホスト名だけの場合は先頭に https:// が、このマシン上のホスト(localhost、127.x.x.x のアドレス、::1)の場合は http:// が付きます。資格情報がそれ以外のホストへ平文の http で送られることはなく、0.0.0.0 や [::] はクライアント作成時に拒否されます。これらはサーバーが待ち受けるアドレスであって、リクエストの送り先ではないからです。
timeout:30呼び出しごとではなく試行ごとの秒数で、接続とレスポンス全体の読み取りを含みます。0 で無効になります。files->upload は、その呼び出しで timeout: を渡さない限り、少なくとも 600 秒待ちます。
maxRetries:2繰り返しても安全な呼び出しについて、初回のあとの追加試行回数です。呼び出しごとではなくクライアントに設定します。0 でリトライを無効にします。
httpClient:CurlHttpClientHTTP 層。OpenEmail\Http\HttpClient を実装するものなら何でもよく、Guzzle や Symfony HttpClient を包む Psr18HttpClient や、テスト用のフェイクも使えます。それぞれについては HTTP クライアントのページで説明しています。
headers:[]すべてのリクエストに付与されます。
userAgent:openemail-php/<version>すべてのリクエストに付与されます。
disableUpdateNotice:falsePackagist に新しいバージョンがないかを、プロセスごとに 1 回確認する処理を省きます。この確認はコマンドラインで、標準出力がターミナルのときにしか動かず、OPENEMAIL_DISABLE_UPDATE_NOTICE でも無効にできます。

環境変数

変数機能
OPENEMAIL_API_KEYapiKey: も accessToken: も渡さないときにクライアントが使うキー。
OPENEMAIL_ACCESS_TOKENOAuth アクセストークン。どちらの資格情報も渡さず、OPENEMAIL_API_KEY も設定されていないときにだけ読まれるため、環境変数にキーがあればそちらが優先されます。
OPENEMAIL_BASE_URL何も渡さないときのベース URL。localhost:2222 のようなホスト名だけの値にはスキームが付け加えられます。
OPENEMAIL_DISABLE_UPDATE_NOTICE空でない値であれば何でも、プロセス内のすべてのクライアントで更新通知を無効にします。
HTTPS_PROXY と NO_PROXY、または https_proxy と no_proxycURL が経由するプロキシと、直接接続するホスト。下の「プロキシと TLS」を参照してください。

各変数はまず getenv() で、次に $_SERVER と $_ENV から読まれるため、フレームワークが .env ファイルから読み込んだ値も有効です。設定されていても空の変数は、未設定として扱われます。

送信前に拒否されるもの

これらは、最初の送信で分かりにくい失敗として表面化するのではなく、誤った値を含む行から OpenEmail\Exception\InvalidArgumentException をスローします。メッセージには何が誤っていて代わりに何を渡すべきかが書かれ、資格情報がそのまま繰り返されることはありません。

拒否される条件理由
資格情報がまったくないapiKey: も accessToken: も渡されず、どちらの変数も設定されていなかったため、認証に使うものがありません。クライアントの作成時にスローされます。
キーとトークンを同時に指定どのリクエストも資格情報を 1 つしか運ばないため、クライアントにはどちらを意図したのか判断できません。
セッション Cookie、セッショントークン、または別のサービスのキーここで認証できるのは oe_live_ と oe_test_ だけで、API もそう応答します。このチェックはプレフィックスを見るだけなので、失効したキーは実際に通信した段階で AuthenticationException として失敗します。
http または https の URL ではない baseUrl:、またはユーザー名やパスワードを含むものそれ以外には接続できず、資格情報は URL ではなく apiKey: か accessToken: に入れるものです。クライアントの作成時にスローされます。
このマシン上にないホストへ、暗号化されていない http で資格情報を送ろうとする何かが送信される前に、呼び出しがスローします。https のベース URL を使ってください。
負の timeout:秒数を渡すか、タイムアウトなしなら 0 を渡してください。クライアントの作成時に、または 1 回の呼び出しに渡したタイムアウトならその呼び出しでスローされます。
トークンとして正しくないヘッダー名、またはヘッダー値に含まれる改行やその他の制御文字headers:、userAgent:、idempotencyKey: でチェックされます。改行があると 2 つ目のヘッダーが始まってしまうからです。値の前後にある空白、タブ、改行は、fetch と同じように先に取り除かれるため、末尾が改行のファイルから読み込んだキーもそのまま使えます。
どのメソッドでも空、またはドットだけの idメソッド呼び出し時にスローされます。ドットだけのパスセグメントはどの URL パーサーでも除去されるため、リクエストが別のエンドポイントに届いてしまいます。有効な UTF-8 ではない id も拒否されます。
base64 ではない添付ファイルの内容文字列は常に base64 として読まれるため、生のバイト列を入れるとでたらめなデータが送られてしまいます。OpenEmail::toBase64() でエンコードするか、SplFileInfo、ストリーム、PSR-7 ストリームを渡せば、クライアントがエンコードします。

このクラスは PHP 標準の InvalidArgumentException を継承しているため、すでにそれを catch しているコードはそのまま動きます。また、パッケージがスローする他のすべての例外と同じく OpenEmail\Exception\OpenEmailException を実装しています。文字列の id を渡すべきところに数値を渡すような型の誤りは、PHP 自身による TypeError になります。すべてのメソッドが型を宣言しているからです。

testMode: というオプションはなく、今後も追加されません。キーの体系はヒントではなく資格情報の一部なので、モードはキーの属性です。$client->mode はプレフィックスを読んで live か test を返すだけで、何も判断しません。

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

クライアントは一度作って共有してください。リクエストごとに新しいクライアントを作ると、開いている接続を無駄に捨てることになり、しかもその状態に呼び出し元ごとのものは何もありません。

複数のワークスペースに代わって送信するジョブのように、本来ならキーごとにクライアントが必要になる場合は、呼び出しで apiKey: を渡してください。そのリクエストの Authorization ヘッダーを置き換え、クライアントには何も残しません。

per_call_key.php
$message = [    'from' => '[email protected]',    'to' => '[email protected]',    'subject' => 'Your invoice',    'text' => 'Attached.',];$workspaceKey = (string) getenv('OPENEMAIL_API_KEY'); $client->emails->send($message); $client->emails->send($message, apiKey: $workspaceKey); $client->threads->list(folder: 'inbox', apiKey: $workspaceKey);$client->webhooks->list(apiKey: $workspaceKey);

tempMail 以外のすべてのメソッドは、これを最後の名前付き引数として受け取ります(一覧ではフィルターの後に渡します)。tempMail のメソッドは代わりに inboxToken: を受け取ります。リクエスト送信前に、クライアントと同じ規則でチェックされるため、タイプミスは、後で探し回ることになる資格情報についての 401 ではなく、この呼び出しに渡された apiKey についての InvalidArgumentException をスローします。リトライされた呼び出しは、渡されたキーをそのまま使い続けます。

$client->mode はクライアントの「作成時」のキーを表し、上書きには追従しません。1 つのクライアントが複数のキーを扱うようになると、報告すべき単一のモードは存在しないため、渡したキーから読み取ってください。var_dump($client) はモードとベース URL を表示し、キーは決して表示しません。また、資格情報を受け取る引数にはすべて #[\SensitiveParameter] が付いているため、スタックトレースにはその代わりにプレースホルダーが出力されます。

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

$client->raw はすべてのメソッドが通るトランスポートです。$client->raw->request() は、まだどのメソッドもラップしていないパスを、クライアントの資格情報、ベース URL、タイムアウト、リトライ方針を適用して呼び出し、メソッドと同じようにデコード済みのボディを返します。

raw_request.php
$ping = $client->raw->request('/ping'); $label = $client->raw->request('/labels', method: 'POST', body: ['name' => 'Invoices']); var_dump($ping, $label);
名前付き引数機能
method:指定しない限り GET。ほかに POST、PUT、PATCH、DELETE。
query:クエリパラメーターの配列。null と空の値は省かれ、リストはカンマで連結され、DateTimeInterface は UTC の ISO 8601 の時刻として送られます。
body:JSON として送られる配列。
raw: と contentType:そのまま送るバイト列。文字列、ストリームリソース、SplFileInfo、PSR-7 ストリームのいずれかで、型を指定しない限り application/octet-stream になります。
accept: と binary:JSON 以外の accept: はボディをテキストとして返し、binary: true はバイト列の文字列として返します。
idempotent: と idempotencyKey:idempotent: true は Idempotency-Key を付与します。自分で渡さない限り自動生成されます。
repeatable:失敗時にリトライするかどうか。repeatable: true を渡さない限り、リトライされるのは GET だけです。
anonymous:true を渡すと、資格情報をまったく送りません。
apiKey:、inboxToken:、timeout:呼び出しごとの資格情報と同じもの、およびこの呼び出しだけに適用される秒単位のタイムアウト。

パスは 1 つの / で始まる必要があります。完成した URL がベース URL のオリジンから外れるパスは、何かが送信される前に InvalidArgumentException をスローするため、資格情報が別のホストに届くことはありません。

使い捨て受信トレイ

OpenEmail::createTempMail() は、API キーを持たず環境変数からも読まない、使い捨て受信箱用のクライアントを作ります。受信箱は匿名で作成され、読み取りのたびに create が返した受信箱トークン、または extend が返した新しいトークンを送ります。トークンは呼び出しごとに inboxToken: として渡すか、OpenEmail::createTempMail(inboxToken: ...) として一度だけ渡します。

temp_mail.php
use OpenEmail\OpenEmail; $tempMail = OpenEmail::createTempMail(); $inbox = $tempMail->create();$page = $tempMail->listMessages($inbox['id'], inboxToken: $inbox['token']); echo count($page->items), ' ', $page->expiresAt, PHP_EOL;

OpenEmail::createTempMail() は他のクライアントと同じく baseUrl:、httpClient:、maxRetries:、timeout:、userAgent:、headers:、disableUpdateNotice: を受け取り、ベース URL を渡さないときは OPENEMAIL_BASE_URL を読みます。

OAuthアクセストークン

コマンドラインツールやエージェントのように、人が OAuth で接続したアプリは、API キーではなくアクセストークンを持っています。これを accessToken: として渡します。トークンそのものか、クロージャーや第一級 callable のようにトークンを返す callable を渡せます。callable は呼び出しごとに 1 回実行され、その呼び出しのリトライは返された値を再利用するため、期限切れが近づいたらその中でトークンを更新すれば、クライアントを作り直す必要はありません。

access_token.php
use OpenEmail\OpenEmail; $tokens = ['current' => 'token-from-your-oauth-flow']; $oauthClient = new OpenEmail(accessToken: fn(): string => $tokens['current']); $me = $oauthClient->me->get(); if ($me['object'] === 'oauth_token') {    echo $me['clientId'], ' ', $me['expiresAt'], PHP_EOL;}
ケース起きること
apiKey: と accessToken: の両方、またはどちらもなしクライアントの作成時に InvalidArgumentException をスローします。どちらもない場合、メッセージは OPENEMAIL_API_KEY と OPENEMAIL_ACCESS_TOKEN に言及します。
トークンではない値トークンは 1〜512 文字で、oe_ で始まりません。これが OpenEmail::isAccessToken() の行うチェックです。これに通らない文字列はクライアントの作成時に拒否され、そうした値を返す callable は、何かが送信される前に呼び出しに InvalidArgumentException をスローさせます。
OPENEMAIL_ACCESS_TOKENどちらの資格情報も渡さず、OPENEMAIL_API_KEY も設定されていないときに読まれます。そのため環境変数にキーがあればそちらが優先されます。
例外をスローする callable呼び出しはその例外をそのままスローし、何も送信されません。
呼び出しごとの apiKey:そのリクエストに限ってトークンを置き換え、callable は呼ばれません。
$client->modeトークンでは常に live です。
OpenEmail::createTempMail()環境に何があっても、資格情報は送信しません。
me->get() と me->ping()トークンの場合、get は object が oauth_token、id と roleId が null で、接続されたアプリの clientId と、本人によるアプリの承認が切れる時刻 expiresAt を返します。ping は kind が oauth、keyId が null で、clientId を返します。id や keyId を読む前に object か kind を確認してください。

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

確認コード

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

step_up.php
use OpenEmail\Exception\ApiException; $domainId = 'b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f'; try {    $client->domains->delete($domainId);} catch (ApiException $error) {    if (!$error->isStepUpRequired()) {        throw $error;    }     $challenge = $client->security->beginStepUp();     if ($challenge['method'] === 'email') {        echo 'Enter the code we emailed to ', $challenge['sentTo'], PHP_EOL;    } else {        echo 'Enter the code from your authenticator app, or a backup code', PHP_EOL;    }     $client->security->verifyStepUp(['code' => trim((string) fgets(STDIN))]);    $client->domains->delete($domainId);}
メソッド機能
security->stepUpStatus()アプリがいま確認済みかどうか(elevated、elevatedUntil)、次のコードの確認方法(method、email または totp)、そして確認が有効な時間の長さである minutes。何も送信せず、一時停止も報告しません。
security->beginStepUp()確認を開始します。email では、本人がサインインに使うアドレスに 6 桁のコードが届き、sentTo がそれを伏せた形で示します。totp では、本人が認証アプリからコードを読むか、バックアップコードを使います。まだ開いていて試行回数が残っている確認は、['resend' => true] を渡さない限り再利用され、ロックされたものや期限切れのものは通常の呼び出しで置き換えられます。各アプリは本人ごとに 1 時間に 5 回、24 時間に 20 回まで確認を開始でき、それを超えると 429 step_up_throttled をスローします。
security->verifyStepUp(['code' => ...])コードを確認し、REST と、同じ変更を行う MCP ツールを通じて、このアプリの重要な変更を 60 分間、elevatedUntil まで許可します。このアプリから 24 時間に 10 回、または本人のすべてのアプリの合計で 20 回コードを誤ると、この呼び出しと beginStepUp は、確認をいつ再開できるかを示すメッセージ付きで 429 step_up_locked をスローします。

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

更新通知

Packagist にパッケージの新しいバージョンがあると、クライアントはプロセスごとに 1 回、標準エラーに ℹ openemail/sdk 0.0.2 is available, you are on 0.0.1. のような行を出力し、続けてパッケージのページを示します。このチェックはコマンドラインで、標準出力がターミナルのときだけ実行され、Web サーバー上では決して実行されません。最初のクライアントの作成時に始まってリクエストと並行して進み、スクリプトの終わりには 2 秒の持ち時間の残りだけ待ちます。Packagist に接続できなくても無視されます。

このチェックはクライアントの httpClient: を通さず、cURL で独自にリクエストを送るため、テストのフェイク HTTP クライアントにそれが見えることはありません。無効にするには disableUpdateNotice: true を渡すか、OPENEMAIL_DISABLE_UPDATE_NOTICE を設定してください。

プロキシと TLS

既定の CurlHttpClient はプロキシを cURL に任せます。cURL は https_proxy または HTTPS_PROXY からプロキシを、no_proxy または NO_PROXY から直接接続するホストを読み取ります。代わりにコードで指定するには proxy: を渡します。プロキシ URL に含まれるユーザー名とパスワードはプロキシに送られます。

curl_options.php
use OpenEmail\Http\CurlHttpClient;use OpenEmail\OpenEmail; $client = new OpenEmail(httpClient: new CurlHttpClient(    caBundle: '/etc/ssl/certs/corporate-ca.pem',    proxy: 'http://proxy.internal:3128',    curlOptions: [CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4],));

接続には TLS 1.2 以降を使い、サーバーの証明書とホスト名を検証します。リダイレクトに従うことはありません。caBundle: は、TLS を検査するプロキシのために、信頼する認証局を指定します。curlOptions: はその他の任意の cURL オプションを設定しますが、URL とそのポート、メソッド、ヘッダー、ボディ、リダイレクトの無効化といった、リクエストに必要な設定が常に優先されます。CURLOPT_REQUEST_TARGET は拒否され、cURL が受け付けないオプションは、その名前を示す InvalidArgumentException をスローします。