GestorCorreo/modelo.py

213 lines
7.6 KiB
Python

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