Files
scripts_zubabot/envio_contrato_docs_email.py

170 lines
5.5 KiB
Python

from google.oauth2 import service_account
from googleapiclient.discovery import build
import os
import sys
import json
import re
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_json2}'
IMPERSONATED_USER = '{gdoc_impersonated_user}'
def rb_get_var(name, required=True, default=''):
try:
value = GetVar(name)
except NameError:
value = os.environ.get(name, default)
if value is None:
value = ''
value = str(value).strip()
if value == f'{{{name}}}':
value = ''
if required and not value:
raise RuntimeError(f'La variable Rocketbot "{name}" está vacía o no fue leída correctamente.')
return value
def extract_doc_id_from_url(url):
match = re.search(r"/document/d/([a-zA-Z0-9_-]+)", url or "")
return match.group(1) if match else ""
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, impersonated_user=IMPERSONATED_USER):
info = _load_json(credentials_json_path)
if not isinstance(info, dict) or info.get('type') != 'service_account':
raise RuntimeError('gdoc_sa_json2 debe apuntar a un JSON de cuenta de servicio.')
impersonated_user = (impersonated_user or '').strip()
if not impersonated_user:
raise RuntimeError('Falta la variable gdoc_impersonated_user.')
creds = service_account.Credentials.from_service_account_file(
credentials_json_path, scopes=SCOPES, subject=impersonated_user)
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, IMPERSONATED_USER)
# Id del documento de Google Drive a enviar por email
CURRENT_URL = rb_get_var('current_url')
DOC_ID = extract_doc_id_from_url(CURRENT_URL)
if not DOC_ID:
raise RuntimeError('No pude extraer documentId desde current_url: ' + CURRENT_URL)
try:
SetVar('gdoc_id', DOC_ID)
SetVar('gdoc_url_used', CURRENT_URL)
except NameError:
pass
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)