Kalo te dokumentacioni
Python

Bisedat

`threads.list`, `list_all`, `iterate`, `get`, `update`, `trash`, `snooze`, `unsnooze` dhe `list_attachments`.

Leximi

read_threads.py
from openemail import openemail page = openemail.threads.list(    folder='inbox',    query='from:ada',    label_ids=['INBOX', 'IMPORTANT'],    limit=25,) next_page = (    openemail.threads.list(folder='inbox', cursor=page['nextCursor'])    if page['nextCursor']    else None) thread = openemail.threads.get('thread_…')print(thread['messageCount'], thread['hasUnread'], thread['totalReplies'])

API-ja i ndan bisedat në faqe me një pageToken. Klienti jua jep si nextCursor dhe e merr prapë si cursor, si çdo listë tjetër, kurse list_all dhe iterate e ndjekin atë për ju. Ai është i errët: ktheni atë që ju u dha dhe mos ndërtoni kurrë një të tillë.

Filtrat e listës janë argumente me fjalë kyçe në snake_case (label_ids=, date_from=), ndërsa çelësat e një trupi kërkese ruajnë emrat camelCase të API-së (addLabelIds te update). Një faqe dhe një bisedë kthehen si dict, kështu që i lexoni me page['nextCursor'] dhe thread['messageCount'].

sort_threads.py
from datetime import datetime, timedelta, timezone from openemail import openemail now = datetime.now(timezone.utc) last_week = openemail.threads.list_all(    sort='oldest',    date_from=now - timedelta(days=7),    date_to=now,    from_contacts=True,) for thread in openemail.threads.iterate(sort='sender'):    print(thread['id'])

sort, date_from, date_to dhe from_contacts janë kontrollet e vetë listës së bisedave. sort është newest, oldest, sender ose subject, datat marrin një datetime ose një varg ISO 8601 dhe të dy skajet përfshihen, dhe from_contacts mban postën mesazhi më i ri i së cilës erdhi nga një kontakt i ruajtur. Çdo renditje faqoset deri në fund pa kapërcyer apo përsëritur një bisedë. Një datetime pa tzinfo lexohet si ora vendore.

Organizimi

organise_threads.py
from datetime import datetime, timedelta, timezone from openemail import openemail openemail.threads.update('thread_…', {    'read': True,    'addLabelIds': ['USER_DONE'],    'removeLabelIds': ['INBOX'],}) openemail.threads.trash('thread_…')openemail.threads.snooze('thread_…', datetime.now(timezone.utc) + timedelta(days=1))openemail.threads.unsnooze('thread_…')

Gjendja e leximit ËSHTË një etiketë në çdo backend këtu, ndaj udhëton bashkë me listat e etiketave dhe renditja është deterministe kur i vendosni të dyja. Të paktën njëra nga tri fushat duhet të jetë e pranishme.

addLabelIds merr ID nga labels.list dhe ID-të e sistemit si ARCHIVE dhe STARRED. Një ID që nuk emërton asnjë etiketë refuzohet me një 422 label_not_found në vend që të krijohet, prandaj krijoni së pari etiketën me labels.create. threads.list(folder='USER_DONE') liston çdo bisedë me një etiketë, në cilëndo dosje qoftë.

Bashkëngjitjet e një mesazhi

attachments.py
import base64from pathlib import Path from openemail import openemail files = openemail.threads.list_attachments('thread_…', 'message_…') for file in files:    print(file['filename'], file['contentType'], file['size'])     if file['content']:        name = Path(file['filename']).name        Path(name).write_bytes(base64.b64decode(file['content']))

content është base64, dhe një varg bosh kur bajtat e ruajtur nuk u gjetën dot, ndaj kontrolloni gjatësinë e tij para se ta dekodoni. Teksti i shifruar i një mesazhi të enkriptuar ËSHTË në këtë listë dhe shkarkohet si çdo skedar tjetër; pjesa e versionit PGP/MIME dhe çdo nënshkrim i shkëputur nuk janë. Ato i mbajnë id-të e veta te encryption.parts dhe asgjë më shumë.

Një mesazh që mbërriti i enkriptuar

