From ec82740ed9db4d8c4d4c2177a062c2c9f8487265 Mon Sep 17 00:00:00 2001 From: Drk0027 Date: Tue, 16 Dec 2025 11:13:04 -0500 Subject: [PATCH] Correcciones documentales. Creado el proyecto envio-reportes-correo --- README.md | 9 +- envio-reportes-correo/.env.example | 15 +++ envio-reportes-correo/README.md | 30 ++++++ envio-reportes-correo/enviar-reporte.py | 99 +++++++++++++++++++ renombrado-sercop/README.md | 30 ++++++ renombrado-sercop/renombrar-archivo.py | 41 ++++++++ .../renombrar-archivos-carpeta.py | 47 +++++++++ 7 files changed, 270 insertions(+), 1 deletion(-) create mode 100644 envio-reportes-correo/.env.example create mode 100644 envio-reportes-correo/README.md create mode 100644 envio-reportes-correo/enviar-reporte.py create mode 100644 renombrado-sercop/README.md create mode 100644 renombrado-sercop/renombrar-archivo.py create mode 100644 renombrado-sercop/renombrar-archivos-carpeta.py diff --git a/README.md b/README.md index bee31ce..cd69215 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ # utilidades-python -Solo un conjunto de scripts python que he escrito bajo alguna necesidad. Si alguno de estos proyectos necesita atención especial, crear un repo exclusivo para el. \ No newline at end of file +Solo un conjunto de scripts python que he escrito bajo alguna necesidad. Si alguno de estos proyectos necesita atención especial, crear un repo exclusivo para el. + +# Indice + +- [renombrado-sercop](/renombrado-sercop/README.md) +- [envio-reportes-correo](/envio-reportes-correo/README.md) + + diff --git a/envio-reportes-correo/.env.example b/envio-reportes-correo/.env.example new file mode 100644 index 0000000..d6d1750 --- /dev/null +++ b/envio-reportes-correo/.env.example @@ -0,0 +1,15 @@ +# Configuraciones de Zimbra SMTP +SMTP_SERVER=mail.tudominio.com +SMTP_PORT=587 +USER=tu.usuario@tudominio.com +PASS=TuContrasenaSegura + +# Configuraciones del Correo +REMITENTE=tu.usuario@tudominio.com +DESTINATARIO_TO=destinatario@ejemplo.com +DESTINATARIO_CC=copia@ejemplo.com +ASUNTO_CORREO="Informe Automático - Archivo Reciente" +CUERPO_CORREO="Hola, Adjunto reporte automatico generado" + +# Ruta a la carpeta de adjuntos (usa barras diagonales /) +CARPETA_ADJUNTOS=./mis_informes \ No newline at end of file diff --git a/envio-reportes-correo/README.md b/envio-reportes-correo/README.md new file mode 100644 index 0000000..5a6257d --- /dev/null +++ b/envio-reportes-correo/README.md @@ -0,0 +1,30 @@ +# Envio de Reportes + +Un Script rápido para enviar el archivo mas reciente de un directorio, a una direccion de correo electronica y con copia a otra direccion. + +Este script es para automatizacion y no cuenta con interfaz grafica. + +# Reglas + +- Dados los datos del achivo ```.env``` se elije el archivo mas reciente del directorio configurado y se envia a las direcciones configuradas. + +# Modo de uso + +- Ejecutar con python 3.x + - Instalar los siguientes modulos: + - smtplib + - dotenv +- renombrar o copiar el archivo [.env.example](.env.example) a ```.env``` +- Llenar los datos necesarios en el archivo ```.env``` + +# Detalles + +||| +|---|---| +|**Autor**|drk0027| +|**Fecha Creacion**|16-12-2025| +|**tags**|automatizaciones, correo-electronico| + +# Observaciones + +¿Funciona? si. Pero no lo pude aprovechar por restricciones que desconocía a la hora de escribir este codigo. \ No newline at end of file diff --git a/envio-reportes-correo/enviar-reporte.py b/envio-reportes-correo/enviar-reporte.py new file mode 100644 index 0000000..6a2f50e --- /dev/null +++ b/envio-reportes-correo/enviar-reporte.py @@ -0,0 +1,99 @@ +import smtplib +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.mime.base import MIMEBase +from email import encoders +import os +import glob +from dotenv import load_dotenv # Importamos la función para cargar el .env + +# Cargar las variables de entorno desde el archivo .env +load_dotenv() + +def enviar_correo_con_adjunto_reciente( + servidor_smtp, puerto_smtp, usuario, contrasena, + remitente, destinatario_principal, destinatario_cc, + asunto, cuerpo_mensaje, carpeta_adjuntos +): + """ + Busca el archivo más reciente en una carpeta y lo envía por correo. + """ + + # 1. Encontrar el archivo más reciente en la carpeta dada + try: + ruta_completa = os.path.abspath(carpeta_adjuntos) + archivos = glob.glob(os.path.join(ruta_completa, '*')) + if not archivos: + print(f"No se encontraron archivos en la carpeta: {ruta_completa}") + return + + archivos.sort(key=os.path.getmtime, reverse=True) + archivo_mas_reciente = archivos[0] # Tomamos el primer elemento (el más reciente) + nombre_archivo = os.path.basename(archivo_mas_reciente) + print(f"Archivo más reciente encontrado: {nombre_archivo}") + + except Exception as e: + print(f"Error al buscar archivos en la carpeta: {e}") + return + + # 2. Crear el mensaje de correo + msg = MIMEMultipart() + msg['From'] = remitente + msg['To'] = destinatario_principal + msg['Cc'] = destinatario_cc + msg['Subject'] = asunto + + msg.attach(MIMEText(cuerpo_mensaje, 'plain')) + + # 3. Adjuntar el archivo + try: + with open(archivo_mas_reciente, "rb") as attachment: + parte = MIMEBase("application", "octet-stream") + parte.set_payload(attachment.read()) + encoders.encode_base64(parte) + parte.add_header( + "Content-Disposition", + f"attachment; filename={nombre_archivo}", + ) + msg.attach(parte) + except IOError as e: + print(f"Error al adjuntar el archivo {archivo_mas_reciente}: {e}") + return + + # 4. Enviar el correo usando SMTP de Zimbra + try: + servidor = smtplib.SMTP(servidor_smtp, puerto_smtp) + servidor.ehlo() + servidor.starttls() + servidor.ehlo() + + servidor.login(usuario, contrasena) + + destinatarios_totales = [destinatario_principal, destinatario_cc] + servidor.sendmail(remitente, destinatarios_totales, msg.as_string()) + + servidor.quit() + + print("Correo enviado exitosamente.") + + except smtplib.SMTPException as e: + print(f"Error al enviar el correo: {e}") + except Exception as e: + print(f"Ocurrió un error inesperado: {e}") + +# --- INVOCACIÓN DE LA FUNCIÓN USANDO VARIABLES DE ENTORNO --- + +if __name__ == "__main__": + # Obtenemos los valores del archivo .env usando os.getenv() + enviar_correo_con_adjunto_reciente( + servidor_smtp=os.getenv("SMTP_SERVER"), + puerto_smtp=int(os.getenv("SMTP_PORT")), # Convertimos el puerto a entero + usuario=os.getenv("USER"), + contrasena=os.getenv("PASS"), + remitente=os.getenv("REMITENTE"), + destinatario_principal=os.getenv("DESTINATARIO_TO"), + destinatario_cc=os.getenv("DESTINATARIO_CC"), + asunto=os.getenv("ASUNTO_CORREO"), + cuerpo_mensaje=os.getenv("CUERPO_CORREO"), + carpeta_adjuntos=os.getenv("CARPETA_ADJUNTOS") + ) diff --git a/renombrado-sercop/README.md b/renombrado-sercop/README.md new file mode 100644 index 0000000..a911e7b --- /dev/null +++ b/renombrado-sercop/README.md @@ -0,0 +1,30 @@ +# Utilidades de renombrado + +Renombrado de archivos pdf segun las reglas del SERCOP. + +El Script [renombrar-archivo.py](renombrar-archivo.py) solo funciona con un archivo a la vez. + +El Script [renombrar-archivos-carpeta.py](renombrar-archivos-carpeta.py) trabaja sobre todos los archivos PDF de una carpeta y crea una nueva con el prefijo sercopready_ en el mismo directorio que contiene a la carpeta de origen. + +# Reglas + +- Reemplazar espacios por guiones bajos +- Reemplazar eñes por 'enes' +- Eliminar caracteres especiales dejando solo letras, números y guiones bajos +- Solo archivos PDF + +# Modo de uso + +Super sencillo. Se asume que tiene python 3.x con tkinter para los dialogos. + +# Detalles + +||| +|--|--| +|**Autor**|drk0027| +|**Fecha creacion**|08-01-2025| +|**Tags**|renombrado, tkinter| + +# Observaciones + +¿Funciona? Si. Esta perfecto para obtener un archivo o carpeta de archivos listos para ser subidos al SERCOP segun sus reglas. \ No newline at end of file diff --git a/renombrado-sercop/renombrar-archivo.py b/renombrado-sercop/renombrar-archivo.py new file mode 100644 index 0000000..cd461e8 --- /dev/null +++ b/renombrado-sercop/renombrar-archivo.py @@ -0,0 +1,41 @@ +import os +import re +from tkinter import Tk, filedialog, messagebox + +def limpiar_nombre_archivo(nombre): + # Cambiar espacios en blanco por guiones bajos + nombre = nombre.replace(' ', '_') + # Cambiar eñes por enes + nombre = nombre.replace('ñ', 'n') + # Eliminar caracteres especiales (dejando solo letras, números y guiones bajos) + nombre = re.sub(r'[^a-zA-Z0-9_]', '', nombre) + return nombre + +def seleccionar_archivo(): + root = Tk() + root.withdraw() # Ocultar la ventana principal de Tkinter + archivo = filedialog.askopenfilename(title="Seleccionar archivo") + + if archivo: + # Obtener el directorio y el nombre del archivo + directorio = os.path.dirname(archivo) + nombre_archivo = os.path.basename(archivo) + + # Limpiar el nombre del archivo + nombre_limpio = limpiar_nombre_archivo(nombre_archivo) + + # Crear nuevo nombre de archivo con la misma extensión + nombre_nuevo = f"{nombre_limpio}{os.path.splitext(nombre_archivo)[1]}" + ruta_nueva = os.path.join(directorio, nombre_nuevo) + + # Crear la copia del archivo + with open(archivo, 'rb') as f_original: + with open(ruta_nueva, 'wb') as f_copia: + f_copia.write(f_original.read()) + + messagebox.showinfo("Éxito", f"Copia creada: {ruta_nueva}") + else: + messagebox.showwarning("Advertencia", "No se seleccionó ningún archivo.") + +if __name__ == "__main__": + seleccionar_archivo() diff --git a/renombrado-sercop/renombrar-archivos-carpeta.py b/renombrado-sercop/renombrar-archivos-carpeta.py new file mode 100644 index 0000000..846161f --- /dev/null +++ b/renombrado-sercop/renombrar-archivos-carpeta.py @@ -0,0 +1,47 @@ +import os +import re +import shutil +from tkinter import Tk, filedialog + +def limpiar_nombre(nombre): + # Reemplazar espacios por guiones bajos + nombre = nombre.replace(' ', '_') + # Reemplazar eñes por 'enes' + nombre = nombre.replace('ñ', 'en') + nombre = nombre.replace('Ñ', 'En') + # Eliminar caracteres especiales dejando solo letras, números y guiones bajos + nombre = re.sub(r'[^a-zA-Z0-9_\.]', '', nombre) + return nombre + +def main(): + # Crear ventana de Tkinter y esconderla + root = Tk() + root.withdraw() + + # Seleccionar carpeta + carpeta_origen = filedialog.askdirectory(title="Selecciona la carpeta con los archivos PDF") + if not carpeta_origen: + print("No se seleccionó ninguna carpeta.") + return + + # Crear carpeta destino + carpeta_destino = os.path.join(os.path.dirname(carpeta_origen), f"sercopready_{os.path.basename(carpeta_origen)}") + os.makedirs(carpeta_destino, exist_ok=True) + + # Procesar archivos PDF + for filename in os.listdir(carpeta_origen): + if filename.lower().endswith('.pdf'): + # Limpiar nombre + nuevo_nombre = limpiar_nombre(filename) + # Mantener extensión .pdf + nuevo_nombre = nuevo_nombre if nuevo_nombre.lower().endswith('.pdf') else nuevo_nombre + '.pdf' + # Rutas completas + ruta_origen = os.path.join(carpeta_origen, filename) + ruta_destino = os.path.join(carpeta_destino, nuevo_nombre) + # Copiar y renombrar archivo + shutil.copy2(ruta_origen, ruta_destino) + + print(f"Archivos procesados y copiados en: {carpeta_destino}") + +if __name__ == "__main__": + main()