Ugrás a dokumentációra
API

Beszélgetések

Levél olvasása és rendszerezése.

GETapi.openemail.uk/threads

Az oldalon lévő 7 hívás bármelyikét lefuttatja a munkaterületén, a saját kulcsával.

Listázás

GET /threads?folder=inbox. A query átadása ugyanazt a helyi indexet keresi. A sima szavaknak mind szerepelniük kell, és mindegyik lazán illeszkedik, kis- és nagybetűt, ékezeteket és elválasztókat figyelmen kívül hagyva, így a min megtalálja a „Benjamin” nevet. Az idézőjeles kifejezés a kis- és nagybetűn és az ékezeteken túl szó szerint illeszkedik, tehát a "ben jamin" nem találja meg a „Ben-Jamin” alakot. A töltelékszavakat, mint a the vagy az emails, kidobjuk a sima szavak listájából, ha marad még valami, amire keresni lehet. Az olyan operátorok, mint a from:, a to:, a subject:, a label:, az is:unread, a has:pdf, az after:2026/01/31 és a newer_than:7d szűkítik, az OR, a zárójelek és a vezető - pedig kombinálják őket. A címzetteket egyetlen listaként tároljuk, szerepek nélkül, és soha nem tartalmaz Bcc-t, tehát a cc: ugyanazt a mezőt olvassa, mint a to:, a bcc: pedig önmagában semmire sem illeszkedik. A from:me az általad küldött levél, a to:me pedig az a levél, amely a saját címeid egyikét viszi, az aliasokkal együtt, a címzettek között vagy kézbesítési címként.

A szavak, valamint a from:, a to:, a cc:, a subject: és a body: operátor az egyes beszélgetések legújabb üzenetét olvassa: a feladóját, a címzettjeit, a tárgyát és a törzs első 4000 karakterét. A filename: és a has: a teljes beszélgetés minden mellékletét olvassa, a label:, az in: és az is: pedig az egész beszélgetést. A folder továbbra is érvényes, hacsak a lekérdezés meg nem nevez egyet in: operátorral vagy olyan is: értékkel, amely mappa, például is:sent, az in:anywhere pedig minden mappában keres, önmagában és más kifejezések mellett is. A piszkozatlistázás a kivétel: a piszkozatokban marad, bármit is nevezzen meg a lekérdezés.

Azt az értéket, amelyet a keresés nem tud használni, figyelmen kívül hagyjuk, nem pedig szűkítünk vele, így egy elgépelt érték tágítja az eredményt ahelyett, hogy kiürítené: ilyen a category:, a larger:, a smaller:, a size:, a messagesize:, a list:, az rfc822msgid:, a received:, a sent:, a kategóriaszavak, például az is:promotions, az olyan has: szó, amely semmilyen mellékletfajtát nem nevez meg, a high vagy low értéktől eltérő importance:, az olvashatatlan dátum és az a időtartam, amelynek egysége nem h, d, w, m vagy y. Az ismeretlen operátornevet, például a project: kifejezést, sima szövegként keressük. A dátumok a beszélgetés legújabb tevékenységét olvassák, UTC szerint, az after: az általa megnevezett napot is beleértve, a before: pedig kizárva; írd YYYY/MM/DD, YYYY-MM-DD, YYYYMMDD, puszta év, vagy epoch másodperc vagy ezredmásodperc alakban.

A nextPageToken átlátszatlan. Pontosan azt add vissza, amit kaptál; soha ne állíts elő vagy szerkessz ilyet. Az alakja nem része a szerződésnek.

Lekérés

A GET /threads/{id} a beszélgetés minden üzenetét visszaadja, nem csak a legfrissebbet, a címkéivel és azzal együtt, hogy van-e benne olvasatlan.

Titkosítva érkezett üzenetek

Ez az API se nem titkosít, se nem fejt vissza. Nem tud megnyitni egy olyan üzenetet, amelyet más titkosított, és nem tud titkosítottat küldeni. Azt a kérést, amely titkosítási jelölőt visz, 422-vel utasítjuk el, mert az egyetlen felület, amely ilyet beállíthat, az, amely a kulcsokat tartja, márpedig egyetlen API-kliens sem tart kulcsot. Amit viszont megtesz: FELISMERI a lepecsételt borítékot beérkezéskor, kizárólag a felső szintű Content-Type alapján, és ezt jelzi is az üzeneten.

