Eine E-Mail senden
`emails->send`: eine Nachricht, jetzt oder später.
emails->send
$email = $client->emails->send([ 'from' => ['email' => '[email protected]', 'name' => 'Acme Billing'], 'to' => ['[email protected]', 'Grace <[email protected]>'], 'cc' => '[email protected]', 'bcc' => [['email' => '[email protected]']], 'replyTo' => '[email protected]', 'subject' => 'Your September invoice', 'html' => '<p>Invoice attached.</p>', 'text' => 'Invoice attached.', 'headers' => ['X-Campaign' => 'invoices'], 'attachments' => [['filename' => 'invoice.pdf', 'content' => new \SplFileInfo('invoice.pdf')]], 'threadId' => 'CAHk7pQ2x9LmZ4-mail.example.com', 'scheduledAt' => 'PT1H', 'tags' => ['order' => '4021'], 'tracking' => ['opens' => true, 'clicks' => true],]); echo $email['id'], ' ', $email['status'], PHP_EOL;to, cc und bcc nehmen einen Empfänger oder eine Liste von Empfängern entgegen, und ein einzelner wird für Sie verpackt. Jeder darf eine bloße Adresse, Name <addr@host> oder ein Array mit email und name sein.
Die Nachricht ist ein Array mit den Feldnamen der API als Schlüsseln, deshalb bleiben replyTo und scheduledAt in camelCase, während idempotencyKey: und apiKey: benannte Argumente des Aufrufs und nie Teil der Nachricht sind. Um ein Feld einer Nachricht zu ändern, die Sie zuvor gebaut haben, entpacken Sie sie in ein neues Array: $client->emails->send([...$message, 'subject' => 'Re: your invoice']) behält jedes andere Feld und ersetzt den Betreff.
Parameter
fromstring or arrayerforderlich- Der Absender. Eine bloße Adresse, `Name <addr@host>` oder ein Array mit `email` und `name`. Muss eine Adresse sein, als die dieser Schlüssel senden darf, sonst wirft der Aufruf einen 403 `from_address_forbidden`. Es gibt keinen Ersatzabsender, ein Versand nennt also immer die Adresse, von der er ausgeht.
tostring or arrayerforderlich- Ein Empfänger oder eine Liste von Empfängern, und ein einzelner wird für Sie verpackt. Höchstens 50 über `to`, `cc` und `bcc` zusammen, mehr ergibt einen 422 `too_many_recipients`.
ccstring or array- Zählt gegen das Limit von 50 Empfängern.
bccstring or array- Wird in den Bytes, die andere erhalten, nie genannt, denn pro Empfänger wird ein eigener Umschlag übertragen. Zählt ebenfalls zu den 50.
replyTostring or array- Eine einzelne Adresse, wird als Reply-To-Header gesendet.
subjectstring- Höchstens 998 Zeichen, das Zeilenlimit von RFC 5322. Standardmäßig leer, und ein leerer Betreff fällt auf den des Templates oder des Entwurfs zurück.
htmlstring- Eines von `html`, `text`, `draftId` oder `template` ist erforderlich. HTML ist das, was Empfänger sehen, wenn sowohl `html` als auch `text` angegeben sind. Höchstens 1.000.000 Zeichen.
textstring- Der Nur-Text-Teil, höchstens 1.000.000 Zeichen.
templatearray- Rendert ein gespeichertes Template serverseitig: ein Array mit `id`, das eine id oder einen Slug nimmt, und optional `version` (ein int), `props` und `slots`. `version` schreibt eine Revision fest. Lassen Sie es weg, um das zu verwenden, was bei Annahme der Anfrage veröffentlicht ist. Ein unbekanntes oder fehlendes Prop ergibt einen 422 und keine Lücke in der Nachricht.
draftIdstring- Sendet einen gespeicherten Entwurf unter diesem Umschlag, so wie er geschrieben wurde. Kann nicht mit `template` oder `translate` kombiniert werden.
headersarray- Header-Name auf String-Wert, beschränkt auf `X-*`, `List-*`, Reply-To, Precedence, Auto-Submitted, Importance, Priority und Feedback-ID. Alles, was der Transport selbst setzt, wird mit einem 422 `reserved_header` abgelehnt statt stillschweigend verworfen.
attachmentsarray- Eine Liste, jeder Eintrag ein Array mit `filename`, `content` und optional `contentType` oder ein Array nur mit `fileId`, das eine bereits im Workspace liegende Datei benennt, etwa eine aus `files->upload`. `content` ist base64: Ein Stream aus `fopen`, eine `SplFileInfo` oder ein PSR-7-Stream wird für Sie gelesen und kodiert, und ein String muss bereits base64 sein. 20 Dateien, wobei eingebettete Dateien nach dem Dekodieren zusammen auf 5 MB begrenzt sind. Eine gespeicherte Datei darf größer sein und reist als Download-Link.
attachmentDeliverystring- `mime`, `link` oder `auto`. `auto` überträgt Dateien als Download-Links, sobald sie 2 MB überschreiten und die Domain eine aktive Dateien-Domain hat, und andernfalls innerhalb der Nachricht. Weggelassen gilt die Postfacheinstellung, die standardmäßig `auto` ist.
threadIdstring- Antwort in einen bestehenden Thread. Der Transport schreibt In-Reply-To und References.
scheduledAtDateTimeInterface or string- Ein `DateTimeInterface`, gesendet als Zeitpunkt nach ISO 8601 in UTC, ein Zeitpunkt nach ISO 8601 als String oder eine Dauer wie `PT1H`. Bis zu einem Jahr im Voraus, nie in der Vergangenheit. Kann nicht mit `cancellableForSeconds` kombiniert werden. Ein Datums-String ohne Uhrzeit, etwa `2027-01-01`, wird als Mitternacht UTC an diesem Tag gelesen. Übergeben Sie also einen Zeitpunkt, wenn die Uhrzeit wichtig ist.
cancellableForSecondsint- 0 bis 900. Ein Rückgängig-Fenster bei einem sofortigen Versand: der Rückgängig-Mechanismus des Composers, offengelegt statt fest verdrahtet.
tagsarray- Bis zu 10 Labels, mit Schlüsseln aus 1 bis 64 Buchstaben, Ziffern, `_` oder `-` und String-Werten bis 256 Zeichen. Werden bei jedem Lesen zurückgegeben und nie interpretiert.
signaturebool- Ob diese Nachricht die Signatur der Absenderadresse trägt: die eigene dieser Adresse, sonst bei einer von einem Catch-all aufgefangenen Adresse die des Catch-all, sonst die OpenEmail-Fußzeile, sofern diese Adresse sie nicht ausgeschaltet hat. Ohne Angabe geht ein `html`-Text genau so hinaus, wie er geschrieben ist, ohne Signatur, und ein reiner `text`-Text trägt sie. Setzen Sie es auf false für Mail, die ein Programm im Namen einer Person sendet, etwa eine Quittung, ein Passwort-Reset oder eine Zusammenfassung, unter denen niemand die Unterschrift einer Person erwartet. Template-Versände und verschlüsselte Versände tragen nie eine.
trackingarray- Ein Array mit den optionalen Schlüsseln `opens` und `clicks`, jeweils ein bool: ob für diese Nachricht ein Öffnungs-Pixel hinzugefügt und Links umgeschrieben werden. Inaktiv, sofern das Tracking nicht für die Absenderadresse (oder den Catch-all, der sie aufgefangen hat) eingeschaltet wurde, und jeder hier angegebene Schlüssel entscheidet diese eine Nachricht, unabhängig davon, wie die Adresse eingestellt ist.
translatearray- Sendet sie in der Sprache des Empfängers: ein Array mit `to` und optional `from`, `subject` und `includeOriginal`. `to` nimmt einen Code, einen englischen Namen oder den Eigennamen der Sprache entgegen, und `subject` und `includeOriginal` sind beide standardmäßig true. Wird bei Annahme der Anfrage festgelegt, eine geplante Nachricht trägt daher genau die freigegebenen Worte. Wird zusammen mit `draftId` abgelehnt.
idempotencyKeystring- Ein benanntes Argument des Aufrufs, kein Feld der Nachricht. Ihr eigener Key für diesen Versand, 1 bis 255 Zeichen aus Buchstaben, Ziffern, `_`, `.`, `:` oder `-`. Ohne ihn erzeugt der Client für jeden Aufruf einen Key, sodass seine eigenen Wiederholungen nie zweimal senden, und mit ihm wird ein Versand, der in einem anderen Prozess erneut läuft, erneut abgespielt statt wiederholt.
apiKeystring- Ebenfalls ein benanntes Argument. Sendet mit diesem Schlüssel statt mit dem des Clients, für einen Prozess, der im Namen mehrerer Workspaces sendet.
Antwort
Ein Array mit den camelCase-Namen der API als Schlüsseln, $email['status'] liest also den Status.
idstring- Die Versand-id, `msg_` gefolgt von 24 Hex-Zeichen. Verwenden Sie sie für `get`, `cancel`, `reschedule` und `getTracking`.
statusstring- queued, scheduled, sending, sent, partial, bounced, cancelled oder failed. Lesen Sie dies und nicht die Tatsache, dass der Aufruf zurückgekehrt ist: Ein sofortiger Versand wird innerhalb der Anfrage ausgeliefert und kommt meist als `sent`, `partial` oder `failed` zurück, ein zurückgehaltener als `queued` oder `scheduled`. `partial` ist ein eigener Zustand: Einige Empfänger haben die Nachricht, und das lässt sich nicht rückgängig machen. Ein erneuter Versuch ist daher falsch, und einen Fehlschlag zu melden ist eine Lüge.
modestring- `live` oder `test`: welche Art von Schlüssel sie gesendet hat. Ein Testversand wird aufgezeichnet und nie übertragen. Er zeigt `sent`, mit `transport` gleich `test`. Prüfen Sie also die Antwort und nicht einen Posteingang.
fromstring- Die tatsächlich autorisierte und auf die Leitung gegebene Adresse, die nicht immer die angeforderte ist.
subjectstring or null- Wie gesendet.
messageIdstring or null- Die Message-ID nach RFC 5322. null, bis das MIME existiert. Der Versanddienst schreibt den Header auf dem Weg hinaus um, kein Bounce und kein Zustellbericht trägt daher diesen Wert. `id` ist das, worüber ein Ereignis zurückkommt.
threadIdstring or null- Der Thread, in dem sie gelandet ist.
transportstring or null- Wie die Nachricht hinausging. null bis zum Versand.
attemptsint- Wie oft der Versand versucht wurde.
lastErrorstring or null- Warum der letzte Versuch fehlschlug, wörtlich.
scheduledAtstring or null- Der Zeitpunkt nach ISO 8601, zu dem sie hinausgehen soll.
cancellableUntilstring or null- Solange die aktuelle Zeit davor liegt, funktioniert `cancel` noch.
sentAtstring or null- Der Zeitpunkt nach ISO 8601, zu dem sie hinausging.
tagsarray- Was Sie gesendet haben, zurückgegeben.
sourcestring- composer, api, mcp, ai oder queue: welche Oberfläche angefragt hat. `api` ist dieser Client.
createdAtstring- Der Zeitpunkt nach ISO 8601, zu dem der Datensatz geschrieben wurde.
replayedbool- True, wenn ein Idempotency-Key auf einen bereits existierenden Versand passte. Es wurde nichts Neues gesendet, und dies ist die ursprüngliche Nachricht in ihrem aktuellen Zustand.
translationarray- Nur bei einer übersetzten Nachricht vorhanden, und nur dort, wo die gesamte gespeicherte Anfrage mitgeführt wird: in dieser Antwort und bei `get`. Es enthält `language`, `languageName`, `detectedSourceLanguage`, `subject` und `includeOriginal`, mit Codes statt ganzer Sprachzeilen. Eine Listenzeile hat es nie, sein Fehlen dort sagt daher in keine Richtung etwas aus.
In der Sprache des Empfängers
translate verfasst die Nachricht vor dem Versand in der Sprache eines anderen. Der Body und, sofern Sie das nicht abschalten, der Betreff werden übersetzt, sobald die API die Anfrage annimmt, und was dabei herauskam, geht hinaus: Eine Übersetzung, die nicht erzeugt werden konnte, lässt den Versand scheitern, statt die Nachricht in der Sprache zu verschicken, in der Sie sie geschrieben haben.
$email = $client->emails->send([ 'from' => '[email protected]', 'to' => '[email protected]', 'subject' => 'Your September invoice', 'html' => '<p>Invoice attached. Payment is due on the 14th.</p>', 'translate' => ['to' => 'de'],]); print_r($email['translation'] ?? []);$email['translation'] enthält dann language mit de, languageName mit German, detectedSourceLanguage mit en sowie subject und includeOriginal, beide true.
Niemand hat das gelesen, bevor es hinausging. emails->translate ist derselbe Weg, einen Schritt früher angehalten. Zeigen Sie das Ergebnis einer Person, lassen Sie sie es ändern und senden Sie dann das Freigegebene ganz ohne translate am Aufruf. Es erneut zu übergeben würde ein zweites Mal übersetzen und ihre Änderungen verwerfen.
$preview = $client->emails->translate([ 'subject' => 'Your September invoice', 'html' => '<p>Invoice attached. Payment is due on the 14th.</p>', 'to' => 'de',]); echo $preview['language']['native'], PHP_EOL, $preview['subject'], PHP_EOL, $preview['html'], PHP_EOL;echo 'Send it as it is? [y/N] '; $answer = fgets(STDIN); if ($answer !== false && strtolower(trim($answer)) === 'y') { $client->emails->send([ 'from' => '[email protected]', 'to' => '[email protected]', 'subject' => $preview['subject'], 'html' => $preview['html'], ]);}use OpenEmail\Constants\Languages;use OpenEmail\OpenEmail; echo count(Languages::ALL), PHP_EOL; $current = $client->languages->list();echo count($current), PHP_EOL; echo OpenEmail::resolveLanguage('Deutsch')['code'] ?? 'none', PHP_EOL;echo OpenEmail::resolveLanguage('zh-TW')['code'] ?? 'none', PHP_EOL;echo OpenEmail::languageByCode('DE')['native'] ?? 'none', PHP_EOL;var_dump(OpenEmail::isRtlLanguage('ar'));Diese Zeilen geben 200 aus, die Zeilen, mit denen diese Version ausgeliefert wird, dann die Anzahl, die die API jetzt hält, dann de, zh-Hant, Deutsch und bool(true). Die Tabelle ist in der Reihenfolge des Auswahlfelds als OpenEmail\Constants\Languages::ALL mitgeliefert, eine Liste von Arrays mit code, label, native, flag und rtl, ein Auswahlfeld lässt sich daher schon vor der ersten Anfrage füllen. languages->list gibt dieselben Zeilen von der Leitung als einfache Liste zurück, für Aufrufer, denen die aktuellen lieber sind als die, mit denen diese Version ausgeliefert wurde. OpenEmail::resolveLanguage() nimmt einen Code, einen englischen Namen, ein Endonym oder einen Alias entgegen (zh-TW ist ein Alias eines nicht mehr gelisteten Codes) und gibt null zurück, wenn nichts passt, OpenEmail::languageByCode() trifft einen exakten Code ohne Beachtung der Groß- und Kleinschreibung, und OpenEmail::isRtlLanguage() sagt, ob eine Sprache von rechts nach links läuft, wie es sechzehn der Zeilen tun. Durchsuchen Sie native, label und code gemeinsam, zeigen Sie native zuerst und speichern Sie den Code.
emails->translate wird nicht automatisch wiederholt. Es verbraucht Modellaufrufe und schreibt nichts, es gibt also nichts idempotent zu machen, und eine Wiederholung nach einer unbeantworteten Anfrage würde dieselbe Antwort nur zweimal bezahlen.
- Eine Sprache, die die API nicht zuordnen kann, ergibt einen
validation_errorauftranslate.to, bevor irgendetwas gesendet wird. translation_too_longbei über 30.000 Zeichen,translation_not_configured, wenn für die Installation keine KI konfiguriert ist, ein 429ai_quota_exceeded, wenn der Workspace die KI-Aktionen für heute verbraucht hat (es wird um Mitternacht UTC zurückgesetzt und nicht erneut versucht),translation_failed, wenn der Anbieter nicht geantwortet hat. Keiner dieser Fälle sendet die Nachricht ersatzweise unübersetzt.- Funktioniert mit
template: Übersetzt wird die GERENDERTE Ausgabe, ein gespeicherter Body bedient daher jede Sprache, in der Ihre Kunden lesen. Ein Template, das ein ganzes Dokument rendert, behält seinen doctype, seine<style>-Blöcke und seine@font-face-Regeln: Nur der Body geht an das Modell, der Rest wird wieder darum gelegt. Sein<title>bleibt unangetastet, was ohnehin nirgends angezeigt wird. - Eine Wiederholung kostet nichts zusätzlich. Die Übersetzung ist nicht Teil des Idempotenz-Fingerabdrucks (die Anfrage schon,
translateeingeschlossen), eine Wiederholung eines unbeantworteten Versands mit demselbenIdempotency-Keyspielt daher die bereits existierende Nachricht erneut ab, statt ein zweites Mal zu übersetzen und zu senden. - Eine übersetzte Nachricht, die queued oder scheduled ist, behält ihren freigegebenen Wortlaut.
emails->rescheduleverschiebt sie weiterhin, währendemails->updateeinen neuen Wortlaut mit einem 409translation_lockedablehnt. Ihren Inhalt zu ändern bedeutet also, abzubrechen und erneut zu senden.
Anhänge
content ist auf der Leitung base64. Geben Sie dem Client etwas, das er lesen kann, dann kodiert er die Bytes für Sie: eine Stream-Ressource aus fopen, eine SplFileInfo oder einen PSR-7-Stream oder eine hochgeladene Datei. Ein String wird so gesendet, wie er ist, er muss also bereits base64 sein, und genau das macht OpenEmail::toBase64() aus Bytes, die Sie im Speicher halten.
use OpenEmail\OpenEmail; $attachments = [ ['filename' => 'invoice.pdf', 'content' => OpenEmail::toBase64(file_get_contents('invoice.pdf')), 'contentType' => 'application/pdf'], ['filename' => 'report.csv', 'content' => new \SplFileInfo('report.csv')], ['filename' => 'contacts.csv', 'content' => fopen('contacts.csv', 'rb')], ['fileId' => 'file_6bb640f5b99e47deb758f1f5'],]; $client->emails->send([ 'from' => '[email protected]', 'to' => '[email protected]', 'subject' => 'Your documents', 'text' => 'All three are attached.', 'attachments' => $attachments,]);Ein String in content, der kein base64 ist, wirft eine OpenEmail\Exception\InvalidArgumentException, bevor etwas gesendet wird. Rohe Bytes, die zufällig als base64 lesbar sind, würden stattdessen verstümmelt hinausgehen. Übergeben Sie die Bytes einer Datei also nie unverändert: Verpacken Sie sie in OpenEmail::toBase64() oder übergeben Sie die Datei selbst.
OpenEmail::toBase64() steht bereit, wenn Sie dieselbe Kodierung anderswo brauchen. Es nimmt einen String aus Bytes, eine Stream-Ressource, eine SplFileInfo oder einen PSR-7-Stream und gibt base64 ohne Zeilenumbrüche zurück.