Ver https://developers.google.com/gmail/api/quickstart/python
Repositorio GIT de código google para utilizar esta API
1. Permitir la API (Enable the API)
Si clicamos donde se indica podemos crear proyectos o modificar uno existente.
Le damos a SIGUIENTE
Y aparece esta pantalla y le damos a HABILITAR para habilitar la API
2. Configurar la pantalla de consentimiento de OAuth
Entrar en https://console.cloud.google.com/iam-admin
Añadir un usuario habilitado y su correo electronico con el botón "+ ADD USERS" y después seleccionarlo en el filtro
3. Autorizar las credenciales para una apliocación de escritorio
Entrar en https://console.cloud.google.com/apis/credentials
Clicar el boton de "+ CREAR CREDENCIALES" y seleccionar "ID de Cliente de OAuth"
Y aparece esta pantalla donde seleccionamos App de escritorio y le damos un nombre
Y le damos al btón de CREAR
Y aparece esta pantalla
y podemos decargar el JSON y le damos a ceptar
El ficheo JSON es
{ "installed":{ "client_id":"*********************************************.apps.googleusercontent.com", "project_id":"********-***-******", "auth_uri":"https://accounts.google.com/o/oauth2/auth", "token_uri":"https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs", "client_secret":"******-********-*****************", "redirect_uris":["http://localhost"] } }
Hay que guardar dicho fichero en el directorio de trabajo con el nombre de "credentials.json"
4. Instalar las librerías de cliente de Google
En nuestro caso nos vamos a la carpeta donde está el entorno de python:
En una ventana de comandos ejecutar:
#1.Cambiamos de directorio.
cd ~/MyOdoo/Control-Presencia #2.Instalamos los paquetes de Google indicando la ruta del ejecutable python en
# el entorno virtual
./bin/python -m pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
5. Crear un programa Python para registrar las credenciales
Ahora nos vamos al direcotrio de nuestro proyecto y creamos el fichero "quickstart.py".
que contendrá este código modificado por el tema de localización de ficheros dentro de la carpeta de trabajo.
Hay que tener cuidado con la variable SCOPES!!! como veremos mas adelante.
import os.path import sys from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build from googleapiclient.errors import HttpError # If modifying these scopes, delete the file token.json. SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"] def main(): """Shows basic usage of the Gmail API. Lists the user's Gmail labels. """ creds = None # The file token.json stores the user's access and refresh tokens, and is # created automatically when the authorization flow completes for the first # time. LOCAL_PATH= os.path.dirname(os.path.abspath(sys.argv[0])) tokenFile=LOCAL_PATH+"/"+"token.json" if os.path.exists(tokenFile): creds = Credentials.from_authorized_user_file(tokenFile, SCOPES) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: credentialsFile=LOCAL_PATH+"/"+"credentials.json" flow = InstalledAppFlow.from_client_secrets_file( credentialsFile, SCOPES ) creds = flow.run_local_server(port=0) # Save the credentials for the next run with open(tokenFile, "w") as token: token.write(creds.to_json()) try: # Call the Gmail API service = build("gmail", "v1", credentials=creds) results = service.users().labels().list(userId="me").execute() labels = results.get("labels", []) if not labels: print("No labels found.") return print("Labels:") for label in labels: print(label["name"]) except HttpError as error: # TODO(developer) - Handle errors from gmail API. print(f"An error occurred: {error}") if __name__ == "__main__": main()
Y cuando lo ejecutmos por primera vez nos pedirá que aceptemos las condiciones etc.. y al final creará un fichero "token.json" en nuestra carpeta de trabajo que permitirá ejecutar el programa sin pedirlo mas veces.
6. Enviar un correo
Si no cambiamos la linea de SCOPES nos dará un error:
googleapi: Error 403: Request had insufficient authentication scopes.
Hay que tener en cuenta que en el programa anterior tenemos en la línea 11:
# If modifying these scopes, delete the file token.json. SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]
que indica claramente que solo podemos leer correos. Si queremos enviar hay que utiliar otros SCOPES.
Los scopes vienen dados en https://developers.google.com/gmail/api/auth/scopes
Para nuestro caso queremos enviar un correo, por tanto podemos cambiar la línea por esta otra
# If modifying these scopes, delete the file token.json. SCOPES = ["https://www.googleapis.com/auth/gmail.send"]
y tenemos que borrar el fichero "token.json"
Aquí hay un programa simple que verifica si un fichero es mas antiguo de 0,25 dias y si lo es envia un correo a una cuenta.
import os.path as path import sys import base64 import time from email.message import EmailMessage from google.auth.transport.requests import Request from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from googleapiclient.discovery import build from googleapiclient.errors import HttpError # If modifying these scopes, delete the file token.json. SCOPES = ["https://www.googleapis.com/auth/gmail.send"] ''' Mail Utils ''' #============================================================================== # GENERAL #============================================================================== def getGMailCredentials()->object: creds = None # The file token.json stores the user's access and refresh tokens, and is # created automatically when the authorization flow completes for the first # time. LOCAL_PATH= path.dirname(path.abspath(sys.argv[0])) tokenFile=LOCAL_PATH+"/"+"token.json" if path.exists(tokenFile): creds = Credentials.from_authorized_user_file(tokenFile, SCOPES) # If there are no (valid) credentials available, let the user log in. if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: credentialsFile=LOCAL_PATH+"/"+"credentials.json" flow = InstalledAppFlow.from_client_secrets_file( credentialsFile, SCOPES ) creds = flow.run_local_server(port=0) # Save the credentials for the next run with open(tokenFile, "w") as token: token.write(creds.to_json()) return creds def sendGMail(senderEmail:str='ximodante@gmail.com', message:str='Prueba', receiversEmail:list[str]=['receiver@gmail.com']): """Create and send an email message Print the returned message id Returns: Message object, including message id Load pre-authorized user credentials from the environment. TODO(developer) - See https://developers.google.com/identity for guides on implementing OAuth2 for the application. """ #creds, _ = google.auth.default() creds=getGMailCredentials() try: service = build("gmail", "v1", credentials=creds) eMessage = EmailMessage() eMessage.set_content("This is automated draft mail") eMessage["To"] = receiversEmail[0] eMessage["From"] = senderEmail eMessage["Subject"] = message # encoded message encoded_message = base64.urlsafe_b64encode(eMessage.as_bytes()).decode() create_message = {"raw": encoded_message} # pylint: disable=E1101 send_message = ( service.users() .messages() .send(userId="me", body=create_message) .execute() ) print(f'Message Id: {send_message["id"]}') except HttpError as error: print(f"An error occurred: {error}") send_message = None return send_message #if __name__ == "__main__": # gmail_send_message() # [END gmail_send_message] def myTestCron(): try: senderEmail=sys.args[1] message=sys.args[2] receiversEmail=[sys.args[3]] filePath=sys.args[4] except: senderEmail='ximodante@gmail.com' message='Ha fallat la importació del padró de OESIA' receiversEmail=['receiver@gmail.com'] #a010 filePath='/mnt/NASDADES_DOCS/A0-003_INFORMATICA/ASS/ASS2024/AS2024-0042_Padro_habitants_policia/PH_ROLAN_ODOO.xlsx' #filePath='Z:\\A0-003_INFORMATICA\\ASS\\ASS2024\\AS2024-0042_Padro_habitants_policia\\PH_ROLAN_ODOO.xlsx' if path.exists(filePath): if (time.time() - path.getmtime(filePath)) / (3600 *24) > 1: print('File older than 1 day') sendGMail(senderEmail=senderEmail, message=('Fitxer > 1 dia ' + message), receiversEmail=receiversEmail) else: sendGMail(senderEmail, ('No existeix el fitxer ' + message), receiversEmail) #------ main myTestCron()
No hay comentarios :
Publicar un comentario