Az OpenEmail immár maga is tart kulcsokat, és érdemes pontosan megmondani, melyik felét és hol. A postafiók tulajdonosa a böngészőjében generál egy OpenPGP-identitást, és a NYILVÁNOS kulcsot közzéteszi egy címtárban, amelyet más bejelentkezett OpenEmail-feladók fel tudnak oldani. A privát fél abban a böngészőben készül, soha nem kerül ide, és soha nem állítható helyre, tehát ebben az API-ban semmi nem tud semmit visszafejteni, és nincs az az ügyfélszolgálati kérés, bírósági végzés vagy mentésünk, amely kulcsot adna hozzá. A webalkalmazás mostantól KÉPES megnyitni egy PGP/MIME vagy inline PGP üzenetet, ha a kulcs az olvasó böngészőjében van, de ez a visszafejtés a fülön történik, és a nyílt szöveg soha nem íródik vissza: a tárolt üzenet titkosított marad, és ennek az API-nak egyetlen válasza sem viszi a megnyitott szöveget. Az alkalmazás mostantól le tud pecsételni egy új üzenetet a böngészőben, és el tudja küldeni: a szerkesztő a címzettek közzétett kulcsaira titkosít, és a levél PGP/MIME formában megy ki. Ez az API továbbra sem tud semmit lepecsételni, tehát az alábbi mező egyszerre írja le a más által titkosított levelet és az OpenEmail-fülön lepecsételtet.

Ez azért ér meg egy mezőt, mert mi volt az alternatíva. A lepecsételt üzenet nem tárol olvasható törzset, tehát a decodedBody "" értékkel jön vissza, ugyanazokkal a bájtokkal, mint egy olyan üzenet, amelynek valóban nem volt tartalma. Az encryption az, ami alapján a kettőt meg tudod különböztetni, mielőtt bármelyikre reagálnál, és ez a borítékról szóló állítás, nem ellenőrzés: látni, hogy egy üzenet le van pecsételve, nem ugyanaz, mint megnyitni.

Válasz
{    "object": "thread",    "id": "thread_2f9b…",    "messages": [      {        "id": "msg_7c41…",        "subject": "Q3 numbers",        "decodedBody": "",        "encryption": {          "format": "pgp-mime",          "detectedAt": "2026-08-30T09:14:22.117Z",          "rawRetained": false,          "parts": [            { "index": 0, "attachmentId": "msg_7c41…-0", "role": "version" },            { "index": 1, "attachmentId": "msg_7c41…-1", "role": "ciphertext" }          ]        }      }    ]  }

encryption

