From bf73b52d1264f3b220ce15d981c1fb65d70b5343 Mon Sep 17 00:00:00 2001 From: Santi Date: Tue, 4 Feb 2025 12:28:44 +0100 Subject: [PATCH] =?UTF-8?q?A=C3=B1adimos=20la=20la=20solapa=20de=20correos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/misc.xml | 3 + .idea/vcs.xml | 6 ++ app/main.py | 19 ++++- correo_server/EmailTab.py | 80 ++++++++++++++++++ correo_server/MailClient.py | 41 +++++++++ correo_server/__init__.py | 0 .../__pycache__/EmailTab.cpython-313.pyc | Bin 0 -> 6637 bytes .../__pycache__/MailClient.cpython-313.pyc | Bin 0 -> 3120 bytes .../__pycache__/__init__.cpython-313.pyc | Bin 0 -> 184 bytes hilos/__pycache__/ChatWidget.cpython-313.pyc | Bin 4951 -> 4951 bytes 10 files changed, 146 insertions(+), 3 deletions(-) create mode 100644 .idea/vcs.xml create mode 100644 correo_server/EmailTab.py create mode 100644 correo_server/MailClient.py create mode 100644 correo_server/__init__.py create mode 100644 correo_server/__pycache__/EmailTab.cpython-313.pyc create mode 100644 correo_server/__pycache__/MailClient.cpython-313.pyc create mode 100644 correo_server/__pycache__/__init__.cpython-313.pyc diff --git a/.idea/misc.xml b/.idea/misc.xml index 7a7809b..59934d8 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/main.py b/app/main.py index 60f65c5..5c65050 100644 --- a/app/main.py +++ b/app/main.py @@ -4,7 +4,8 @@ import time import datetime from tkinter import Menu # Importar el widget Menu from tkinter import ttk # Importar el widget ttk - +from correo_server.EmailTab import MailTab +from correo_server.MailClient import MailClient from hilos.ChatWidget import ChatWidget from hilos.MusicPlayer import MusicPlayer from hilos.WeatherWidget import WeatherWidget @@ -17,9 +18,20 @@ from solapas.SQLQueryExecutor import SQLQueryExecutor from solapas.TicTacToe import TicTacToe from solapas.WebScraperToDB import WebScraperToDB +# Configuración del servidor de correos +smtp_server = "192.168.120.103" +smtp_port = 465 +imap_server = "192.168.120.103" +imap_port = 993 +username = "tu_usuario@psp.ieslamar.org" +password = "tu_contraseña" + # Clave de API de OpenWeatherMap API_KEY = "1fa8fd05b650773bbc3f2130657e808a" +# Crear cliente de correo +mail_client = MailClient(smtp_server, smtp_port, imap_server, imap_port, username, password) + def update_time(status_bar): """Función que actualiza la hora y el día de la semana en un label""" while True: @@ -175,13 +187,14 @@ notebook.add(tab5, text="Solapa 5", padding=4) # Añadir el widget de Web Scraper a la Solapa 5 web_scraper = WebScraperToDB(tab5) +# Crear e inicializar la pestaña de correos +email_tab = MailTab(notebook, mail_client) + # Barra de estado # Dividir la barra de estado en 4 labels - # Usar pack para alinear los labels horizontalmente label_fecha_hora = tk.Label(barra_estado, text="Hilo fecha-hora", font=("Helvetica", 14), bd=1, fg="blue", relief="sunken", anchor="w", width=20, padx=10) - label_fecha_hora.pack(side="right", fill="x", expand=True) # barra_estado.grid(row=1, column=0, columnspan=3, sticky="ew") diff --git a/correo_server/EmailTab.py b/correo_server/EmailTab.py new file mode 100644 index 0000000..33bdacf --- /dev/null +++ b/correo_server/EmailTab.py @@ -0,0 +1,80 @@ +import tkinter as tk +from tkinter import ttk, messagebox +import threading + +class MailTab: + def __init__(self, notebook, mail_client): + self.mail_client = mail_client + + # Crear el frame de la pestaña dentro del Notebook + self.frame = ttk.Frame(notebook) + notebook.add(self.frame, text="Correo") # ← Ahora esto es correcto + + # Campos de entrada para credenciales + ttk.Label(self.frame, text="Correo electrónico:").grid(row=0, column=0, sticky="e", padx=5, pady=5) + self.entry_email = ttk.Entry(self.frame, width=40) + self.entry_email.grid(row=0, column=1, padx=5, pady=5) + + ttk.Label(self.frame, text="Contraseña:").grid(row=1, column=0, sticky="e", padx=5, pady=5) + self.entry_password = ttk.Entry(self.frame, show="*", width=40) + self.entry_password.grid(row=1, column=1, padx=5, pady=5) + + self.login_button = ttk.Button(self.frame, text="Iniciar Sesión", command=self.login) + self.login_button.grid(row=2, column=1, padx=5, pady=5, sticky="e") + + # Campos para enviar correo + ttk.Label(self.frame, text="Destinatario:").grid(row=3, column=0, padx=5, pady=5, sticky="e") + self.recipient_entry = ttk.Entry(self.frame, width=40) + self.recipient_entry.grid(row=3, column=1, padx=5, pady=5) + + ttk.Label(self.frame, text="Asunto:").grid(row=4, column=0, padx=5, pady=5, sticky="e") + self.subject_entry = ttk.Entry(self.frame, width=40) + self.subject_entry.grid(row=4, column=1, padx=5, pady=5) + + ttk.Label(self.frame, text="Mensaje:").grid(row=5, column=0, padx=5, pady=5, sticky="ne") + self.body_text = tk.Text(self.frame, width=50, height=10) + self.body_text.grid(row=5, column=1, padx=5, pady=5) + + self.send_button = ttk.Button(self.frame, text="Enviar", command=self.send_email_thread) + self.send_button.grid(row=6, column=1, padx=5, pady=5, sticky="e") + + # Widgets para recibir correos + self.receive_button = ttk.Button(self.frame, text="Recibir Correos", command=self.fetch_emails_thread) + self.receive_button.grid(row=7, column=1, padx=5, pady=5, sticky="e") + + self.emails_listbox = tk.Listbox(self.frame, height=10, width=80) + self.emails_listbox.grid(row=8, column=0, columnspan=2, padx=5, pady=5) + + def login(self): + email = self.entry_email.get() + password = self.entry_password.get() + result = self.mail_client.login(email, password) + if result: + messagebox.showinfo("Inicio de Sesión", "Inicio de sesión exitoso") + else: + messagebox.showerror("Error", "Credenciales incorrectas") + + def send_email_thread(self): + threading.Thread(target=self.send_email).start() + + def send_email(self): + recipient = self.recipient_entry.get() + subject = self.subject_entry.get() + body = self.body_text.get("1.0", tk.END).strip() + result = self.mail_client.send_email(recipient, subject, body) + messagebox.showinfo("Resultado", result) + + def fetch_emails_thread(self): + threading.Thread(target=self.fetch_emails).start() + + def fetch_emails(self): + try: + result = self.mail_client.fetch_emails() + if isinstance(result, list): + self.emails_listbox.delete(0, tk.END) + for email in result: + self.emails_listbox.insert(tk.END, email[:100]) # Mostrar los primeros 100 caracteres + else: + messagebox.showerror("Error", result) + except Exception as e: + print(f"Error al recibir correos: {e}") diff --git a/correo_server/MailClient.py b/correo_server/MailClient.py new file mode 100644 index 0000000..ead2e55 --- /dev/null +++ b/correo_server/MailClient.py @@ -0,0 +1,41 @@ +import smtplib +import imaplib + +class MailClient: + def __init__(self, smtp_server, smtp_port, imap_server, imap_port, username, password): + self.smtp_server = smtp_server + self.smtp_port = smtp_port + self.imap_server = imap_server + self.imap_port = imap_port + self.username = username + self.password = password + + def send_email(self, recipient, subject, body): + """Envía un correo utilizando el servidor SMTP.""" + try: + with smtplib.SMTP_SSL(self.smtp_server, self.smtp_port) as server: + server.login(self.username, self.password) + message = f"Subject: {subject}\\n\\n{body}" + server.sendmail(self.username, recipient, message) + return "Correo enviado correctamente" + except Exception as e: + return f"Error al enviar el correo: {str(e)}" + + def fetch_emails(self): + """Obtiene los correos más recientes utilizando el servidor IMAP.""" + try: + with imaplib.IMAP4_SSL(self.imap_server, self.imap_port) as server: + server.login(self.username, self.password) + server.select("inbox") + status, messages = server.search(None, "ALL") + email_ids = messages[0].split() + emails = [] + + for email_id in email_ids[-5:]: # Obtener los últimos 5 correos + status, msg_data = server.fetch(email_id, "(RFC822)") + for response_part in msg_data: + if isinstance(response_part, tuple): + emails.append(response_part[1].decode()) + return emails + except Exception as e: + return f"Error al recibir correos: {str(e)}" diff --git a/correo_server/__init__.py b/correo_server/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/correo_server/__pycache__/EmailTab.cpython-313.pyc b/correo_server/__pycache__/EmailTab.cpython-313.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55a00126b79639ad54ed3b8ec52c2864aa356692 GIT binary patch literal 6637 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