jdZddlmZddlZddlZddlZddlZddlZddl Z ddl Z ddl m Z ddlZdZdZdZddZdd ZGd d ej(j*Zddd Zed k(rej2eyy)uoauth_bootstrap.py — flusso OAuth ONE-TIME per ottenere il refresh_token gmail.readonly. Da eseguire UNA SOLA VOLTA, in modo interattivo, con Mauro davanti al browser: lui fa login/consenso come se stesso su maurof.gagliardi@gmail.com. Il risultato (refresh_token) NON viene scritto su disco da questo script: viene stampato su stdout e va copiato a mano nel file .env locale (gitignored) — vedi .env.example. PREREQUISITO (lato Google Cloud Console, fatto da Mauro una volta): 1. Console Google Cloud -> crea/usa un progetto. 2. "API e servizi" -> "Libreria" -> abilita "Gmail API". 3. "API e servizi" -> "Schermata consenso OAuth": - User type: External (va bene) -> pubblica in "Testing" con maurof.gagliardi@gmail.com tra gli utenti di test (in Testing il refresh_token dura ~7 giorni se l'app non e' verificata: valutare "In produzione" per un refresh_token stabile, oppure mettere in conto un re-consenso periodico). - Scope: aggiungere SOLO https://www.googleapis.com/auth/gmail.readonly 4. "Credenziali" -> "Crea credenziali" -> "ID client OAuth" -> tipo "App desktop". -> ottieni CLIENT_ID e CLIENT_SECRET. 5. Mettili nel .env locale come GMAIL_CHECK_CLIENT_ID / GMAIL_CHECK_CLIENT_SECRET (oppure passali qui con --client-id / --client-secret). USO python oauth_bootstrap.py # legge client_id/secret dal .env accanto python oauth_bootstrap.py --env PATH python oauth_bootstrap.py --client-id ... --client-secret ... COSA FA - Avvia un piccolo server locale su http://localhost: (redirect loopback, metodo raccomandato da Google per le app desktop; l'OOB copia-incolla e' deprecato). - Stampa l'URL di autorizzazione: Mauro lo apre, sceglie maurof.gagliardi@gmail.com, concede l'accesso in sola lettura. - Cattura il ?code= dal redirect, lo scambia per i token (access_type=offline + prompt=consent => arriva il refresh_token). - Stampa SOLO il refresh_token su stdout. Nessuna scrittura file. ) annotationsN)Pathz,https://accounts.google.com/o/oauth2/v2/authz#https://oauth2.googleapis.com/tokenz.https://www.googleapis.com/auth/gmail.readonlycp|jsiSi}|jdjD]~}|j}|r|j dsd|vr+|j d\}}}|jjdjd||j<|S)Nutf-8)encoding#="')is_file read_text splitlinesstrip startswith partition)pathoutrawlinekey_vals oauth_bootstrap.pyload_envr8s <<> C~~w~/::<=yy{ts+s$ nnS) Q99;,,S177<CIIK = Jctjtjtj5}|jd|j dcdddS#1swYyxYw)N) 127.0.0.1r)socketAF_INET SOCK_STREAMbind getsockname)ss r free_portr%EsL v~~v'9'9 :"a  }}q!"""s $A!!A*c:eZdZUdZded<dZded<ddZddZy)_CatcherNz str | Nonecodeerrorc0tjjtjj|jj }|j dxsdgdt_|j dxsdgdt_ |jd|jdd|jd}tjrdtj}|jj|jd y) Nr(rr)z Content-Typeztext/plain; charset=utf-8z7OK, puoi chiudere questa scheda e tornare al terminale.zErrore dal consenso: r)urllibparseparse_qsurlparserquerygetr'r(r) send_response send_header end_headerswfilewriteencode)selfparamsmsgs rdo_GETz_Catcher.do_GETOs&&v||'<'>)(..)9:C G,-rcyN)r8_argss r log_messagez_Catcher.log_message[s r)returnNone)__name__ __module__ __qualname__r(__annotations__r)r;r@r>rrr'r'Ks D*E: . rr'c tjd}|jdtt t j jdz d|jdd|jd d|j|}tt |j}|jxs|jd d }|jxs|jd d }|r|std tj yt#}d|}t$j&j)d|ft*}t-j.|j0dj3||dt4ddd} t6dt8j:j=| } tdt| dz t?j@| td|d t*jD2t*jF" t*jDt*jF"|jKt*jFr-tdt*jFtj ytMjNtP||t*jDd |d!d"#} | jRd$k7r9td%| jRd&| jTdd'tj y| jW} | jd(} | std)tj ytd*t| td+y,#tB$rYwxYw#tH$r|jKYywxYw)-Nz)Bootstrap OAuth one-time (gmail.readonly)) descriptionz--envz.envzJfile .env da cui leggere client_id/secret se non passati a riga di comando)defaulthelpz --client-id)rIz--client-secretGMAIL_CHECK_CLIENT_IDGMAIL_CHECK_CLIENT_SECRETzServono client_id e client_secret: mettili nel .env come GMAIL_CHECK_CLIENT_ID / GMAIL_CHECK_CLIENT_SECRET, oppure passali con --client-id / --client-secret.)filezhttp://localhost:rT)targetdaemonr(offlineconsent) client_id redirect_uri response_typescope access_typeprompt?zF Apri questo URL nel browser (login come maurof.gagliardi@gmail.com):  zIn attesa del redirect suz... rzConsenso negato / errore: authorization_code)rT client_secretr( grant_typerUg>@)datatimeoutr+z"Scambio code->token fallito: HTTP  i, refresh_tokenzNessun refresh_token nella risposta (gia' concesso in passato senza prompt=consent?). Revoca l'accesso da https://myaccount.google.com/permissions e riprova.zH === REFRESH TOKEN (copialo nel .env come GMAIL_CHECK_REFRESH_TOKEN) ===zG=== non committarlo, non scriverlo in file sincronizzati in chiaro === r),argparseArgumentParser add_argumentstrr__file__resolveparent parse_argsrenvrTr1r^printsysstderrr%httpserver HTTPServerr' threadingThread serve_foreverstartSCOPEAUTH_URLr,r- urlencode webbrowseropen Exceptionr(r)KeyboardInterruptshutdownhttpxpost TOKEN_URL status_codetextjson)argvparserargsrlrTr^portrUrq auth_paramsurlresppayloadrcs rmainr_s  $ $1\ ]F T(^335< "CF#''*A2"FI&&R#''2Mr*RM M  -   ;D&tf-L [[ # #[$$7 BF F00>DDF$  KJa ..{;< =C TU #*  %|W=mm#(> mm#(>  OO~~ *8>>*:;#**M ::"*MM.(   D 3 243C3C2DAdiiPTQToEVW:: iikGKK0M      UV - TU ]     s%M'AM MMM;:M;__main__)rrrAzdict[str, str])rAintr=)rzlist[str] | NonerAr)__doc__ __future__rrd http.serverrprrnrs urllib.parser,rzpathlibrrrxrrwrr%rqBaseHTTPRequestHandlerr'rrCexitr>rrrs"H#  9 1 8 "  t{{11 (W t z CHHTVr