Correcciones documentales. Creado el proyecto envio-reportes-correo

This commit is contained in:
2025-12-16 11:13:04 -05:00
parent cd70a1d73b
commit ec82740ed9
7 changed files with 270 additions and 1 deletions

View File

@@ -1,3 +1,10 @@
# utilidades-python # 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. 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)

View File

@@ -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

View File

@@ -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.

View File

@@ -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")
)

View File

@@ -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.

View File

@@ -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()

View File

@@ -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()