format'pgp-mime' | 'pgp-signed' | 'pgp-inline' | 'smime-encrypted' | 'smime-signed'
Melyik boríték érkezett. A felső szintű `Content-Type` alapján olvassuk ki (PGP esetén a `protocol` paraméteréből, S/MIME esetén az `smime-type` értékéből), `pgp-inline` esetén pedig abból a törzsből, amely PGP armor fejléccel kezdődik. Az `smime-type` nélküli `pkcs7-mime` részt `smime-encrypted` értékként olvassuk, mert alapértelmezés szerint az RFC 8551 is ezzé teszi.
detectedAtstring
ISO 8601, amikor a detektor lefutott, vagyis amikor az üzenet ide beérkezett. Semmit nem mond arról, mikor titkosították az üzenetet, és ki.
rawRetainedboolean
Hogy megőriztük-e az eredeti RFC822 bájtokat, azaz visszaadható-e az üzenet egészében. Ma minden üzeneten false, mivel itt még semmi nem őriz nyers levelet. Azért van már most a válaszban, hogy amikor ez megváltozik, ne ugyanaznap kelljen minden tárolt üzenetet újra migrálni.
partsobject[]
Azok a borítékrészek, amelyeket ez a formátum használ. Mindig jelen van, ha az `encryption` is, és üres, ha nincs mit megnevezni: a `pgp-inline` esetén nincs külön rész, mivel az armor MAGA a törzs, és a `decodedBody` mezőben érkezik.
parts[].indexnumber
Az eredeti üzenet melyik MIME-része volt ez, a beérkezés szerinti részeken számolva, nem pedig az `attachments` listán. A két lista eltér, és pontosan ezért rögzítjük ezt.
parts[].attachmentIdstring
Az az id, amelyet ez a rész az `attachments` listában visel, ha egyáltalán megjelenik ott: az üzenet id-je a rész indexével kiegészítve. A `ciphertext` rész szerepel a listában, és úgy tölthető le, mint bármely más fájl; a `version` és a `signature` ki van hagyva a listából, tehát az id-jük csupán összeköti a két nézetet. A mellékletvégpont nem adja vissza őket.
parts[].role'version' | 'ciphertext' | 'signature'
A `version` a PGP/MIME vezérlőrésze, a `ciphertext` maga az üzenet, a `signature` pedig egy leválasztott aláírás. Csak a `ciphertext` letöltése érdemi; a másik kettő protokollkellék, amely korábban haszontalan mellékletként jelent meg, ma már nem.
formatAmi megérkezettTörzs
pgp-mimePGP/MIME boríték: multipart/encrypted a protocol=application/pgp-encrypted paraméterrel.Lezárt
pgp-inlinePáncél (armor) magában a törzsben. Csak a törzs szövegéből olvassuk ki, így az a válasz, amely pusztán idéz egy páncélozott blokkot, nem tévesztendő ilyennek.Lezárt
smime-encryptedEgy S/MIME pkcs7-mime rész smime-type=enveloped-data értékkel, vagy olyan, amelyen egyáltalán nincs smime-type.Lezárt
pgp-signedLeválasztott PGP-aláírás az üzenet mellett: multipart/signed a protocol=application/pgp-signature paraméterrel.Olvasható
smime-signedLeválasztott S/MIME-aláírás: pkcs7-signature protokoll, vagy smime-type=signed-data.Olvasható

Az aláírt nem egyenlő a lezárttal, és ha az encryption meglétére ágazol el a format helyett, pontosan a visszájára fordítod. Az aláírás arra vonatkozó állítás, hogy ki írta az üzenetet, nem pedig burok körülötte: az aláírt üzenet törzse tisztán olvasható, és úgy olvasható, mint bármely másiké. A pgp-mime, a pgp-inline és az smime-encrypted formátumot kezeld olvashatatlanként, a két aláírt formátumot pedig közönséges levélként.

Mi változik egy lezárt üzeneten

Csak a három lezárt formátum változtat bármin is, és a változás a beérkezéskor történik, nem ebben a válaszban. Minden, ami a törzset olvasta volna, leáll, ahelyett hogy titkosított szöveget olvasna, és olyan eredményt jelentene, amelyet nem kaphatott volna meg:

  • A törzsben való keresés. Az üzenet üres törzskivonattal kerül indexelésre, így továbbra is megtalálható feladó, tárgy, cím és címke alapján – a benne lévő bármi alapján nem.
  • Az adathalászat-pontozó törzselemzése. A verdikt így is megérkezik, és megmondja, mit nem tudott elvégezni: a risk.signals tartalmazza a body-encrypted jelzést, a risk.aiChecked pedig false.
  • Az AI-szerzőség ellenőrzése, amely inkább nem nyilatkozik, mint hogy találgasson: az aiWritten.level értéke unknown, az aiWritten.skipped értéke pedig encrypted.
  • A szabályok törzsre vonatkozó feltételei. A borítékra és a fejlécekre vonatkozó feltételek pontosan úgy futnak, mint eddig; az a szabály, amely a törzsről kérdezett, kiértékeletlenként rögzül, nem pedig nem illeszkedőként, mert a „nem illeszkedett” és a „nem volt olvasható” két különböző válasz.
  • A naptármeghívók importálása. A meghívó a titkosított szövegben van, és ha a borítékból építenénk eseményt, az hibás bejegyzést tenne egy valódi naptárba.
  • A beszélgetés-összefoglalók és a beágyazások, az egész beszélgetésre. Egyetlen lezárt válasz is elég. Az összefoglaló a modell olvasata a nyílt szövegről, tiszta szövegű metaadatként tárolva, és ez az egyetlen pont ebben a folyamatban, ahol a törzs olyan tárolóba szivárogna, amelyre senki nem gondol törzsként.

