Přejít na dokumentaci
SDK

Konverzace

`threads.list`, `listAll`, `iterate`, `get`, `update`, `trash`, `snooze`, `unsnooze` a `listAttachments`.

Čtení

read-threads.ts
const page = await openemail.threads.list({  folder: 'inbox',  query: 'from:ada',  labelIds: ['INBOX', 'IMPORTANT'],  limit: 25,}) const next = page.nextCursor  ? await openemail.threads.list({ folder: 'inbox', cursor: page.nextCursor })  : null const thread = await openemail.threads.get('thread_…')console.log(thread.messageCount, thread.hasUnread, thread.totalReplies)

API stránkuje konverzace pomocí pageToken. Klient vám jej předává jako nextCursor a bere zpět jako cursor, stejně jako u každého jiného seznamu, a listAll i iterate jej sledují za vás. Je neprůhledný: vracejte přesně to, co jste dostali, a nikdy si žádný nesestavujte.

Organizace

organise-threads.ts
await openemail.threads.update('thread_…', {  read: true,  addLabelIds: ['Done'],  removeLabelIds: ['INBOX'],}) await openemail.threads.trash('thread_…')await openemail.threads.snooze('thread_…', new Date(Date.now() + 86_400_000))await openemail.threads.unsnooze('thread_…')

Stav přečtení JE na všech zdejších backendech štítek, takže cestuje spolu se seznamy štítků a pořadí je deterministické, i když nastavíte obojí. Alespoň jedno ze tří polí musí být přítomno.

Přílohy zprávy

attachments.ts
const files = await openemail.threads.listAttachments('thread_…', 'message_…') for (const file of files) {  console.log(file.filename, file.contentType, file.size)  if (file.content) await save(file.filename, Buffer.from(file.content, 'base64'))}

content je base64 a prázdný řetězec tehdy, když se uložené bajty nepodařilo najít, takže před dekódováním zkontrolujte jeho délku. Šifrovaný text zašifrované zprávy v tomto seznamu JE a stahuje se jako každý jiný soubor; část s verzí PGP/MIME a případný oddělený podpis nikoli. Ty si drží svá id v encryption.parts a nic víc.

Zpráva, která dorazila zašifrovaná

Toto SDK nešifruje ani nedešifruje: nedokáže otevřít zprávu, kterou zašifroval někdo jiný, a nedokáže zašifrovanou zprávu odeslat. Požadavek na odeslání je odmítnut, pokud nese značku šifrování, protože klient bez klíče nemá co takovou věc tvrdit. Klíče vygenerované v aplikaci OpenEmail žijí v prohlížeči, který je vytvořil, a sem nedosáhnou; když takový prohlížeč otevře zapečetěnou zprávu, otevřený text zůstane v něm a uložená zpráva, kterou toto volání čte, je pořád šifrovaný text. To, co vám threads.get dá, je obálka – rozpoznaná. Zpráva, která dorazila zabalená v PGP nebo S/MIME, nese objekt encryption, takže prázdné decodedBody přestává být jediné, co dostanete do ruky, a encryption je jediné pole na MessageResource se skutečným typem, protože je to jediné, jehož nepřítomnost nepřežijete hádáním.

encrypted-mail.ts
import { isSealed, openemail } from '@openemail/sdk' const thread = await openemail.threads.get('thread_…') for (const message of thread.messages) {  if (!message.encryption) continue  if (!isSealed(message)) continue   console.warn('cannot read this one:', message.encryption.format)}

Větvěte přes isSealed, nikdy podle přítomnosti toho pole. Dva z pěti formátů, pgp-signed a smime-signed, popisují tělo, které dorazilo NEZAŠIFROVANÉ vedle odděleného podpisu, takže podmínka na přítomnost skryje poštu, kterou nikdo skrývat nepotřeboval, a uživatel ji neuvidí ani si ji nevysvětlí. isSealed se dodává přesně z toho důvodu: server vysloví množinu zapečetěných formátů jednou, a třetí kopie, vypsaná z unionu, je ta, která se rozejde.

