Zur Dokumentation springen
Ruby

Fehler

Jeder Fehlschlag löst eine Exception aus. Eine Klasse für eine Ablehnung, eine für eine ausbleibende Antwort und eine request id bei jedem API-Fehler.

Einen Fehler abfangen

rescue_errors.rb
message = {from: "[email protected]", to: "[email protected]", subject: "Your September invoice", text: "Invoice attached."} begin  client.emails.send(message)rescue OpenEmail::ApiError => error  warn "#{error.code} #{error.param} #{error.message}" if error.validation?  warn client.addresses.list_all.addresses.inspect if error.permission?  warn "try again in #{error.retry_after_seconds} seconds" if error.rate_limited?   warn "#{error.status} #{error.request_id}"  raiserescue OpenEmail::NetworkError => error  warn "no answer in time" if error.timeout?  raiseend

Ein permission_error bei einem Versand liegt meist am Sende-Scope des SCHLÜSSELS, an einer Domain oder einer Adresse, die ihm nicht zugestanden wurde, und nicht am Workspace. Darum gibt das Beispiel aus, was addresses.list_all als zulässige Absenderadressen dieses Schlüssels nennt.

Jede Art von Ablehnung hat eine eigene Unterklasse, ein rescue kann also anhand der Klasse auswählen, welche es behandelt, und den Rest nach oben durchlassen.

rescue_by_class.rb
message = {from: "[email protected]", to: "[email protected]", subject: "Your September invoice", text: "Invoice attached."} begin  client.emails.send(message)rescue OpenEmail::ValidationError => error  warn "#{error.param}: #{error.message}"rescue OpenEmail::AuthenticationError, OpenEmail::PermissionError => error  warn "the key cannot do this: #{error.code}"  raiserescue OpenEmail::Error => error  warn "#{error.class}: #{error.message}"  raiseend

Die Klassen

KlasseWann
OpenEmail::ErrorDie Basis jedes Fehlers, den das Gem definiert, rescue OpenEmail::Error fängt also alle ab. ArgumentError fängt es nicht ab.
OpenEmail::ApiErrorDie API hat geantwortet, und zwar nicht mit einem Erfolg. Trägt status, type, code, param, doc_url, request_id, retry_after_seconds, fields und body. Wird als diese Klasse selbst ausgelöst, wenn type gleich api_error ist, wie bei einem Serverfehler, und sonst als die Unterklasse für seinen type.
OpenEmail::InvalidRequestError, AuthenticationError, PermissionError, NotFoundError, ConflictError, ValidationError und RateLimitErrorUnterklassen von ApiError, eine für jeden type: invalid_request_error, authentication_error, permission_error, not_found_error, conflict_error, validation_error und rate_limit_error.
OpenEmail::NetworkErrorEs kam keine Antwort an: DNS, TLS, eine abgelehnte oder abgebrochene Verbindung oder das Timeout. Trägt original, die zugrunde liegende Exception, die auch seine cause ist, und timeout? ist true, wenn das Timeout der Grund war.
OpenEmail::WebhookSignatureErrorOpenEmail.verify_webhook_signature hat eine Zustellung abgelehnt.
ArgumentErrorWird ausgelöst, bevor etwas gesendet wird: ein fehlender oder fehlerhafter Schlüssel, eine unbrauchbare base_url:, eine leere id. Es ist die gewöhnliche Ruby-Klasse, kein OpenEmail::Error, weil es bedeutet, dass der Aufruf selbst falsch ist.

Was ein ApiError trägt

