Konfigurimi
Tri mënyra për të ndërtuar një klient, çdo opsion, dhe çfarë refuzon përpara se të dërgohet një kërkesë.
Opsionet
import os from openemail import AsyncOpenEmail, OpenEmail, init, openemail init(os.environ['OPENEMAIL_API_KEY'])openemail.me.ping() billing = OpenEmail(os.environ['BILLING_API_KEY']) pinned = OpenEmail('oe_live_...', base_url='https://api.openemail.uk') background = AsyncOpenEmail()| Pika e hyrjes | Çfarë ju jep |
|---|---|
| init(...) | Konfiguron klientin e përbashkët dhe e kthen atë. openemail është ai klient që nga ai çast, në çdo modul, dhe çdo gjë që lini jashtë lexohet nga mjedisi. |
| openemail | Klienti i përbashkët. I përdorur përpara init, ai ndërtohet vetë nga OPENEMAIL_API_KEY dhe OPENEMAIL_BASE_URL në thirrjen e parë. |
| OpenEmail(...) | Një klient i veçantë, për një çelës të dytë pranë atij të përbashkët, ose për të ndërtuar instancën që eksporton moduli juaj. Çdo gjë që lini jashtë lexohet nga mjedisi, siç bën init, dhe create_client është e njëjta klasë me një emër tjetër. |
| AsyncOpenEmail(...) | Një klient asinkron i veçantë me të njëjtat opsione, ku çdo metodë thirret me await. openemail i përbashkët është sinkron, ndaj këtë duhet ta ndërtoni vetë. |
| get_client() dhe reset_client() | get_client kthen vetë klientin e përbashkët dhe e ndërton nga mjedisi kur init nuk është ekzekutuar. reset_client e harron atë, kështu që përdorimi i radhës ndërton një të ri. |
import httpxfrom openemail import init init( 'oe_live_...', base_url='https://api.openemail.uk', timeout=30, max_retries=2, http_client=httpx.Client(proxy='http://proxy.internal:3128'), headers={'X-Team': 'billing'}, user_agent='billing-service/1.4', disable_update_notice=True,)| Opsioni | Parazgjedhja | Shënime |
|---|---|---|
| api_key | OPENEMAIL_API_KEY | Lexohet nga mjedisi prej init dhe OpenEmail. Duhet të fillojë me oe_live_ ose oe_test_. |
| access_token | OPENEMAIL_ACCESS_TOKEN | Një token qasjeje OAuth, ose një funksion që kthen një të tillë, në vend të api_key. Shihni tokenat e qasjes OAuth më poshtë. |
| base_url | https://api.openemail.uk | Ose OPENEMAIL_BASE_URL. Një slash në fund hiqet, dhe init e OpenEmail vendosin https:// përpara një hosti të zhveshur, ose http:// përpara një hosti në këtë makinë: localhost, një adresë 127.x.x.x ose ::1. Një kredencial nuk dërgohet kurrë me http të thjeshtë te ndonjë host tjetër, dhe 0.0.0.0 ose [::] ngre gabim kur ndërtohet klienti, sepse këto janë adresa ku dëgjon një server, jo adresa ku dërgohen kërkesa. |
| timeout | 30 | Në sekonda, për çdo përpjekje, jo për çdo thirrje. Mbulon leximin e trupit, jo vetëm të header-ave. 0 e çaktivizon. files.upload lejon të paktën 600 sekonda, përveç nëse thirrja jep timeout-in e vet. |
| max_retries | 2 | Përpjekje shtesë pas së parës, në thirrjet që janë të sigurta për t'u përsëritur. Caktohet te klienti, jo për çdo thirrje. |
| http_client | një httpx.Client i ri | Jepni tuajin për një proxy, për cilësimet tuaja TLS, për një transport të montuar ose për një test double: një httpx.Client te OpenEmail, një httpx.AsyncClient te AsyncOpenEmail. Mbyllja e klientit e lë të hapur atë që keni dhënë ju. |
| headers | {} | Dërgohen në çdo kërkesë. |
| user_agent | openemail-python/<version> | Dërgohen në çdo kërkesë. |
| disable_update_notice | False | Anashkalon kontrollin një herë për proces për një version më të ri në PyPI. Kontrolli kryhet vetëm kur dalja shkon te një terminal, dhe OPENEMAIL_DISABLE_UPDATE_NOTICE e çaktivizon gjithashtu. |
Çfarë refuzon para dërgimit
Këto ngrenë ValueError (ose TypeError, aty ku e thotë tabela) para se të dërgohet ndonjë kërkesë, në vend që të shfaqen si një dështim ngatërrues te dërgimi juaj i parë. Mesazhi thotë çfarë ishte gabim dhe çfarë të jepni në vend të saj.
| Refuzohet | Pse |
|---|---|
| Asnjë çelës fare | As api_key dhe as OPENEMAIL_API_KEY nuk ishin caktuar, pra nuk ka asgjë me të cilën të autentikohet. |
| Një cookie sesioni ose një token sesioni | Vetëm oe_live_ dhe oe_test_ autentikohen këtu, dhe këtë e thotë edhe API-ja. Kontrolli është thjesht një prefiks dhe asgjë më shumë, prandaj një çelës i revokuar dështon prapë në rrjet. |
| Një base_url që nuk është URL http ose https | Asgjë tjetër nuk mund të merret, ndaj klienti e refuzon kur ndërtohet, në vend që të dështojë te kërkesa e parë. |
| Një base_url në 0.0.0.0 ose [::] | Një adresë ku dëgjon një server, jo një adresë ku dërgohen kërkesa. Mesazhi përmend në vend të saj 127.0.0.1 ose [::1] me të njëjtin port. |
| Një kredencial me http të thjeshtë | Refuzohet gjatë thirrjes, para se kërkesa të nisë, përveç nëse serveri është në këtë makinë. Kushdo në rrjet mund ta lexonte. |
| Një id bosh ose e përbërë vetëm nga pika te çfarëdo metode | Ngrihet kur thirret metoda. Një segment shtegu prej pikash hiqet nga çdo parser URL-je, pra kërkesa do të arrinte te një endpoint tjetër. |
| Një http_client i llojit të gabuar | Një TypeError kur ndërtohet klienti. OpenEmail merr një httpx.Client, ndërsa AsyncOpenEmail një httpx.AsyncClient. |
| Një vlerë trupi që JSON nuk mund ta mbartë | Një TypeError që emërton tipin e saj. Tipet JSON kalojnë ashtu siç janë, dhe një datetime, një date ose një set konvertohet për ju. |
Nuk ka opsion test_mode dhe nuk do të ketë. Skema e çelësit është pjesë e kredencialit dhe jo një sinjal, pra mënyra është veti e çelësit. client.mode lexon prefiksin dhe nuk vendos asgjë.
Një klient, disa çelësa
Ndërtojeni klientin një herë dhe përdorni të njëjtin kudo. Një instancë e re për çdo kërkesë hedh poshtë pool-in e lidhjeve dhe konfigurimin pa asnjë përfitim, dhe asnjë pjesë e gjendjes mbi të nuk është e veçantë për thirrësin.
Një klient mund të ndahet pa rrezik mes thread-eve. close() ose fundi i një blloku with mbyll pool-in e lidhjeve që hapi ai, ndërsa një http_client që keni dhënë ju mbetet i hapur që ta mbyllni vetë.
Për rastin që përndryshe do të detyronte një instancë për çdo çelës, si një punë që dërgon në emër të disa hapësirave pune, jepni api_key te vetë thirrja. Ai zëvendëson header-in Authorization për atë kërkesë dhe nuk lë asgjë pas te klienti.
from openemail.types import EmailSend workspace_key = 'oe_live_...' message: EmailSend = {'from': sender, 'to': recipient, 'subject': subject, 'text': text} client.emails.send(message) client.emails.send(message, api_key=workspace_key) client.threads.list(folder='inbox', api_key=workspace_key)client.webhooks.list(api_key=workspace_key)Çdo metodë jashtë temp_mail e merr si argument me fjalë kyçe, pranë timeout. Kontrollohet para se të dërgohet kërkesa, me të njëjtin rregull që përdor konstruktori, ndaj një gabim shtypi ngre një ValueError që përmend api_key= on this call në vend të një 401 për një kredencial që pastaj duhet të shkoni ta gjeni. Një thirrje e riprovuar e mban çelësin që iu dha.
timeout jepet në sekonda dhe zëvendëson timeout-in e klientit për atë thirrje të vetme, në secilën nga përpjekjet e saj.
client.mode përshkruan çelësin me të cilin u NDËRTUA klienti dhe nuk ndjek një mbivendosje. Kur një klient i vetëm u shërben disa çelësave, nuk ka një mënyrë të vetme për të raportuar, prandaj lexojeni atë nga çelësi që dhatë.
Një endpoint që nuk e mbështjell asnjë metodë
client.raw.request dërgon një kërkesë me kredencialin, URL-në bazë, timeout-in dhe politikën e riprovimeve të klientit të zbatuara, dhe kthen JSON-in e analizuar. Merr method, query, body, api_key dhe timeout. Riprovon një GET dhe çdo gjë tjetër e dërgon një herë, përveç nëse jepni repeatable=True. idempotent=True shton një Idempotency-Key, atë që jepni si idempotency_key ose një të ri.
result = client.raw.request('/something-new', method='POST', body={'name': 'Invoices'})Shtegu duhet të nisë me një / të vetme. Çdo gjë tjetër, si //host/x, ngre gabim para se të dërgohet kërkesa, dhe po ashtu edhe një shteg URL-ja përfundimtare e të cilit del jashtë origjinës së URL-së bazë, kështu që kredenciali që mbart nuk arrin kurrë te një host tjetër.
Kuti të përkohshme
create_temp_mail() ndërton një klient që nuk mban asnjë çelës API, dhe create_async_temp_mail() është binjaku i tij asinkron. Ai krijon kuti në mënyrë anonime, dhe çdo lexim dërgon token-in e kutisë që ktheu create, ose atë më të ri që ktheu extend, qoftë për çdo thirrje si inbox_token, qoftë një herë si create_temp_mail(inbox_token=...).
from openemail import create_temp_mail temp_mail = create_temp_mail() inbox = temp_mail.create()messages = temp_mail.list_messages(inbox['id'], inbox_token=inbox['token']) print(messages['items'], messages['expiresAt'])Tokenat e qasjes OAuth
Ende e palëshuarNjë aplikacion që dikush e lidhi përmes OAuth, si një mjet i rreshtit të komandave ose një agjent, mban një token qasjeje në vend të një çelësi API. Jepeni si access_token, qoftë vetë tokenin, qoftë një funksion që e kthen atë, i cili te AsyncOpenEmail mund të jetë async. Funksioni thirret një herë për çdo thirrje, dhe riprovimet e asaj thirrjeje ripërdorin atë që ktheu, ndaj rinovojeni tokenin brenda tij kur i afrohet skadimit dhe klienti nuk ka nevojë të rindërtohet kurrë.
from openemail import OpenEmail client = OpenEmail(access_token=session.fresh_access_token) me = client.me.get() if me['object'] == 'oauth_token': print(me['clientId'], me['expiresAt'])| Rasti | Çfarë ndodh |
|---|---|
| api_key dhe access_token bashkë, ose asnjëri | Konstruktori ngre ValueError. Kur mungojnë të dy, mesazhi përmend OPENEMAIL_API_KEY dhe OPENEMAIL_ACCESS_TOKEN. |
| Një vlerë që nuk është token | Një token ka nga 1 deri në 512 karaktere dhe nuk nis me oe_, kontrolli që bën is_access_token. Një varg që nuk e kalon ngre gabim nga konstruktori, dhe një funksion që kthen një të tillë e rrëzon thirrjen para se të dërgohet ndonjë gjë. |
| OPENEMAIL_ACCESS_TOKEN | E lexojnë init, OpenEmail dhe openemail i përbashkët kur nuk jepni asnjërin nga dy kredencialet dhe OPENEMAIL_API_KEY nuk është caktuar, ndaj një çelës në mjedis ka përparësi. |
| Një funksion që ngre përjashtim | Thirrja ngre po atë gabim, të pandryshuar, dhe nuk dërgohet asgjë. |
| Një funksion te OpenEmail që kthen një awaitable | Një ValueError, sepse klienti sinkron nuk mund ta presë. Te AsyncOpenEmail funksioni mund të jetë async. |
| Një api_key për thirrje | Zëvendëson tokenin për atë kërkesë të vetme, dhe funksioni nuk thirret. |
| mode | Gjithmonë live me një token. |
| create_temp_mail() | Nuk dërgon asnjë kredencial, çfarëdo që të ketë mjedisi. |
| me.get() dhe me.ping() | Për një token, get përgjigjet me object të barabartë me oauth_token, id dhe roleId të barabarta me None, clientId e aplikacionit të lidhur, dhe expiresAt, kur skadon miratimi që personi i dha aplikacionit. ping përgjigjet me kind të barabartë me oauth, keyId të barabartë me None dhe clientId. KeyResource dhe PingResource janë bashkime, ndaj dalloni sipas object ose kind para se të lexoni clientId ose expiresAt. |
Një token vepron për një person dhe lexon postën e tij ashtu siç mund ta lexojë ai, ndaj mbajeni në një server si një çelës.
Kodet e verifikimit
Ende e palëshuarPara një ndryshimi të ndjeshëm, si fshirja e një domeni ose ndryshimi i një webhook-u, API-ja i kërkon një tokeni qasjeje kodin e verifikimit që aplikacioni web do t'ia kërkonte personit. Thirrja ngre një OpenEmailApiError me is_step_up_required të barabartë me True, dhe asgjë nuk u ndryshua. Kërkoni një kod, verifikoni atë që ju jep personi, pastaj bëjeni thirrjen sërish. Një çelësi API nuk i kërkohet kurrë.
from openemail import OpenEmailApiError try: client.domains.delete(domain_id)except OpenEmailApiError as error: if not error.is_step_up_required: raise challenge = client.security.begin_step_up() if challenge['method'] == 'email': prompt = f'Enter the code we emailed to {challenge.get("sentTo")}: ' else: prompt = 'Enter the code from your authenticator app, or a backup code: ' client.security.verify_step_up({'code': input(prompt)}) client.domains.delete(domain_id)| Metoda | Çfarë bën |
|---|---|
| security.step_up_status() | Nëse aplikacioni është i verifikuar tani (elevated, elevatedUntil), si kontrollohet kodi i radhës (method, email ose totp), dhe minutes, gjatësia e dritares. Nuk dërgon asgjë dhe nuk raporton një ndalesë. |
| security.begin_step_up(body=None) | Hap një sfidë. Me email një kod me gjashtë shifra niset drejt adresës me të cilën hyn personi, dhe sentTo e shfaq të maskuar. Me totp personi lexon një nga aplikacioni i vërtetimit ose përdor një kod rezervë. Një sfidë ende e hapur që ka përpjekje të mbetura ripërdoret, përveç nëse jepni {'resend': True}, dhe një e bllokuar ose e skaduar zëvendësohet me një thirrje të thjeshtë. Çdo aplikacion mund të hapë 5 në orë dhe 20 në 24 orë për çdo person, dhe e radhës ngre një 429 step_up_throttled. |
| security.verify_step_up({'code': code}) | Kontrollon kodin dhe zhbllokon ndryshimet e ndjeshme për këtë aplikacion për 60 minuta, deri te elevatedUntil, përmes REST dhe përmes mjeteve MCP që bëjnë të njëjtat ndryshime. Pas 10 kodeve të gabuara në 24 orë nga ky aplikacion, ose 20 nga të gjitha aplikacionet e personit bashkë, kjo thirrje dhe begin_step_up ngrenë një 429 step_up_locked me një mesazh që tregon kur rifillon verifikimi. |
Klienti nuk kërkon kurrë vetë një kod dhe nuk e përsërit vetë thirrjen, dhe as begin_step_up, as verify_step_up nuk riprovohen automatikisht, sepse një riprovim pas një përgjigjeje të humbur mund të dërgonte një email të dytë ose të harxhonte një përpjekje të dytë. Nuk kërkojnë fushëveprim, dhe një çelës API që thërret njërën merr 400 step_up_not_applicable. STEP_UP_ERROR_CODES emërton çdo mënyrë si mund të dështojë një verifikim, dhe faqja e gabimeve të API-së tregon çfarë të bëni për secilën.