Ky SDK as enkripton, as dekripton: nuk mund të hapë një mesazh që e enkriptoi dikush tjetër dhe nuk mund të dërgojë një mesazh të enkriptuar. Kërkesa e dërgimit refuzohet nëse mbart një shenjues enkriptimi, sepse një klient pa çelës nuk ka pse të pohojë një të tillë. Çelësat e gjeneruar në aplikacionin OpenEmail jetojnë në shfletuesin që i krijoi dhe nuk mbërrijnë askund këtu; kur ai shfletues hap një mesazh të vulosur, teksti i qartë mbetet brenda tij, kurse mesazhi i ruajtur që lexon kjo thirrje mbetet tekst i shifruar. Ajo që ju jep threads.get është zarfi, i njohur si i tillë. Një mesazh që mbërriti i mbështjellë me PGP ose S/MIME mbart një dict encryption, kështu që një decodedBody bosh pushon së qeni e vetmja gjë që ju jepet. Ky është i vetmi çelës mungesën e të cilit nuk e përballoni dot duke hamendësuar, dhe e përshkruan MessageEncryption në openemail.types.

encrypted_mail.py
import sys from openemail import is_sealed, openemail thread = openemail.threads.get('thread_…') for message in thread['messages']:    if not message.get('encryption'):        continue    if not is_sealed(message):        continue     print('cannot read this one:', message['encryption']['format'], file=sys.stderr)

Degëzoni me is_sealed, kurrë sipas pranisë së fushës. Dy nga pesë formatet, pgp-signed dhe smime-signed, përshkruajnë një trup që mbërriti I HAPUR përkrah një nënshkrimi të shkëputur, ndaj kushtëzimi sipas pranisë fsheh postë që nuk kishte pse fshihej, dhe përdoruesi as e sheh dot, as e shpjegon dot. is_sealed vjen i gatshëm pikërisht për këtë arsye: serveri e deklaron një herë të vetme bashkësinë e të vulosurave, kurse një kopje e tretë e shkruar nga union-i është kopja që rrëshqet.

Mungesa nuk do të thotë tekst i qartë. encryption mungon në çdo mesazh të ruajtur para se të dilte zbulimi, si dhe në çdo gjë që mbërriti në kutinë postare përmes një rruge ku zbuluesi nuk u ekzekutua kurrë. Ajo regjistron faktin që askush nuk shikoi, një fakt për mbulimin tonë e jo për vetë postën, dhe asgjë nuk e mbush atë në mënyrë retroaktive.

Ku ndryshojnë këto nga të tjerat

  • Çdo element në ThreadResource.messages është një MessageResource, një dict[str, Any] i thjeshtë, tipi i të cilit nuk emërton asnjë fushë, as edhe encryption. Tipizimi i fushave do të thoshte që klienti pohon një normalizim që nuk e kryen askush. Lexojeni encryption me message.get('encryption') dhe degëzoni me is_sealed, sepse një klient që nuk mund të degëzojë sipas tij e lexon një mesazh të vulosur si një mesazh bosh.
  • Një kërkesë që nuk mund të shërbehet me besnikëri është një 422 capability_unsupported, jo një përgjigje që duket e saktë dhe është në heshtje e gabuar.

Parametrat: threads.list