Nepřítomnost neznamená otevřený text. encryption chybí u každé zprávy uložené dřív, než detekce vyšla, a u všeho, co se do schránky dostalo cestou, kde detektor nikdy neběžel. Zaznamenává, že se nikdo nedíval – fakt o našem pokrytí, ne o té poště – a nic to zpětně nedoplňuje.

V čem se tyhle liší od ostatních

  • Každá položka v ThreadResource.messages je MessageResource, tedy Record<string, unknown> s přesně jedním pojmenovaným polem. Otypovat zbytek by znamenalo, že klient tvrdí normalizaci, kterou nikdo neprovádí, a encryption pojmenované přesto je, protože klient, který podle něj neumí větvit, čte zapečetěnou zprávu jako prázdnou.
  • Požadavek, který nelze obsloužit věrně, je 422 capability_unsupported, ne odpověď, která vypadá správně a tiše správná není.

Parametry: threads.list (ThreadListOptions)

folderstring
Kterou složku vypsat. Server ji ve výchozím stavu nastaví na `inbox`, takže vynechání výpis zúží, místo aby ho rozšířilo na všechno. Platí i pro vyhledávání přes `query`, pokud dotaz sám nejmenuje složku pomocí `in:` nebo složkového `is:`, jako je `is:sent`.
querystring
Syntaxe vyhledávání ve schránce. Všechna prostá slova se musí vyskytnout a každé se shoduje volně: velikost písmen, diakritika i oddělovače se ignorují a počítá se i část delšího slova, takže `min` i `ben jamin` najdou „Benjamin“. Fráze v uvozovkách se hledá tak, jak je napsaná, až na velikost písmen a diakritiku, takže `"ben jamin"` nenajde „Ben-Jamin“, a výplňová slova se zahazují, pokud zbývá něco jiného, podle čeho hledat. Zužujte operátory jako `from:ada`, `label:Invoices`, `is:unread`, `has:pdf`, `before:2026/01/31` a `older_than:1y` a kombinujte je pomocí `OR`, závorek a předřazeného `-`; hodnota, kterou vyhledávání použít neumí, se ignoruje, místo aby zužovala. Slova a operátory `from:`, `to:`, `cc:`, `subject:` a `body:` čtou odesílatele, příjemce a předmět poslední zprávy a prvních 4 000 znaků jejího těla zbaveného značek, zatímco `filename:` a `has:` čtou všechny přílohy celé konverzace a štítky i složky čtou celou konverzaci. Zužuje tentýž index, ze kterého čte nefiltrovaný výpis. Zapečetěné zprávy neukládají text těla, takže se u nich může shodovat jen odesílatel, příjemci a předmět.
labelIdsstring | string[]
Omezí výpis na konverzace nesoucí tyto štítky. Endpoint bere řetězec oddělený čárkami a klient za vás pole do takového řetězce spojí; počet uvedených štítků není nijak omezen.
limitnumber
Kolik konverzací vrátit, od 1 do 100. Když se vynechá, použije handler 25. Výchozí hodnota bydlí v handleru, ne ve schématu, takže chybějící hodnota a explicitní 25 se chovají stejně.
cursorstring
`nextCursor` z předchozí stránky, vrácený doslova. Je to `pageToken` z API pod názvem, který používá každý jiný seznam, a je neprůhledný, takže si žádný nesestavujte ani neupravujte.

Odpověď: Page<ThreadSummaryResource>

itemsThreadSummaryResource[]
Jedna položka na každou konverzaci v této stránce, vyzvednutá z obálky `data` v API. Každá položka je jen značka objektu a id. Výpis nenese předmět, úryvek, účastníky ani štítky, takže cokoli dalšího znamená zavolat `threads.get` na konverzace, které chcete.
items[].idstring
Id konverzace, které beze změny předáte do `threads.get`, `threads.update` a dalších. Je to totéž id, ať řádek pochází z filtrovaného výpisu, nebo z vyhledávání přes `query`.
hasMoreboolean
Zda existuje další stránka; odvozuje se z `nextCursor` tam, kde to API neuvádí.
nextCursorstring | null
`nextPageToken` z API, které pro následující stránku pošlete zpět jako `cursor`, nebo null, když další stránka není. Prázdný token se normalizuje na null, takže kontrola na falsy a kontrola na null dávají stejnou odpověď.