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
require "openemail" OpenEmail.init(api_key: ENV.fetch("OPENEMAIL_API_KEY"))OpenEmail.me.ping pinned = OpenEmail::Client.new(api_key: ENV.fetch("OPENEMAIL_API_KEY"), base_url: "https://api.openemail.uk")quick = OpenEmail::Client.new(ENV.fetch("OPENEMAIL_API_KEY"))billing = OpenEmail.create_client(api_key: ENV.fetch("BILLING_API_KEY")) p pinned.mode, quick.mode, billing.mode| Pika e hyrjes | Çfarë ju jep |
|---|---|
| OpenEmail.init(...) | Konfiguron klientin e përbashkët dhe e kthen atë. Që atëherë OpenEmail.client është ai klient, në çdo skedar dhe në çdo fije ekzekutimi, dhe çdo gjë që nuk e jepni lexohet nga mjedisi. |
| OpenEmail.client, OpenEmail.emails, OpenEmail.threads dhe çdo hapësirë tjetër emrash | Klienti i përbashkët dhe shkurtoret për hapësirat e tij të emrave. Nëse përdoret para init, ndërtohet vetë në thirrjen e parë nga OPENEMAIL_API_KEY dhe OPENEMAIL_BASE_URL. |
| OpenEmail.reset_client | Heq klientin e përbashkët, ndaj thirrja e radhës ndërton një të ri nga mjedisi. |
| OpenEmail.create_client(...) | Një klient më vete me të njëjtin rikthim te mjedisi: për një çelës të dytë pranë atij të përbashkët ose për një klient që kodi juaj e mban dhe e kalon përreth. |
| OpenEmail::Client.new(...) or OpenEmail::Client.new(api_key) | Një klient më vete i ndërtuar saktësisht nga ajo që jepni. Nuk lexon mjedisin, ndaj i duhet api_key: ose access_token:. OpenEmail.new është e njëjta thirrje. |
OpenEmail.init( api_key: ENV.fetch("OPENEMAIL_API_KEY"), base_url: "https://api.openemail.uk", timeout: 30, max_retries: 2, adapter: OpenEmail::NetHttpAdapter.new(max_idle: 8, keep_alive_timeout: 2), 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, create_client dhe klientit të përbashkët. Duhet të fillojë me oe_live_ ose oe_test_. Mund të jepet edhe si argumenti i parë, por jo në të dyja mënyrat njëherësh. |
| access_token: | OPENEMAIL_ACCESS_TOKEN | Një token qasjeje OAuth, ose çdo gjë që i përgjigjet call dhe kthen një të tillë. Shihni “Tokenat e qasjes OAuth” më poshtë. Jepni një çelës ose një token, kurrë të dyja. |
| base_url: | https://api.openemail.uk | Ose OPENEMAIL_BASE_URL. Slash-et në fund hiqen, dhe init e create_client 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 [::] ngrenë gabim kur ndërtohet klienti, sepse këto janë adresa ku dëgjon një server, jo adresa ku dërgohen kërkesa. |
| timeout: | 30 | Sekonda për përpjekje, jo për thirrje. Me adapterin e parazgjedhur mbulon lidhjen dhe leximin e gjithë trupit, jo vetëm të header-ave. 0 e çaktivizon. files.upload pret të paktën 600 sekonda, përveç nëse jepni timeout: në atë thirrje. |
| max_retries: | 2 | Përpjekje shtesë pas së parës, te thirrjet që mund të përsëriten pa rrezik. Vendoset te klienti, jo për çdo thirrje. 0 i çaktivizon riprovat. |
| adapter: | OpenEmail::NetHttpAdapter.new | Shtresa HTTP. Ajo e parazgjedhura mban deri në 8 lidhje boshe për host, për 2 sekonda secila, dhe max_idle: e keep_alive_timeout: e ndryshojnë këtë. Çdo gjë që i përgjigjet call(request) mund të zërë vendin e saj; kështu një test ekzekutohet pa rrjet. |
| headers: | {} | Dërgohen në çdo kërkesë. |
| user_agent: | openemail-ruby/<version> | Dërgohen në çdo kërkesë. |
| disable_update_notice: | false | Kapërcen kontrollin për një version më të ri në RubyGems, që bëhet një herë për proces. Kontrolli ekzekutohet vetëm kur dalja standarde është një terminal, dhe OPENEMAIL_DISABLE_UPDATE_NOTICE e çaktivizon gjithashtu. |
Variablat e mjedisit
| Variabli | Çfarë bën |
|---|---|
| OPENEMAIL_API_KEY | Çelësi që përdorin init, create_client dhe klienti i përbashkët kur nuk jepni as api_key: as access_token:. |
| OPENEMAIL_ACCESS_TOKEN | Një token qasjeje OAuth, që lexohet vetëm kur nuk jepni asnjë kredencial dhe OPENEMAIL_API_KEY nuk është vendosur, ndaj një çelës në mjedis ka përparësi. |
| OPENEMAIL_BASE_URL | URL-ja bazë kur nuk jepni asnjë. Një hosti të zhveshur si localhost:2222 i shtohet skema. |
| OPENEMAIL_DISABLE_UPDATE_NOTICE | Çdo vlerë jo bosh e çaktivizon njoftimin për përditësim, për çdo klient në proces. |
| HTTPS_PROXY dhe NO_PROXY, ose https_proxy dhe no_proxy | Proxy-ja përmes së cilës lidhet adapteri i parazgjedhur dhe hostet që lidhen drejtpërdrejt. Shihni “Proxy-t” më poshtë. |
OpenEmail::Client.new nuk lexon asnjë nga tri të parat, ndaj një klient i ndërtuar në këtë mënyrë nuk merr kurrë rastësisht një çelës nga mjedisi. Një variabël që është vendosur, por është bosh, llogaritet si e pavendosur.
Çfarë refuzon para dërgimit
Këto ngrenë ArgumentError nga rreshti që përmbante vlerën e gabuar, në vend që të shfaqen si një dështim i paqartë në dërgimin tuaj të parë. Mesazhi thotë çfarë ishte gabim dhe çfarë të jepni në vend të saj, dhe nuk e përsërit kurrë një kredencial.
| Refuzohet | Pse |
|---|---|
| Asnjë kredencial | Nuk u dha as api_key: as access_token:, dhe për init e create_client nuk u vendos as ndonjë nga variablat, ndaj nuk ka asgjë për t’u autentikuar. Ngrihet kur ndërtohet klienti. |
| Një çelës dhe një token bashkë | Çdo kërkesë mbart një kredencial, ndaj klienti nuk mund ta dallojë cilin keni pasur parasysh. Një çelës i dhënë edhe si argumenti i parë, edhe si api_key: refuzohet për të njëjtën arsye. |
| Një cookie sesioni, një token sesioni ose një çelës për një shërbim tjetër | Këtu autentikojnë vetëm oe_live_ dhe oe_test_, dhe këtë e thotë edhe API-ja. Kontrolli është vetëm i prefiksit dhe asgjë më shumë, ndaj një çelës i revokuar dështon prapëseprapë kur kërkesa arrin te serveri, si një OpenEmail::AuthenticationError. |
| Një base_url: që nuk është URL http ose https, ose që përmban emër përdoruesi ose fjalëkalim | Asgjë tjetër nuk mund të arrihet, dhe vendi i kredencialit është te api_key: ose access_token:, jo në URL. Ngrihet kur ndërtohet klienti. |
| Një kredencial me http të thjeshtë drejt një hosti që nuk është në këtë makinë | Ngrihet nga thirrja, para se të dërgohet çfarëdo. Përdorni një URL bazë me https. |
| Një timeout: që nuk është numër sekondash ose është negativ | Jepni sekonda, ose 0 për të mos pasur afat skadimi. Ngrihet kur ndërtohet klienti. |
| Një emër header-i që nuk është token HTTP, ose një ndërprerje rreshti në vlerën e një header-i | Kontrollohet te headers:, user_agent: dhe idempotency_key:, sepse një ndërprerje rreshti do të niste një header të dytë. |
| 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. Refuzohet gjithashtu një id që nuk është UTF-8 i vlefshëm. |
| Një trup kërkese që nuk është Hash | Jepni argumente me fjalë kyçe ose një Hash të vetëm. Çdo gjë që i përgjigjet to_hash llogaritet si Hash. |
Nuk ka opsion test_mode: dhe nuk do të ketë. Skema e çelësit është pjesë e kredencialit, jo një sugjerim, ndaj modaliteti është veti e çelësit. client.mode lexon prefiksin, "live" ose "test", dhe nuk vendos asgjë.
Një klient, disa çelësa
Ndërtojeni klientin një herë dhe ndajeni. Një klient i ri për çdo kërkesë i hedh poshtë lidhjet e hapura pa asnjë përfitim, dhe asnjë pjesë e gjendjes mbi të nuk është e veçantë për thirrësin. Një klient është i ngrirë sapo ndërtohet dhe mund të përdoret pa rrezik nga shumë fije ekzekutimi njëherësh, ndaj një procesi Puma ose Sidekiq i duhet vetëm një, dhe pas një fork-u procesi bir hap lidhjet e veta.
Për rastin që përndryshe do të detyronte një klient për çdo çelës, si një punë në sfond që dërgon në emër të disa hapësirave të punës, jepni api_key: te thirrja. Ai zëvendëson header-in Authorization për atë kërkesë dhe nuk lë asgjë pas te klienti.
message = {from: "[email protected]", to: "[email protected]", subject: "Your invoice", text: "Attached."}workspace_key = ENV.fetch("OPENEMAIL_API_KEY") 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ë filtrave të një liste, ndërsa metodat e temp_mail marrin në vend të tij inbox_token:. Kontrollohet para se të dërgohet kërkesa, me të njëjtin rregull që përdor klienti, ndaj një gabim shtypi ngre një ArgumentError për api_key-n e dhënë në këtë thirrje, në vend të një 401 për një kredencial që pastaj duhet ta kërkoni. Një thirrje e riprovuar e ruan çelësin që iu dha.
client.mode përshkruan çelësin me të cilin u NDËRTUA klienti dhe nuk ndjek një mbishkrim. Kur një klient shërben disa çelësa, nuk ka një modalitet të vetëm për të raportuar, ndaj lexojeni nga çelësi që dhatë. client.inspect tregon modalitetin dhe URL-në bazë, kurrë çelësin.
Endpoint-e që nuk i mbështjell asnjë metodë
client.raw është transporti përmes të cilit kalon çdo metodë. client.raw.request thërret një shteg që ende nuk e mbështjell asnjë metodë, duke zbatuar kredencialin, URL-në bazë, afatin e skadimit dhe politikën e riprovimit të klientit, dhe kthen trupin e analizuar ashtu si një metodë.
ping = client.raw.request("/ping") label = client.raw.request("/labels", method: :post, body: {name: "Invoices"}) p ping[:ok], label[:id]| Fjala kyçe | Çfarë bën |
|---|---|
| method: | :get, përveç nëse thoni ndryshe: :post, :put, :patch ose :delete. |
| query: | Një Hash parametrash query. Vlerat nil dhe ato bosh lihen jashtë, një Array ose një Set bashkohen me presje, dhe një Time dërgohet si një çast ISO 8601. |
| body: | Një Hash, i dërguar si JSON. |
| raw: dhe content_type: | Bajte për t’u dërguar ashtu siç janë, si String binar, IO ose Pathname, me application/octet-stream përveç nëse emërtoni një tip. |
| accept: dhe binary: | Një accept: tjetër nga JSON e kthen trupin si tekst, ndërsa binary: true e kthen si String binar. |
| idempotent: dhe idempotency_key: | idempotent: true bashkëngjit një Idempotency-Key, të gjeneruar përveç nëse jepni tuajin. |
| repeatable: | Nëse një dështim riprovohet. Riprovohet vetëm një GET, përveç nëse jepni repeatable: true. |
| api_key: dhe timeout: | I njëjti çelës për thirrje dhe një afat skadimi në sekonda vetëm për këtë thirrje. |
Shtegu duhet të fillojë me një / të vetme, dhe një shteg URL-ja përfundimtare e të cilit do të dilte nga origjina e URL-së bazë ngre ArgumentError para se të dërgohet çfarëdo, ndaj kredenciali nuk arrin kurrë te një host tjetër.
Kuti të përkohshme
OpenEmail.create_temp_mail ndërton një klient për kutitë e përkohshme që nuk mban çelës API dhe nuk lexon asnjë nga mjedisi. Krijon kuti në mënyrë anonime, dhe çdo lexim dërgon tokenin e kutisë që ktheu create, ose atë më të riun që ktheu extend, qoftë në çdo thirrje si inbox_token:, qoftë një herë si OpenEmail.create_temp_mail(inbox_token:).
temp_mail = OpenEmail.create_temp_mail inbox = temp_mail.createpage = temp_mail.list_messages(inbox[:id], inbox_token: inbox[:token]) p page.items.size, page.expires_atcreate_temp_mail merr base_url:, adapter:, max_retries:, timeout:, user_agent:, headers: dhe disable_update_notice: si çdo klient, dhe lexon OPENEMAIL_BASE_URL kur nuk jepni URL bazë.
Tokenat e qasjes OAuth
Një aplikacion që një person 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ë çdo gjë që i përgjigjet call dhe e kthen atë, si një lambda ose një Method. Ai thirret një herë për çdo thirrje, dhe riprovat e asaj thirrjeje ripërdorin atë që ktheu, ndaj rinovojeni tokenin brenda tij kur i afrohet skadimi, dhe klienti nuk ka nevojë të rindërtohet kurrë.
tokens = {current: "token-from-your-oauth-flow"} oauth_client = OpenEmail::Client.new(access_token: -> { tokens.fetch(:current) }) me = oauth_client.me.get puts me[:clientId], me[:expiresAt] if me[:object] == "oauth_token"| Rasti | Çfarë ndodh |
|---|---|
| api_key: dhe access_token: bashkë, ose asnjëri | Klienti ngre ArgumentError kur ndërtohet. Kur nuk ka asnjërin, 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 fillon me oe_; këtë kontroll e bën OpenEmail.access_token?. Një String që nuk e kalon ngre gabim kur ndërtohet klienti, dhe një objekt i thirrshëm që kthen një të tillë ngre ArgumentError nga thirrja para se të dërgohet çfarëdo. |
| OPENEMAIL_ACCESS_TOKEN | Lexohet nga init, create_client dhe klienti i përbashkët kur nuk jepni asnjë kredencial dhe OPENEMAIL_API_KEY nuk është vendosur, ndaj një çelës në mjedis ka përparësi. |
| Një objekt i thirrshëm që ngre gabim | Thirrja e ngre atë gabim të pandryshuar dhe nuk dërgohet asgjë. |
| Një api_key: për thirrje | Zëvendëson tokenin vetëm për atë kërkesë, dhe objekti i thirrshëm nuk thirret. |
| client.mode | Gjithmonë "live" me një token. |
| OpenEmail.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 nil, clientId e aplikacionit të lidhur dhe expiresAt, kur skadon miratimi që personi i ka dhënë aplikacionit. ping përgjigjet me kind të barabartë me oauth, keyId nil dhe clientId. Kontrolloni object ose kind para se të lexoni id ose keyId. |
Një token vepron në emër të një personi dhe lexon postën e tij ashtu siç mund ta lexojë ai, ndaj mbajeni në një server si një çelës.
Kodet e verifikimit
Para 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ë OpenEmail::PermissionError, një 403 me step_up_required? true, dhe asgjë nuk ndryshoi. 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ë.
domain_id = "b3e1f0a4-6c2d-4e8a-9f17-2d5c8a0b4e6f" begin client.domains.delete(domain_id)rescue OpenEmail::ApiError => error raise unless error.step_up_required? challenge = client.security.begin_step_up if challenge[:method] == "email" puts "Enter the code we emailed to #{challenge[:sentTo]}" else puts "Enter the code from your authenticator app, or a backup code" end client.security.verify_step_up(code: $stdin.gets.to_s.strip) client.domains.delete(domain_id)end| 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 | Hap një sfidë verifikimi. Me email një kod gjashtëshifror shkon te adresa me të cilën personi hyn, dhe sentTo e tregon atë të maskuar. Me totp personi e lexon kodin nga aplikacioni i tij i autentikimit ose përdor një kod rezervë. Një sfidë që është ende e hapur dhe ka përpjekje të mbetura ripërdoret përveç nëse jepni resend: true, ndërsa një sfidë e bllokuar ose e skaduar zëvendësohet nga një thirrje e zakonshme. Çdo aplikacion mund të hapë 5 në orë dhe 20 në 24 orë për çdo person, dhe e radhësja ngre një 429 step_up_throttled. |
| security.verify_step_up(code:) | Kontrollon kodin dhe zhbllokon ndryshimet e ndjeshme për këtë aplikacion për 60 minuta, deri në 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ë thotë kur rifillon verifikimi. |
Klienti nuk kërkon kurrë vetë një kod dhe nuk e përsërit vetë thirrjen, dhe asnjë nga tri metodat nuk riprovohet 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ë, dhe një çelës API që thërret njërën prej tyre merr një 400 step_up_not_applicable. OpenEmail::STEP_UP_ERROR_CODES emërton çdo mënyrë si mund të dështojë një verifikim, dhe faqja e gabimeve të API-së thotë çfarë të bëni për secilën.
Njoftimi për përditësim
Kur në RubyGems ka një version më të ri të gem-it, klienti e thotë këtë një herë për proces, në daljen standarde të gabimeve, me një rresht si ℹ openemail 0.0.2 is available, you are on 0.0.1. të ndjekur nga faqja e gem-it. Kontrolli ekzekutohet kur ndërtohet klienti i parë, në një fije ekzekutimi në sfond me afat skadimi prej dy sekondash, vetëm kur dalja standarde është një terminal, dhe një dështim për të arritur RubyGems shpërfillet.
Kontrolli kalon përmes adapterit të klientit, ndaj një adapter testimi mund të shohë një kërkesë drejt RubyGems kur testet ekzekutohen në një terminal. Ndërtojini klientët e testimit me disable_update_notice: true ose vendosni OPENEMAIL_DISABLE_UPDATE_NOTICE.
Proxy-t
Adapteri i parazgjedhur e gjen proxy-n e tij me URI#find_proxy të vetë Ruby-t, ndaj ndjek të njëjtat rregulla si pjesa tjetër e bibliotekës standarde: https_proxy ose HTTPS_PROXY emërton proxy-n, ndërsa no_proxy ose NO_PROXY rendit hostet që lidhen drejtpërdrejt. Emri i përdoruesit dhe fjalëkalimi në URL-në e proxy-t i dërgohen proxy-t, dhe një server në këtë makinë nuk arrihet kurrë përmes një proxy-je.
Lidhjet përdorin TLS 1.2 ose më të ri dhe kontrollojnë certifikatën e serverit, ndaj një proxy që inspekton TLS ka nevojë që autoriteti i tij i certifikatave të besohet nga OpenSSL në atë makinë.
Testimi pa rrjet
adapter: zëvendëson shtresën HTTP. Është çdo gjë që i përgjigjet call(request), përfshirë një lambda, dhe kthen një OpenEmail::HttpResponse me status, headers dhe body. Kërkesa është një OpenEmail::HttpRequest me method, url, headers, body dhe timeout, ndaj një test mund të kontrollojë saktësisht se çfarë do të ishte dërguar.
requests = [] adapter = lambda do |request| requests << request OpenEmail::HttpResponse.new( status: 200, headers: {"content-type" => "application/json"}, body: JSON.generate({id: "msg_test", status: "sent", replayed: false}) )end test_client = OpenEmail::Client.new(api_key: "oe_test_fake", adapter:, max_retries: 0, disable_update_notice: true) sent = test_client.emails.send(from: "[email protected]", to: "[email protected]", subject: "Hi", text: "Hello") p sent[:status], requests.first.method, requests.first.url, requests.first.headers["Idempotency-Key"]p requests.firstPrintimi i një kërkese e tregon header-in e saj Authorization si [redacted], ndaj një log testimi nuk e mban kurrë çelësin.
- Ktheni një status jashtë 2xx me zarfin e gabimit të API-së si trup, si p.sh.
{"error": {"type": "validation_error", "code": "invalid_parameter", "message": "..."}}, për të marrë nënklasën përkatëse tëOpenEmail::ApiError. - Ngrini
Timeout::Errorngacall, oseNet::ReadTimeout, që është një i tillë, për të marrë njëOpenEmail::NetworkErrormetimeout?true. Çdo StandardError tjetër, siErrno::ECONNREFUSED, bëhet njëNetworkErrormetimeout?false. NameError,TypeErrordheArgumentErrortë ngritura brenda adapterit llogariten si defekte të tij. Ngrihen të pandryshuara dhe nuk riprovohen kurrë.
Ndërtojeni klientin e testimit me max_retries: 0 kur programoni dështime. Përndryshe, një status i riprovueshëm ose një dështim rrjeti te një thirrje që mund të përsëritet pa rrezik provohet tri herë, me pritje të vërteta ndërmjet.