folderstr
Cila dosje të listohet. Serveri e vendos si parazgjedhje `inbox`, ndaj lënia e tij jashtë e ngushton listimin në vend që ta zgjerojë te gjithçka. Ai vlen edhe për një kërkim me `query`, veç nëse vetë pyetja emërton një dosje me `in:` ose me një `is:` dosjeje, si `is:sent`.
querystr
Sintaksa e kërkimit në kutinë postare. Fjalët e thjeshta duhet të shfaqen të gjitha dhe secila përputhet në mënyrë të lirshme: shkronjat e mëdha a të vogla, theksat dhe ndarësit shpërfillen, kurse pjesa e një fjale më të gjatë numërohet, ndaj si `min`, ashtu edhe `ben jamin` e gjejnë "Benjamin". Një frazë në thonjëza përputhet ashtu siç është shkruar, përveç shkronjave të mëdha a të vogla dhe theksave, ndaj `"ben jamin"` nuk e gjen "Ben-Jamin"; fjalët mbushëse hidhen tej kur mbetet diçka tjetër për të kërkuar. Kur asgjë nuk përputhet saktësisht, kthehen në vend të saj shkrime të afërta, prandaj `benjimin` gjen "Benjamin": një fjalë e thjeshtë, ose vlera e `from:`, `to:`, `cc:`, `subject:`, `body:`, `filename:` ose `label:`, mund të ndryshojë nga fillimi i një fjale me një gabim shtypi (një shkronjë të ndryshuar, që mungon, të tepërt ose të ndërruar vendi) kur ka katër deri në shtatë shkronja, dhe me dy kur ka tetë ose më shumë, ndërsa një frazë në thonjëza, një fjalë me shifër, një fjalë më e shkurtër dhe një fjalë e përjashtuar vazhdojnë të përputhen vetëm saktësisht, dhe faqet që pasojnë kërkojnë në të njëjtën mënyrë. Ngushtojeni me operatorë si `from:ada`, `label:Invoices`, `is:unread`, `has:pdf`, `before:2026/01/31` dhe `older_than:1y`, dhe kombinojini me `OR`, me kllapa dhe me një `-` në fillim; një vlerë që kërkimi nuk e përdor dot shpërfillet në vend që të ngushtojë. Fjalët dhe operatorët `from:`, `to:`, `cc:`, `subject:` e `body:` lexojnë dërguesin, marrësit, temën e mesazhit më të fundit dhe 4.000 karakteret e para të trupit të tij me markup-in e hequr, ndërsa `filename:` dhe `has:` lexojnë çdo bashkëngjitje të gjithë bisedës, kurse etiketat dhe dosjet lexojnë gjithë bisedën. Ai ngushton të njëjtin indeks që lexon listimi i pafiltruar. Mesazhet e vulosura nuk ruajnë tekst trupi, ndaj mund të përputhen vetëm dërguesi, marrësit dhe tema e tyre. Një fjalë e thjeshtë përputhet edhe me emrin e çdo bashkëngjitjeje në bisedë, cilido qoftë mesazhi që e solli.
label_idsstr | Sequence[str]
Kufizojeni listimin te bisedat që mbajnë këto etiketa. Endpoint-i merr një varg të ndarë me presje, dhe klienti jua bashkon një listë ose një tuple në një të tillë. Nuk ka kufi se sa prej tyre emërtoni.
limitint
Sa biseda të kthehen, nga 1 deri në 100. Nëse lihet jashtë, handler-i përdor 25. Vlera e parazgjedhur qëndron te handler-i e jo te skema, ndaj një vlerë që mungon dhe një 25 e shprehur sillen njësoj.
cursorstr
`nextCursor`-i i faqes së mëparshme, i kthyer fjalë për fjalë. Është `pageToken`-i i API-së nën emrin që përdor çdo listë tjetër, dhe është i errët, ndaj mos ndërtoni e mos redaktoni kurrë një të tillë.

Përgjigjja: Page[ThreadSummaryResource]

itemslist[ThreadSummaryResource]
Një zë për çdo bisedë në këtë faqe, i nxjerrë nga zarfi `data` i API-së. Çdo zë është vetëm një shenjues objekti dhe një id. Listimi nuk mbart temë, fragment, pjesëmarrës apo etiketa, ndaj çdo gjë më shumë do të thotë të thirret `threads.get` për bisedat që doni.
items[].idstr
Id-ja e bisedës, për t'ia dhënë të pandryshuar `threads.get`, `threads.update` dhe të tjerave. Është e njëjta id, qoftë kur rreshti vjen nga një listim i filtruar, qoftë nga një kërkim me `query`.
hasMorebool
Nëse ka një faqe tjetër, nxjerrë nga `nextCursor` aty ku API-ja nuk e deklaron.
nextCursorstr | None
`nextPageToken`-i i API-së, për ta dërguar prapë si `cursor` për faqen pasuese, ose `None` kur nuk ka faqe tjetër. Një token bosh normalizohet në `None`, ndaj një kontroll falsy dhe një kontroll për `None` pajtohen.

Referencë