Minden, aminek nincs szüksége a törzsre, érintetlen marad:

  • A DMARC, a DKIM és az SPF. Ezeket az Authentication-Results fejlécből olvassuk ki, amelyet a titkosított szöveg nem rejt el, így a titkosított üzenet is valódi hitelesítési verdiktet kap, nem pedig semmilyet.
  • A beszélgetésbe fűzés, a spam iktatása és a tiltólista: mind boríték- és fejlécmunka.
  • A mellékletek. A titkosított szöveget tartalmazó rész az attachments listában marad, encrypted-message.asc néven, ha név nélkül érkezett, és az alábbi végponton keresztül tölthető le. Pontosan ezt tölti le és fejti vissza a böngészőben a webalkalmazás saját olvasója is; egy API-kliensnek, amelynek nincs kulcsa, ez a letöltés marad az egyetlen módja a levél elolvasásának. Nyisd meg olyan kliensben, amelyben van kulcs.
  • Az aláírt üzenet mindebből semmit nem veszít. A fenti ellenőrzések mindegyike tovább fut rajta, és semmit nem tartunk vissza – ezért áll a lezárt formátumok listája háromból, nem ötből.

Az encryption hiánya nem azt állítja, hogy az üzenet nyílt szövegű. Azt jelenti, hogy senki nem nézte meg: az üzenet régebbi, mint a felismerés, vagy olyan úton jutott a postafiókba, amelyen a felismerő nem fut. Semmi nem tölti vissza utólag, tehát azt a mezőt, amely azt mondja, „nem ellenőriztük”, soha nem szabad úgy olvasni, hogy „ellenőriztük, és nem találtunk ilyet”.

Megjelölés és címkézés

A PATCH /threads/{id} a read, az addLabelIds és a removeLabelIds mezőt fogadja. Az olvasottság minden olyan backenden címke, amelyet ez a termék támogat, így a read beállítása és a címkék mozgatása egy hívásban determinisztikusan tartja a sorrendet.

PATCH
{ "read": true, "addLabelIds": ["USER_INVOICES"] }

A TRASH és a SNOOZED értéket itt label_not_directly_settable hibával utasítjuk el. Egyik állapotot sem hordozza önmagában a címkéje (a kukába helyezés a mappacímkéket is törli, a szundihoz pedig mellé tárolt ébresztési idő kell), így a kézi beállítás olyan állapotban hagyja a beszélgetést, amelyet az alkalmazás sosem hoz létre, és amelyből nem tud visszatérni. Használd az alábbi végpontokat.

Kuka és szundi

VégpontMit csinál
POST /threads/{id}/trashA Kukába helyezi, egyszerre törölve az INBOX, SPAM, SNOOZED és ARCHIVE címkéket.
POST /threads/{id}/snoozeTörzs: { "wakeAt": "…" }. Elrejti, és ütemezi a visszatérését.
POST /threads/{id}/unsnoozeMost visszahozza, és törli az ütemezett visszatérést.

A szundi két dolgot ír: a címkét, amely elrejti a beszélgetést, és a bejegyzést, amely visszahozza. Az egyik a másik nélkül pontosan az oka annak, hogy ezek végpontok, nem címkeszerkesztések.

Mellékletek

A GET /threads/{id}/messages/{messageId}/attachments minden mellékletet filename, contentType, size és base64 content mezőkkel ad vissza. A content üres sztring ott, ahol a tárolt bájtokat nem találtuk, ezért dekódolás előtt ellenőrizd a hosszát.

A titkosított boríték nincs itt teljes egészében. A titkosított szöveg igen (az maga az üzenet, és a letöltése az egyetlen módja annak, hogy egy API-kliens elolvassa ezt a levelet), de a PGP/MIME verziórészt és az esetleges leválasztott aláírást kihagyjuk a listából, mert haszontalan mellékletként jelentek meg, és a hívó semmit nem tud kezdeni velük. Az azonosítójuk mindkettőnél megmarad az encryption.parts alatt, ami összeköti a két nézetet; ez a végpont nem adja vissza őket.