import poplib import email import pymongo from email.utils import parsedate_to_datetime import smtplib from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from email.mime.base import MIMEBase from email import encoders from datetime import datetime import re import os class CorreoModelo: POP3_SERVER = "s1.ieslamar.org" #192.168.120.103 POP3_PORT = 110 #110 SMTP_SERVER = "s1.ieslamar.org" #s1.ieslamar.org SMTP_PORT = 25 #25 EMAIL_USER = "kevin@fp.ieslamar.org" EMAIL_PASS = "1234" MONGO_CLIENT = "mongodb://localhost:27017/" DB_NAME = "correo_db" COLLECTION_NAME = "correoc" #*s CARPETA_ADJUNTOS = "archivosAdjuntados" def __init__(self): self.client = pymongo.MongoClient(self.MONGO_CLIENT) self.db = self.client[self.DB_NAME] self.collection = self.db[self.COLLECTION_NAME] if not os.path.exists(self.CARPETA_ADJUNTOS): os.makedirs(self.CARPETA_ADJUNTOS) def correo_existe(self, remitente, asunto, fecha): return self.collection.find_one({"remitente": remitente, "asunto": asunto, "fecha": fecha}) is not None def guardar_correo(self, remitente, asunto, fecha, cuerpo, archivos_adjuntos=[]): if self.correo_existe(remitente, asunto, fecha): return correo = { "remitente": remitente, "asunto": asunto, "fecha": fecha, "cuerpo": cuerpo, "archivos_adjuntos": archivos_adjuntos # Guardar archivos adjuntos } self.collection.insert_one(correo) def descargar_archivo_adjunto(self, correo_id): """Descarga los archivos adjuntos de un correo seleccionado.""" correo = self.collection.find_one({"_id": correo_id}) if not correo: return False, "Correo no encontrado en la base de datos." archivos_adjuntos = correo.get("archivos_adjuntos", []) if not archivos_adjuntos: return False, "No hay archivos adjuntos en este correo." rutas_descargadas = [] for archivo_nombre in archivos_adjuntos: ruta_guardado = os.path.join(self.CARPETA_ADJUNTOS, archivo_nombre) try: # Simulación de descarga del archivo adjunto with open(ruta_guardado, "wb") as f: f.write(b"Contenido de prueba") # En una implementación real, aquí iría el contenido del adjunto. rutas_descargadas.append(ruta_guardado) except Exception as e: return False, f"Error al descargar el archivo: {e}" return True, f"Archivos guardados en: {', '.join(rutas_descargadas)}" def descargar_correos(self): try: mail = poplib.POP3(self.POP3_SERVER, self.POP3_PORT) mail.user(self.EMAIL_USER) mail.pass_(self.EMAIL_PASS) num_mensajes = len(mail.list()[1]) mensajes_nuevos = False for i in range(1, num_mensajes + 1): response, lines, octets = mail.retr(i) raw_email = b"\n".join(lines) msg = email.message_from_bytes(raw_email) remitente = msg["From"] asunto = msg["Subject"] fecha = msg["Date"] if fecha: try: fecha = parsedate_to_datetime(fecha).strftime("%Y-%m-%d %H:%M:%S") except Exception: pass cuerpo = "" archivos_adjuntos = [] if msg.is_multipart(): for part in msg.walk(): if part.get_content_maintype() == "multipart": continue if part.get_content_type() == "text/plain": cuerpo = part.get_payload(decode=True).decode(errors="ignore") if part.get("Content-Disposition") is not None: filename = part.get_filename() if filename: archivos_adjuntos.append(filename) if not self.correo_existe(remitente, asunto, fecha): self.guardar_correo(remitente, asunto, fecha, cuerpo.strip(), archivos_adjuntos) mensajes_nuevos = True mail.quit() return True except Exception as e: return str(e) def obtener_correos(self): correos = list(self.collection.find()) for correo in correos: correo["_id"] = str(correo["_id"]) if "archivos_adjuntos" not in correo: correo["archivos_adjuntos"] = [] return correos def hay_mensajes_nuevos(self): try: mail = poplib.POP3(self.POP3_SERVER, self.POP3_PORT) mail.user(self.EMAIL_USER) mail.pass_(self.EMAIL_PASS) num_mensajes = len(mail.list()[1]) for i in range(1, num_mensajes + 1): response, lines, octets = mail.retr(i) raw_email = b"\n".join(lines) msg = email.message_from_bytes(raw_email) remitente = msg["From"] asunto = msg["Subject"] fecha = msg["Date"] if fecha: try: fecha = parsedate_to_datetime(fecha).strftime("%Y-%m-%d %H:%M:%S") except Exception: pass if not self.correo_existe(remitente, asunto, fecha): mail.quit() return True mail.quit() return False except Exception as e: return False @staticmethod def enviar_correo(destinatario, asunto, mensaje, archivos_adjuntos=[]): try: if not CorreoModelo.validar_correo(destinatario): return False, "Dirección de correo inválida" if len(archivos_adjuntos) > 1: return False, "Solo se permite un archivo adjunto" fecha_envio = datetime.now().strftime("%Y-%m-%d %H:%M:%S") msg = MIMEMultipart() msg["From"] = CorreoModelo.EMAIL_USER msg["To"] = destinatario msg["Subject"] = asunto msg["Date"] = fecha_envio msg.attach(MIMEText(mensaje, "plain")) # Adjuntar el único archivo permitido if archivos_adjuntos: archivo = archivos_adjuntos[0] if os.path.exists(archivo): with open(archivo, "rb") as adjunto: part = MIMEBase("application", "octet-stream") part.set_payload(adjunto.read()) encoders.encode_base64(part) part.add_header("Content-Disposition", f"attachment; filename={os.path.basename(archivo)}") msg.attach(part) server = smtplib.SMTP(CorreoModelo.SMTP_SERVER, CorreoModelo.SMTP_PORT) server.ehlo() server.login(CorreoModelo.EMAIL_USER, CorreoModelo.EMAIL_PASS) server.sendmail(CorreoModelo.EMAIL_USER, destinatario, msg.as_string()) server.quit() return True, f"Correo enviado a {destinatario} el {fecha_envio}" except Exception as e: return False, f"Error enviando correo: {e}" @staticmethod def validar_correo(destinatario): patron = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$" return re.match(patron, destinatario) is not None