Esta página se ha traducido automáticamente y puede contener errores. Leer el original en inglés
Puente Zero-knowledge: Importación automática de correos del banco
Reenvía los correos de alerta del banco directamente a Budgero mediante la Push API usando un asistente local de Python; no se requiere experiencia en programación, no se comparten contraseñas del banco.
En esta guía
- Instala Python + VS Code, genera un token de la Push API de Budgero y una clave de cifrado, y guárdalos en un archivo .env local.
- Usa el script puente inicial para leer los correos de alerta del banco, deja que la IA cree un analizador para tu banco y pruébalo de forma segura en modo dry-run.
- Envía transacciones cifradas a Budgero con el SDK de Python; programa el script para que se ejecute automáticamente una vez validado.
"Si quieres que algo se haga bien, hazlo tú mismo."
Budgero no te pedirá la contraseña de tu banco ni entregará datos a agregadores de terceros. En su lugar, puedes canalizar los correos del banco directamente a Budgero en tu propio equipo. Tus datos fluyen: Correo del banco → Tu script → Budgero (cifrado). Ningún intermediario ve los datos sin cifrar.
Sigue esta guía para principiantes (no se necesita experiencia programando). Mantén todo local y privado.
Parte 1: Instalar las herramientas
- Python 3.12+
- Windows: Descarga Python y marca "Añadir python.exe al PATH."
- Mac: Descarga Python.
- VS Code
- Instala VS Code y ábrelo.
Parte 2: Prepara tu correo (contraseña de aplicación)
Usa una contraseña de aplicación para no almacenar nunca la contraseña principal de tu correo.
- Gmail: Activa la verificación en dos pasos → crea una Contraseña de aplicación (llámala «Budgero Bridge») → copia el código de 16 caracteres.
- Otros proveedores (Outlook/Yahoo/iCloud): busca «Generar contraseña de aplicación para tu proveedor» y sigue sus pasos.
Parte 3: Configura tu proyecto
- Crea una carpeta:
BudgeroBridgeen tu Escritorio. Ábrela en VS Code (Archivo → Abrir carpeta). - Abre una terminal: VS Code → Terminal → Nueva terminal.
- Instala las librerías:
pip install budgero rich pandas python-dotenv imap-tools(En Mac, usa pip3 si lo necesitas.)
- Crea tu archivo de configuración (
.env)
El script necesita saber quién eres y dónde poner los datos. Usamos un archivo.envpara guardar esto de forma segura.- En VS Code, haz clic en Nuevo archivo y nómbralo exactamente
.env(solo dot-env). - Copia y pega el texto de abajo y rellénalo:
- En VS Code, haz clic en Nuevo archivo y nómbralo exactamente
# --- EMAIL SETTINGS ---EMAIL_ADDRESS="[email protected]"EMAIL_APP_PASSWORD="paste_16_char_app_password_here"# --- BANK FILTER SETTINGS ---BANK_SENDER_EMAIL="[email protected]"BANK_SUBJECT_KEYWORD="Transaction Alert"# --- BUDGERO SECURITY ---BUDGERO_API_KEY="paste_your_api_token_here"BUDGERO_ENCRYPTION_KEY="paste_your_space_key_here"# --- DESTINATION SETTINGS ---TARGET_BUDGET_ID="1"TARGET_ACCOUNT_ID="1"TARGET_CATEGORY_ID="5"Qué significa cada cosa:
| Configuración | Qué poner ahí |
|---|---|
EMAIL_ADDRESS | Tu dirección de correo completa (p. ej., [email protected]). |
EMAIL_APP_PASSWORD | La contraseña de aplicación de 16 caracteres del Paso 2 (no tu contraseña de inicio de sesión habitual). |
BANK_SENDER_EMAIL | Abre un recibo bancario reciente y copia la dirección exacta del remitente (p. ej., [email protected]). |
BANK_SUBJECT_KEYWORD | Una palabra o frase que siempre aparezca en el asunto (p. ej., Alerta de transacción, Tu recibo, Compra). |
BUDGERO_API_KEY | Tu token de Push API desde Ajustes → Push API en Budgero. |
BUDGERO_ENCRYPTION_KEY | Tu clave de cifrado del espacio de trabajo desde Ajustes → Push API en Budgero. |
📍 Encontrar tus IDs de destino (modo fácil)
- En Budgero, ve a Ajustes → Push API y baja hasta el final.
- La tabla Tus IDs lista cada Presupuesto, Cuenta y Categoría con su ID.
- Copia los IDs que necesitas:
TARGET_BUDGET_ID: El presupuesto en el que quieres importar.TARGET_ACCOUNT_ID: La cuenta bancaria (p. ej., «Chase Checking») donde deben ir estas transacciones.TARGET_CATEGORY_ID(importante): Usa el ID de tu categoría «Sin categorizar»/«Por asignar» para empezar.
💡 Consejo: Envía todas las importaciones por correo a tu categoría Sin categorizar. Luego crea Reglas en Budgero (p. ej., «Si el Beneficiario contiene Netflix, asigna la Categoría a Suscripciones») para que la app haga la clasificación. Así mantienes el script de Python sencillo.
Mantenlo en secreto, manténlo a salvo. Guarda
.envlocalmente; nunca lo compartas ni lo subas.
Parte 4: Añade el script inicial
Crea bridge.py y pega este script completo:
import osimport imaplibimport emailimport refrom datetime import datetime, timedeltafrom dotenv import load_dotenvfrom rich.console import Consolefrom rich.table import Tablefrom rich.panel import Panelfrom budgero import BudgeroClientfrom budgero.exceptions import APIError, EncryptionError# --- CONFIGURATION & SAFETY ---load_dotenv()console = Console()# 1. SETUP_MODE: Set to True to generate the AI Prompt. Set False to run the bridge.SETUP_MODE = False # 2. DRY_RUN: If True, prints a table but DOES NOT upload to Budgero.DRY_RUN = True # 3. NUM_SAMPLES: How many emails to send to ChatGPT for training (5 is usually fine, if you get incosistent results you can use more sample so LLM can detect more edge cases).NUM_SAMPLES = 5# 4. Lookback in days: How far in the past do you want to search for transaction emails.LOOKBACK_DAYS = 7# --- PASTE YOUR AI-GENERATED FUNCTION BELOW THIS LINE ---def extract_transaction_info(body): """ DEFAULT PLACEHOLDER. Run this script in SETUP_MODE = True to generate the code for this function. """ return None, None, None, None, None# --- END OF PARSING LOGIC ---def imap_since_days(days: int) -> str: d = datetime.today() - timedelta(days=days) return d.strftime('%d-%b-%Y') # IMAP-friendly formatdef connect_imap(): """Helper to connect to Gmail""" mail = imaplib.IMAP4_SSL('imap.gmail.com') mail.login(os.getenv('EMAIL_ADDRESS'), os.getenv('EMAIL_APP_PASSWORD')) mail.select('inbox') return maildef generate_llm_prompt(): """Fetches real emails and creates a ChatGPT prompt""" sender = os.getenv('BANK_SENDER_EMAIL') keyword = os.getenv('BANK_SUBJECT_KEYWORD') console.print(f"[yellow]📡 Connecting to IMAP... Fetching last {NUM_SAMPLES} emails from: {sender}[/yellow]") try: mail = connect_imap() # Search for ANY email from sender (Read or Unread) to get samples status, messages = mail.search(None, f'(FROM "{sender}" SUBJECT "{keyword}")') email_ids = messages[0].split()[-NUM_SAMPLES:] # Get last N if not email_ids: console.print("[red]❌ No emails found! Check your .env sender/keyword.[/red]") return samples = [] for num in email_ids: _, data = mail.fetch(num, '(RFC822)') msg = email.message_from_bytes(data[0][1]) body = msg.get_payload(decode=True).decode(errors='ignore') # Clean up: remove newlines/tabs to save tokens, keep it readable clean_body = body[:2500].replace("\r", "").replace("\n", " ") samples.append(f"--- EMAIL SAMPLE ---\n{clean_body}\n") mail.logout() # Construct the Prompt prompt = f"""I am writing a Python script to parse transaction emails from my bank.I need you to write a Python function called `extract_transaction_info(body)` that takes the raw HTML/text body of an email and returns the transaction details.**Important:** You must import `datetime` inside the function or assume `from datetime import datetime` is available.The Function Signature must be exactly:`return tx_date, amount, note, tx_type, currency`Requirements:1. `tx_date`: **Python datetime object**. Parse the date string found in the email into a real object.2. `amount`: Float. If format is "1.200,50" (European), convert to standard float 1200.50.3. `note`: String. The Merchant Name/Payee. Remove HTML tags like or <br>. Clean extra whitespace.4. `tx_type`: String. "Outflow" or "Inflow".5. `currency`: String (USD, EUR, RSD, etc).6. Return `None, None, None, None, None` if the email is not a transaction receipt.Here are {len(samples)} real samples of my bank emails:{ "".join(samples) } """ console.print(Panel.fit("✅ SAMPLES FETCHED! COPY THE TEXT BELOW INTO CHATGPT:", border_style="green")) print(prompt) console.print(Panel.fit("AFTER CHATGPT REPLIES: Copy the code it gives you and replace the `extract_transaction_info` function in this script.", border_style="blue")) except Exception as e: console.print(f"[red]Connection Error: {e}[/red]")def run_bridge(): """The Main Loop""" sender = os.getenv('BANK_SENDER_EMAIL') keyword = os.getenv('BANK_SUBJECT_KEYWORD') console.print(f"[green]🚀 Starting Budgero Bridge for {sender}...[/green]") if DRY_RUN: console.print("[bold yellow]⚠️ DRY RUN MODE ACTIVE: No data will be uploaded.[/bold yellow]") mail = connect_imap() since = imap_since_days(LOOKBACK_DAYS) # last 7 days # Fetch UNREAD only for the actual run status, messages = mail.search( None, 'FROM', f'"{sender}"', 'SUBJECT', f'"{keyword}"', 'SINCE', since, ) email_ids = messages[0].split() found_transactions = [] # 1. PARSE STAGE for num in email_ids: _, data = mail.fetch(num, '(RFC822)') msg = email.message_from_bytes(data[0][1]) body = msg.get_payload(decode=True).decode(errors='ignore') # --- CALL THE AI GENERATED FUNCTION --- try: tx_date, amount, note, tx_type, currency = extract_transaction_info(body) if amount and tx_date: found_transactions.append({ "date": tx_date, "amount": amount, "note": note, "type": tx_type, "currency": currency, "id": num # Keep email ID to mark as read later if needed }) except Exception as e: console.print(f"[red]Parsing Error on email {num.decode()}: {e}[/red]") mail.logout() if not found_transactions: console.print("[blue]No new transactions found.[/blue]") return # 2. DISPLAY STAGE (The "Nice Table") table = Table(title=f"📥 Found {len(found_transactions)} New Transactions") table.add_column("Date", style="cyan") table.add_column("Amount", style="magenta", justify="right") table.add_column("Currency", style="blue") table.add_column("Payee / Note", style="green") table.add_column("Type", style="yellow") for tx in found_transactions: table.add_row( tx["date"].strftime("%Y-%m-%d"), f"{tx['amount']:.2f}", tx["currency"], tx["note"], tx["type"] ) console.print(table) # 3. UPLOAD STAGE if DRY_RUN: console.print("\n[bold yellow]✋ Dry Run Complete. Set DRY_RUN = False to upload.[/bold yellow]") return console.print("\n[bold green]🚀 Uploading to Budgero...[/bold green]") client = BudgeroClient( api_key=os.getenv('BUDGERO_API_KEY'), encryption_key=os.getenv('BUDGERO_ENCRYPTION_KEY') ) success_count = 0 for tx in found_transactions: try: client.add_transaction( account_id=int(os.getenv('TARGET_ACCOUNT_ID')), category_id=int(os.getenv('TARGET_CATEGORY_ID')), budget_id=int(os.getenv('TARGET_BUDGET_ID')), date=tx["date"], outflow=float(tx["amount"]) if tx["type"] == "Outflow" else 0, inflow=float(tx["amount"]) if tx["type"] == "Inflow" else 0, memo=tx["note"], payee=tx["note"] ) success_count += 1 # Optional: Mark email as read on server after success # mail = connect_imap() # mail.store(tx['id'], '+FLAGS', '\\Seen') # mail.logout() except Exception as e: console.print(f"[red]❌ Upload Error for {tx['note']}: {e}[/red]") console.print(f"[blue]✨ Sync Complete. Successfully imported {success_count} transactions.[/blue]")if __name__ == '__main__': if SETUP_MODE: generate_llm_prompt() else: run_bridge()Parte 5: Enseña al script el formato de tu banco
- Abre
bridge.pyy configuraSETUP_MODE = True. - Ejecuta
python bridge.py(opython3 bridge.py). - El script imprime un prompt de IA con correos de ejemplo. Cópialo.
- Pégalo en ChatGPT/Claude/Gemini. Pídele que escriba
extract_transaction_info(body)según el prompt. - Sustituye la función de marcador de posición
extract_transaction_infoenbridge.pypor la versión de la IA. - Configura
SETUP_MODE = Falsey guarda.
Parte 6: Prueba en simulación y luego actívalo
- Asegúrate de que
DRY_RUN = True. Ejecutapython bridge.py. - Revisa la tabla de salida. Si los importes y las fechas son correctos, configura
DRY_RUN = Falsey vuelve a ejecutar para enviar a Budgero. - ¿No es correcto? Vuelve a ejecutar la configuración con más ejemplos estableciendo
NUM_SAMPLES = 10antes deSETUP_MODE = True.
Automatízalo a diario
- Windows: Usa el Programador de tareas para ejecutar
python bridge.pyuna vez al día. - Mac/Linux: Usa
cron(p. ej.,0 7 * * * /usr/bin/python3 /path/to/bridge.py). - Deja DRY_RUN desactivado cuando confíes en el parser.
Lista de comprobación de seguridad
- Mantén
.enven local; nunca lo confirmes ni lo compartas. - Rota la contraseña de tu aplicación de correo y el token de Budgero Push API si sospechas que han podido quedar expuestos.
- Usa HTTPS (por defecto) para que los tokens estén protegidos en tránsito.
- Si Budgero devuelve un 409 con
message_id, significa que se ha deduplicado un reintento; no se ha insertado ningún duplicado. - Si cambias de banco o de formato, vuelve a ejecutar la configuración para actualizar el analizador.
Ahora tienes un puente zero-knowledge: tu banco nunca comparte contraseñas, tus datos permanecen cifrados y Budgero recibe transacciones automáticamente. Disfruta de la automatización que respeta tu privacidad.