messageString
Der eigene Satz der API, für Menschen geschrieben, der den beanstandeten Wert nennt, sofern es einen gibt. Kein stabiler Bezeichner, verzweigen Sie also über `code`.
statusInteger
Der HTTP-Status der Antwort.
typeString
Einer der acht Werte in `OpenEmail::ERROR_TYPES`, einer eingefrorenen Menge, die nicht wachsen wird. Nennt der Body keinen, wird er aus dem Status abgeleitet.
codeString
Der konkrete Fehlschlag, etwa `from_address_forbidden` oder `invalid_email_address`. Offen und erweiterbar, behandeln Sie einen unbekannten daher als seinen `type`. Er ist `unrecognised_response`, wenn der Body nicht der Fehlerumschlag der API war.
paramString or nil
Das abgelehnte Feld als Pfad mit Punkten, etwa `to.0`, wenn der Fehlschlag eines nennt.
doc_urlString or nil
Eine Seite zu diesem Fehlschlag, wenn die API eine nennt.
request_idString or nil
Die id, unter der der Server die Anfrage protokolliert hat, aus dem Body oder dem Header `x-request-id`.
retry_after_secondsInteger, Float or nil
Die Wartezeit, die der Server in `Retry-After` verlangt hat, in Sekunden, ob er nun eine Zahl oder ein Datum gesendet hat. nil, wenn er keine gesendet hat.
fieldsArray<Hash> or nil
Ein Hash pro Problem, jeweils mit `key` und `error`, etwa `{key: "email", error: "email"}`, wenn `forms.subscribe` die Antworten mit einem 422 `invalid_form_submission` abgelehnt hat. nil, wenn der Fehler keine auflistet.
bodyHash or nil
Die gesamte Fehlerantwort, geparst, mit Symbol-Schlüsseln. nil, wenn sie leer oder kein JSON war.
PrädikatTrue, wenn
auth?type ist authentication_error, ein 401: kein Schlüssel, die falsche Art von Zugangsdaten oder ein Schlüssel, den wir nicht ausgestellt haben.
permission?permission_error, ein 403: ein echter Schlüssel ohne den Scope oder die From-Adresse, die er braucht.
scope_missing?code ist insufficient_scope, der 403, der einen fehlenden Scope nennt.
invalid_request?invalid_request_error, ein 400: eine Anfrage, die nicht verstanden werden konnte. Eine Nachricht über der Größenobergrenze kommt als 422 message_too_large zurück, validation? ist daher das Prädikat, das sie abfängt.
validation?validation_error, ein 422: Das Schema hat sie abgelehnt, und param nennt das Feld.
not_found?not_found_error, ein 404: keine solche Ressource.
conflict?conflict_error, ein 409: Die Ressource ist über den Punkt hinaus, an dem dies mit ihr möglich wäre.
rate_limited?rate_limit_error, ein 429. retry_after_seconds enthält die Wartezeit, wenn der Server eine genannt hat.
server_error?status ist 500 oder höher. Nennen Sie request_id, wenn Sie den Support kontaktieren.
retryable?status ist 408, 429, 500, 502, 503 oder 504.
step_up_required?code ist step_up_required, der 403, den ein OAuth-Zugriffstoken vor einer heiklen Änderung bekommt, bis die Person einen Code bestätigt hat.

Die meisten Prädikate lesen type, die eingefrorene Hälfte des Umschlags, und jede Unterklasse steht für einen type. code bleibt ein String, weil die API zusichert, dass er offen und erweiterbar ist. Behandeln Sie einen unbekannten daher als seinen type. Eine geschlossene Liste würde ein Gem-Upgrade zum Preis dafür machen, einen neuen Fehlerfall lesen zu können.

Ein Body, der nicht dem Fehlerumschlag der API entspricht, löst trotzdem einen OpenEmail::ApiError aus, wobei type aus dem Status abgeleitet und code auf unrecognised_response gesetzt wird. Ein Erfolg, dessen Body kein JSON ist, löst ebenfalls einen aus.

retryable? beschreibt den Status, nicht Ihren Aufruf. Ein Aufruf, der gefahrlos wiederholt werden kann, wurde bereits wiederholt, wenn er den Fehler auslöst, und ein 429 wie send_quota_exceeded oder ai_quota_exceeded scheitert auf dieselbe Weise, bis sein Kontingent zurückgesetzt wird. Zeigen Sie ihn also einer Person, statt ihn in einer Schleife zu wiederholen.

Eine Exception, die Ihr Adapter auslöst, wird zu einem OpenEmail::NetworkError, sobald alle Wiederholungen, die der Aufruf erlaubt, verbraucht sind, mit dem Original in original und cause. NameError, TypeError und ArgumentError sind die Ausnahmen: Sie bedeuten einen Fehler im Adapter und werden daher unverändert ausgelöst und nie wiederholt.

request_id

Jeder OpenEmail::ApiError trägt die vom Server gesendete request id, aus dem Fehler-Body oder dem Header x-request-id, und sie ist das Einzige, was Ihren Fehlschlag mit einer Zeile im Serverlog verbindet. Ein Erfolg gibt allein den geparsten Body zurück, an ihm gibt es daher keine request id zu lesen.