from google.auth.transport.requests import Request from google_auth_oauthlib.flow import InstalledAppFlow from google.oauth2.credentials import Credentials from google.oauth2 import service_account from googleapiclient.discovery import build import os import sys import json import base64 from email.mime.base import MIMEBase from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email import encoders global base_dir, libs_dir, SCOPES, CREDENTIALS_PATH, TOKEN_PATH, _load_json, get_drive_and_gmail_services, get_doc_name, export_doc_as_pdf, create_message_with_attachment, send_email, drive_service, gmail_service, DOC_ID, doc_name, TO_EMAIL, SUBJECT, BODY_TEXT, to_emails, pdf_filename, pdf_data, result, Request # ===== Rocketbot-compatible py_libs path ===== base_dir = os.path.dirname(sys.executable) if getattr( sys, 'frozen', False) else os.getcwd() libs_dir = os.path.join(base_dir, 'librerias', 'py_libs', 'py310') if os.path.isdir(libs_dir) and libs_dir not in sys.path: sys.path.insert(0, libs_dir) SCOPES = {scopes_api_google} CREDENTIALS_PATH = '{gdoc_sa_json}' TOKEN_PATH = '{gmail_token_json}' def _load_json(path): with open(path, 'r', encoding='utf-8') as f: return json.load(f) def get_drive_and_gmail_services(credentials_json_path=CREDENTIALS_PATH, token_json_path=TOKEN_PATH): info = _load_json(credentials_json_path) # Service account if isinstance(info, dict) and info.get('type') == 'service_account': creds = service_account.Credentials.from_service_account_file( credentials_json_path, scopes=SCOPES) drive_service = build( 'drive', 'v3', credentials=creds, cache_discovery=False) gmail_service = build( 'gmail', 'v1', credentials=creds, cache_discovery=False) return drive_service, gmail_service # OAuth flow creds = None if os.path.exists(token_json_path): creds = Credentials.from_authorized_user_file(token_json_path, SCOPES) if not creds or not creds.valid: if creds and creds.expired and creds.refresh_token: creds.refresh(Request()) else: flow = InstalledAppFlow.from_client_secrets_file( credentials_json_path, SCOPES) try: creds = flow.run_local_server(port=0) except Exception: creds = flow.run_console() os.makedirs(os.path.dirname(token_json_path), exist_ok=True) with open(token_json_path, 'w', encoding='utf-8') as f: f.write(creds.to_json()) drive_service = build( 'drive', 'v3', credentials=creds, cache_discovery=False) gmail_service = build( 'gmail', 'v1', credentials=creds, cache_discovery=False) return drive_service, gmail_service def get_doc_name(drive_service, doc_id): """Obtiene el nombre del documento de Google Drive""" file_metadata = drive_service.files().get( fileId=doc_id, fields='name' ).execute() return file_metadata.get('name', 'documento') def export_doc_as_pdf(drive_service, doc_id): request = drive_service.files().export_media( fileId=doc_id, mimeType='application/pdf') return request.execute() def create_message_with_attachment(to_emails, subject, body_text, attachment_bytes, attachment_filename='documento.pdf'): if isinstance(to_emails, (list, tuple)): to_header = ', '.join(to_emails) recipients = to_emails else: to_header = str(to_emails) recipients = [to_header] message = MIMEMultipart() message['to'] = to_header message['subject'] = subject message.attach(MIMEText(body_text, 'plain')) part = MIMEBase('application', 'pdf') part.set_payload(attachment_bytes) encoders.encode_base64(part) part.add_header('Content-Disposition', f'attachment; filename="{attachment_filename}"') message.attach(part) raw_message = base64.urlsafe_b64encode(message.as_bytes()).decode() return {'raw': raw_message} def send_email(gmail_service, to_emails, subject, body_text, attachment_bytes, attachment_filename='documento.pdf'): message_body = create_message_with_attachment( to_emails, subject, body_text, attachment_bytes, attachment_filename) return gmail_service.users().messages().send(userId='me', body=message_body).execute() drive_service, gmail_service = get_drive_and_gmail_services( CREDENTIALS_PATH, TOKEN_PATH) # Id del documento de Google Drive a enviar por email DOC_ID = '{gdoc_id}' print(DOC_ID) # Obtener nombre del documento de Google doc_name = get_doc_name(drive_service, DOC_ID) print(doc_name) # Configuración del email TO_EMAIL = '{email_copia_envio_contrato_finalizado}' SUBJECT = doc_name # --> ZUBA 27 - 306 - ROQUE SANTACRUZ BODY_TEXT = """{email_mensaje}""" print(TO_EMAIL) print(SUBJECT) print(BODY_TEXT) # Permite múltiple destinatarios separados por coma to_emails = [email.strip() for email in TO_EMAIL.split(',') if email.strip()] if not to_emails: raise ValueError( 'Debe especificar al menos un destinatario en TO_EMAIL') if not os.path.exists(CREDENTIALS_PATH): raise FileNotFoundError( f'No existe el archivo de credenciales: {CREDENTIALS_PATH}') pdf_filename = f"{doc_name}.pdf" pdf_data = export_doc_as_pdf(drive_service, DOC_ID) result = send_email(gmail_service, to_emails, SUBJECT, BODY_TEXT, pdf_data, pdf_filename) print('Mensaje enviado. ID:', result.get('id')) SetVar('res_envio', True)