Contenido del curso

Menú de consola para Inbox en Kotlin

Resumen

Construir una interfaz por consola en Kotlin para un simulador de correos requiere combinar un bucle infinito, la expresión when y un manejo de excepciones con try catch. Aprenderás a conectar la capa de UI con el InboxService y sus repositorios, dejando cada clase con su propia responsabilidad.

Este recurso es útil si estás cerrando un proyecto en Kotlin y necesitas un menú interactivo que envíe correos, liste carpetas, marque como leído, mueva entre carpetas, elimine y simule recepción.

¿Cómo se arma el menú principal con while y triple comilla?

La idea es sencilla: un while(true) que imprima el menú una y otra vez hasta que el usuario decida salir [01:30]. Para que el bloque de texto se vea ordenado en consola, se usan triples comillas que permiten escribir el menú en varias líneas sin concatenar strings.

El menú expone siete opciones numeradas:

  1. Enviar correo.
  2. Listar carpetas.
  3. Marcar como leído.
  4. Mover un correo de carpeta.
  5. Eliminar un correo.
  6. Recibir un correo simulado.
  7. Salir del simulador.

La opción siete rompe el bucle, las demás ejecutan acciones contra el servicio.

¿Para qué sirve el triple comilla en Kotlin? Permite definir strings multilínea sin caracteres de escape, ideal para imprimir menús, plantillas o bloques de texto largos tal cual los escribes.

¿Cómo se enrutan las opciones con when y readLine?

Después de mostrar el menú, lees la entrada con readLine() y le aplicas .trim() para limpiar espacios en blanco. Esa cadena entra a una expresión when que ramifica las acciones según el número escrito [02:30].

Dentro de cada rama vive la lógica de cada acción. La de enviar correo pide tres datos por consola, to, subject y body, y luego invoca service.sendEmail(currentUser, to, sub, body). Aquí aparece un detalle de sintaxis: si quieres declarar varias expresiones en la misma línea, puedes usar punto y coma, aunque en Kotlin no es lo común y conviene mantener una expresión por línea.

¿Cómo convertir un string en un valor de enum?

Para la opción de listar carpetas [04:35] necesitas que el texto que escribe el usuario se transforme en un valor del enum Folder. Eso se logra con Folder.valueOf(readLine()!!.trim().uppercase()).

El método valueOf recupera el valor del enum a partir de un string que coincida exactamente con uno de sus nombres, en este caso Inbox, Sent, Archive o Spam. Es case sensitive, por eso se aplica uppercase() para evitar errores cuando el usuario escribe en minúsculas.

Luego, service.listByFolder(currentUser, folder) devuelve la lista. Si está vacía, imprimes vacío; si no, recorres con forEachIndexed para mostrar cada correo numerado por su índice.

¿Cómo se ejecutan las acciones de marcar, mover y eliminar?

Estas tres acciones siguen el mismo patrón: pedir un identificador y delegar al servicio.

Para marcar como leído [06:20] solicitas el ID del correo, lo conviertes con UUID.fromString(readLine()!!.trim()) y llamas a service.markAsRead(currentUser, id). La conversión es necesaria porque el ID viaja como texto pero el servicio espera un UUID.

Para mover un correo pides dos datos: el ID a mover y la nueva carpeta. La carpeta se obtiene igual que en listar, con Folder.valueOf sobre el input en mayúsculas. El servicio recibe currentUser, id y newFolder, y al final imprimes correo movido como confirmación.

Para eliminar basta con el ID y la llamada a service.deleteEmail(currentUser, id).

¿Por qué la UI queda tan corta? Porque toda la lógica vive en el servicio y los repositorios. La consola solo recoge datos y delega, lo que demuestra el valor de separar responsabilidades.

¿Cómo simular la recepción de un correo en el inbox?

La opción seis reutiliza la misma estructura de enviar correo, pide from, subject y body, pero con una diferencia conceptual importante [09:15]. La opción uno envía un correo hacia afuera, hacia la bandeja de otro usuario. La opción seis simula que tú recibes un correo en tu propio inbox.

La llamada queda como service.sendEmail(currentUser, from, subject, body) y al terminar imprimes correo recibido a inbox.

¿Cómo salir del bucle y manejar excepciones con try catch?

La opción siete imprime Adiós y ejecuta break, la forma más rápida de forzar la salida de un while en Kotlin [10:45]. Después del break, el programa continúa hasta terminar de forma natural.

Falta una pieza crítica: envolver toda la lógica del while en un try catch. Esto captura cualquier excepción que lancen los servicios, por ejemplo cuando un ID no existe o una carpeta no es válida.

kotlin try { when (readLine()?.trim()) { "1" -> { /* enviar correo */ } // resto de opciones "7" -> { println("Adiós"); break } } } catch (e: Exception) { println("Error: ${e.message}") }

El catch genérico atrapa cualquier Exception. Si más adelante necesitas reaccionar distinto según el tipo de error, puedes encadenar varios bloques catch específicos, tal como viste en las clases de excepciones.

Con esto queda lista la implementación del inbox simulator. ¿Cómo organizarías tú las opciones del menú o qué validaciones extra agregarías antes de invocar al servicio? Cuéntalo en los comentarios.