Tema 4 - Generación de Servicios en Red Parte II PDF
Document Details

Uploaded by StateOfTheArtSwan
Tags
Summary
Este documento trata sobre la generación de servicios en red, cubriendo temas como las librerías Apache Commons y la comunicación HTTP. También se discuten las peticiones HTTP basadas en HttpURLConnection y las opciones de Java para el desarrollo de comunicaciones web.
Full Transcript
```markdown ## Your role - You are a tool to convert images and documents into a structured markdown format. - Transcribe text. - Keep all important facts, figures etc. - Remove unnecessary spacing and punctuation. - Summarize any messy text but stay very true to the original text. - If text is not...
```markdown ## Your role - You are a tool to convert images and documents into a structured markdown format. - Transcribe text. - Keep all important facts, figures etc. - Remove unnecessary spacing and punctuation. - Summarize any messy text but stay very true to the original text. - If text is not visible on truncated, you can guess what it might say when confident in order to return a complete sentence. - Avoid returning incomplete sentences and tables - Convert any math formula into LaTeX format, for example: $f(x) = -4(x + 3)2 + 2$. - Do not include the image or links to an image. - Instead, do your best job at describing the image. - If the image is of a piece of paper or a book, ignore background objects and focus on the text. - Format text using markdown headings, lists and tables - Do you best job of converting tables and diagrams into markdown, or describing them in detail. - Always write in the same language as the text in the image or document. ## 4. Generación de Servicios en Red ## Informática y Comunicaciones ### 4.2.2. Librerías: Apache Commons Apache Commons es un conjunto de librerías Java de código abierto creadas en el ámbito de la Apache Software Foundation, una organización sin ánimo de lucro dedicada al desarrollo de software. Las librerías de Apache Commons cubren diversos aspectos del desarrollo de software a través de componentes dedicados a temas tan dispares como la gestión de trazas (logs), las operaciones matemáticas y estadísticas o la generación de números aleatorios, por citar algunos ejemplos. Figure 4.5 shows a screenshot of "Apache Commons - Apache Com", with the URL `commons.apache.org` Underneath is the Apache Commons logo with the text "Apache Commons" and `http://commons.apache.org/` followed by "Last Published" underneath the logo. En lo referente a la generación de servicios en red, las librerías más relevantes son Commons Email para el envío y recepción de correos electrónicos y Apache Commons Net con implementaciones de los protocolos de internet. Estas librerías proporcionan implementaciones alternativas a las disponibles en el lenguaje Java. ### 4.3. Comunicación mediante HTTP La generación de servicios basados en el protocolo HTTP tiene dos perspectivas, correspondientes al cliente y al servidor. En este libro se aborda la perspectiva cliente, aprendiendo a desarrollar aplicaciones en Java que sean capaces de realizar peticiones HTTP para obtener información proporcionada por sitios o servicios web. La otra perspectiva proporciona la capacidad de desarrollar aplicaciones y servicios web, pero queda fuera del ámbito de este libro. Debido a cuestiones relacionadas con las licencias y la evolución de las versiones de Java, existen dos modelos para la realización de peticiones HTTP: el utilizado hasta la versión 1.8 de Java y el incorporado a partir de la versión 11. En esta unidad se van a presentar ambas opciones. ### 4.3.1. Peticiones HTTP basadas en HttpUrlConnection Hasta la versión 1.8 de Java, la clase `HttpURLConnection` del paquete `java.net` ha sido la base de la programación de aplicaciones capaces de acceder a recursos de la web. Los pasos para realizar con esta clase una petición HTTP sin parámetros son los siguientes: * Creación de URL. * Apertura de la conexión. * Configuración de la conexión: * Método HTTP. * Tipo de contenido. * Sistema de codificación. * Agente de usuario a utilizar. * Obtención y evaluación del código de respuesta HTTP. Si el código es 200: * Obtención del objeto `InputStream` para lectura (si aplica). * Lectura del stream. * Obtención del objeto `OutputStream` para escritura (si aplica). * Escritura en el stream. * Desconexión. ### Actividad resuelta 4.1 #### Petición HTTP con `HttpUrlConnection` (Java 8) La web del diccionario de la RAE (Real Academia Española) permite consultar el significado de las palabras de la lengua española. Dispone de un sencillo formulario que facilita la introducción de una palabra para realizar la búsqueda. Esta palabra se concatena a la URL para realizar la petición del recurso correspondiente. Por ejemplo, si se introduce la palabra *edificio* en el formulario de búsqueda, se solicita el recurso `https://dle.rae.es/edificio`. Por lo tanto, la petición es de tipo GET y no dispone de parámetros. Figure shows a screenshot of "edificio Definición | Diccionario" from `dle.rae.es/`, showing the Real Academia Española logo and "Diccionario de la lengua española" text. A search bar has the word "edificio" and a text saying "1. m. Construcción estable, hecha con materiales resistentes," En esta actividad se pide la creación de un programa Java que haga peticiones a la web de la RAE y que almacene el código HTML obtenido en un fichero. ## ### Solución Fichero GestorPeticionesHTTP.java ```java package es.paraninfo.http; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class GestorPeticionesHTTP { public StringBuilder getContenidoMetodoGet(String direccion) throws Exception { StringBuilder respuesta = new StringBuilder(); URL url = new URL(direccion); HttpURLConnection conexion = (HttpURLConnection) url.openConnection(); conexion.setRequestMethod("GET"); conexion.setRequestProperty("Content-Type", "text/plain"); conexion.setRequestProperty("charset", "utf-8"); conexion.setRequestProperty("User-Agent", "Mozilla/5.0"); int estado = conexion.getResponseCode(); Reader streamReader = null; if (estado == HttpURLConnection.HTTP_OK) { streamReader = new InputStreamReader(conexion.getInputStream()); int caracter; while ((caracter = streamReader.read()) != -1) { respuesta.append((char) caracter); } } else { throw new Exception("Error HTTP -" + estado); } conexion.disconnect(); return respuesta; } public static void writeFile(String strPath, String contenido) throws IOException { Path path = Paths.get(strPath); byte[] strToBytes = contenido.getBytes(); Files.write(path, strToBytes); } public static void main(String[] args) { try { String esquema = "https://"; String servidor = "dle.rae.es/"; String recurso = URLEncoder.encode("Tiburon", StandardCharsets.UTF_8.name()); GestorPeticionesHTTP gp = new GestorPeticionesHTTP(); String direccion = esquema + servidor + recurso; StringBuilder resultado = gp.getContenidoMetodoGet(direccion); GestorPeticionesHTTP.writeFile("G:/tiburon.html", resultado.toString()); System.out.println("Descarga finalizada"); } catch (Exception e) { System.err.println(e.getMessage()); } } } ``` Hay que destacar la necesidad de codificar la palabra buscada mediante el método encode de la clase `URLEncoder` para que caracteres como la letra ñ, los espacios en blanco o las vocales con tilde tengan el formato aceptado por el protocolo. ### Actividad resuelta 4.2 #### Petición HTTP con parámetros con `HttpUrlConnection` (Java 8) IMDb (Internet Movie Database o Base de Datos de Películas en Internet) es una web que contiene infinidad de información relacionada con el cine y la televisión, incluyendo películas, series, actores, directores, etc. Esta web proporciona un formulario de búsqueda en el que se puede introducir cualquier palabra o palabras para buscar películas, actores o empresas que contengan dichas palabras. Al introducir las palabras, el formulario genera una petición HTTP de tipo GET que incluye un parámetro con nombre `q` y con valor las palabras introducidas. Por ejemplo, si se introducen las palabras `star wars` la petición creada es `https://www.imdb.com/find?q=star+wars`. Figure shows a screenshot of "Find - IMDb" from `imdb.com/find?q=star+wars`, showing the IMDb logo and "Results for "star wars"". It lists the movie names and the option "View: More title matches or Exact title matches" En esta actividad se pide crear un programa en Java que dada una palabra o palabras realice una petición HTTP a la web de IMDb y almacene el resultado en un fichero HTML. ```java package es.paraninfo.http; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class GestorPeticionesHTTPParams { public StringBuilder getContenidoMetodoGet(String direccion) throws Exception { StringBuilder respuesta = new StringBuilder(); URL url = new URL(direccion); HttpURLConnection conexion = (HttpURLConnection) url.openConnection(); conexion.setRequestMethod("GET"); conexion.setRequestProperty("Content-Type", "text/plain"); conexion.setRequestProperty("charset", "utf-8"); conexion.setRequestProperty("User-Agent", "Mozilla/5.0"); int estado = conexion.getResponseCode(); Reader streamReader = null; if (estado == HttpURLConnection.HTTP_OK) { streamReader = new InputStreamReader(conexion.getInputStream()); int caracter; while ((caracter = streamReader.read()) != -1) { respuesta.append((char) caracter); } } else { throw new Exception("Error HTTP -" + estado); } conexion.disconnect(); return respuesta; } public static void writeFile(String strPath, String contenido) throws IOException { Path path = Paths.get(strPath); byte[] strToBytes = contenido.getBytes(); Files.write(path, strToBytes); } public static void main(String[] args) { try { String esquema = "https://"; String servidor = "www.imdb.com"; String path = "/find"; String texto = URLEncoder.encode("Tiburón", StandardCharsets.UTF_8.name()); String parametros = "?q=" + texto; GestorPeticionesHTTPParams gp = new GestorPeticionesHTTPParams(); String direccion = esquema + servidor + path + parametros; StringBuilder resultado = gp.getContenidoMetodoGet(direccion); GestorPeticionesHTTPParams.writeFile("G:/tiburon_movie.html", resultado.toString()); System.out.println("Descarga finalizada"); } catch (Exception e) { e.printStackTrace(); } } } ``` ### 4.3.2. Peticiones HTTP basadas en java.net.http A partir de la versión 11 de Java, se introdujo el paquete java.net.http para proporcionar una alternativa más potente, sencilla y actualizada de realizar peticiones HTTP (admite HTTP/1.1, HTTP/2 y WebSockets). #### Recuerda Los WebSockets permiten establecer una comunicación bidireccional basada en eventos entre un servidor web y un navegador. Para la realización de las peticiones HTTP convencionales se utilizan principalmente tres clases: * HttpClient * HttpRequest * HttpResponse #### Informática y Comunicaciones ### 4. Generación de Servicios en Red Para realizar una petición HTTP se deben realizar los siguientes pasos: * Crear el objeto `HttpClient`, indicando versión del protocolo, así como otros datos opcionales como el comportamiento en caso de que existan redirecciones del servidor. * Crear el objeto `HttpRequest`, indicando la URI y los parámetros de la cabecera de la petición. * Realizar la petición a través del método send del `HttpClient` y asignar la respuesta de la petición a un objeto `HttpResponse`. * Procesar la respuesta. ### Actividad resuelta 4.3 ##### Petición HTTP con `java.net.http` (Java 11 y superior) Realizar el mismo ejercicio propuesto en la Actividad resuelta 4.1 utilizando las clases del paquete `java.net.http`. ```java package es.paraninfo.http; import java.net.HttpURLConnection; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.nio.file.Path; public class GestorPeticionesHTTP { public int almacenarPagina(String esquema, String servidor, String recurso, String path) throws Exception { recurso = URLEncoder.encode(recurso, StandardCharsets.UTF_8); String direccion = esquema + servidor + recurso; HttpClient httpClient = HttpClient .newBuilder() .version(HttpClient.Version.HTTP_1_1) .followRedirects(HttpClient.Redirect.NORMAL) .build(); HttpRequest request = HttpRequest.newBuilder() .GET() .uri(URI.create(direccion)) .headers("Content-Type", "text/plain") .setHeader("User-Agent", "Mozilla/5.0") .build(); HttpResponse<Path> response = httpClient.send(request, HttpResponse.BodyHandlers.ofFile(Path.of(path))); return response.statusCode(); } public static void main(String[] args) { try { String esquema = "https://"; String servidor = "dle.rae.es/"; String recurso = new String("Campeón").toLowerCase(); GestorPeticionesHTTP gestor = new GestorPeticionesHTTP(); int codigoEstado = gestor.almacenarPagina(esquema, servidor, recurso, "G:/resultado.html"); if (codigoEstado == HttpURLConnection.HTTP_OK) { System.out.println("Descarga finalizada"); } else { System.err.println("Error " + codigoEstado); } } catch (Exception e) { e.printStackTrace(); } } } ``` ### Actividad propuesta 4.1 Acceso a un servicio web que proporcione un fichero JSON, recuperarlo y mostrar el contenido por la consola Buscar y estudiar el funcionamiento de algún servicio web gratuito que proporcione información en formato JSON. Desarrollar una aplicación que acceda al mismo, recupere información y la muestre por pantalla. Algunas sugerencias de servicios web que cumplen con estos estos requisitos son las si-guiente: * Open Movie Database - `http://www.omdbapi.com/` * Consulta de premios de la Lotería de Navidad de El País - `https://servicios.elpais.com/sorteos/loteria-navidad/api/` * Datos de la Agencia Estatal de Meteorología - `https://opendata.aemet.es/centrode-descargas/inicio` ### 4.4. Transferencia de ficheros mediante FTP En Java, de manera nativa, es posible realizar transferencias de ficheros mediante este protocolo, pero es sumamente árido. La librería Apache Commons Net proporciona clases y utilidades para realizar cualquier operación sobre un servidor FTP o FTPS desde un cliente Java. Esta librería se puede descargar desde la web de apache.org a través del siguiente enlace: `https://commons.apache.org/proper/commons-net/` Las clases principales se encuentran en el paquete `org.apache.commons.net.ftp` y se muestran en la Tabla 4.13. **Table 4.13. Principales clases de Apache Commons Net referentes al servicio FTP** | Clase | Descripción | | :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | FTP | Proporciona la funcionalidad necesaria para implementar un cliente FTP. Incluye constantes para indicar el tipo de ficheros que se van a transmitir y la configuración de estos | | FTPClient | Subclase de FTP, encapsula la funcionalidad necesaria para subir y descargar ficheros a través del protocolo FTP. | | FTPSClient | Subclase de FTPClient, permite utilizar el protocolo FTP sobre SSL. | | FTPFile | Representa información sobre los ficheros almacenados en el servidor. | | FTPReply | Almacena las constantes que representan los códigos de retorno del protocolo FTP. | La clase FTPClient es la que proporciona los métodos de comunicación con el servidor, permitiendo realizar todas las operaciones que admite el protocolo FTP. Los métodos más comunes se presentan en la Tabla 4.14. **Table 4.14. Principales métodos de la clase FTPClient** | Método | Descripción | | :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------- | | connect | Permite establecer la conexión con un servidor a partir de su nombre de host y su puerto (método heredado de org.apache.commons.net. SocketClient). | | changeToParentDirectory | Cambia el directorio de trabajo del servidor al directorio padre del actual. | | changeWorkingDirectory | Cambia el directorio de trabajo del servidor. | | deleteFile | Borra un fichero en el servidor. | | disconnect | Cierra la conexión con servidor FTP. | | getReplyCode | Proporciona el código de repuesta de una petición FTP (método heredado de `org. apache.commons.net. ftp.FTP`). | | listDirectories | Proporciona los directorios existentes en el directorio de trabajo del servidor. | | listFiles | Proporciona los ficheros existentes en el directorio de trabajo del servidor. | | login | Permite acceder al servidor usando una cuenta de usuario. | | logout | Desconecta la cuenta del usuario validado. | | makeDirectory | Crea un directorio en el servidor. | | rename | Renombra un fichero en el servidor. | | retrieveFile | Descarga un fichero del servidor al cliente. | | setFileType | Permite indicar el tipo de fichero que se va a transferir. | | storeFile | Sube un fichero desde el cliente al servidor. | #### Recuerda Las cuentas de usuario de FTP pueden tener distintos permisos, por lo que los métodos de la clase FTPClient funcionarán en función de que dichos permisos estén correctamente configurados. ### Actividad resuelta 4.4 #### Subida y descarga de un fichero a través de FTP Crear una aplicación Java que suba un fichero al servidor FTP y que lo descargue después a una ubicación local distinta a la del origen del fichero. #### Solución Instalar un servidor FTP en una máquina que sea accesible por red desde el ordenador en el que se va a ejecutar el programa, crear una cuenta de usuario con permisos de subida y descarga de ficheros y arrancar el servidor. Crear un proyecto Java con el IDE que se desee e incluir la librería `commons-net-3.8.0.jar` o la versión actualizada equivalente. ```java package es.paraninfo.clienteftp; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketException; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import org.apache.commons.net.ftp.FTP; public class GestorFTP { private FTPClient clienteFtp; private static final String SERVIDOR = "localhost"; private static final int PUERTO = 21; private static final String USUARIO = "fpaniagua"; private static final String PASSWORD = "psp$1971"; public GestorFTP() { clienteFtp = new FTPClient(); } private void conectar() throws SocketException, IOException { clienteFtp.connect(SERVIDOR, PUERTO); int respuesta = clienteFtp.getReplyCode(); if (!FTPReply.isPositiveCompletion(respuesta)) { clienteFtp.disconnect(); throw new IOException("Error al conectar con el servidor FTP"); } boolean credencialesOk = clienteFtp.login(USUARIO, PASSWORD); if (!credencialesOk) { throw new IOException("Error al conectar con el servidor FTP. Credenciales incorrectas."); } clienteFtp.setFileType(FTP.BINARY_FILE_TYPE); } private void desconectar() throws IOException { clienteFtp.disconnect(); } private boolean subirFichero(String path) throws IOException { File ficheroLocal = new File(path); InputStream is = new FileInputStream(ficheroLocal); boolean enviado = clienteFtp.storeFile(ficheroLocal.getName(), is); is.close(); return enviado; } private boolean descargarFichero(String ficheroRemoto, String pathLocal) throws IOException { OutputStream os = new BufferedOutputStream(new FileOutputStream(pathLocal)); boolean recibido = clienteFtp.retrieveFile(ficheroRemoto, os); os.close(); return recibido; } public static void main(String[] args) { GestorFTP gestorFtp = new GestorFTP(); try { gestorFtp.conectar(); System.out.println("Conectado"); boolean subido = gestorFtp.subirFichero("G:/Cosmos-CARL-SAGAN.rar"); if (subido) { System.out.println("Fichero subido correctamente"); } else { System.err.println("Ha ocurrido un error al intentar subir el fichero"); } boolean descargado = gestorFtp.descargarFichero("Cosmos-CARL-SAGAN.rar", "j:/Cosmos. rar"); if (descargado) { System.out.println("Fichero descargado correctamente"); } else { System.err.println("Ha ocurrido un error al intentar descargar el fichero"); } gestorFtp.desconectar(); System.out.println("Desconectado"); } catch (Exception e) { System.err.println("Ha ocurrido un error:" + e.getMessage()); } } } ``` ### Actividad propuesta 4.2 ##### Descarga de ficheros a través de FTP Construir un programa en Java que descargue todos los ficheros contenidos en la carpeta raíz de un servidor FTP. ### 4.5. Programación de envíos y recepción de correos electrónicos El envío y recepción de correos electrónicos desde las clases nativas de Java es posible pero sumamente árido y laborioso. Por suerte, existen alternativas que proporcionan mecanismos más sencillos y compactos. El framework JavaMail dispone de las clases necesarias para poder programar las acciones más habituales que podría realizar un sistema informático en relación con los correos electrónicos, tales como el envío y la recepción de mensajes con y sin adjuntos. La forma más sencilla de configurar un proyecto para utilizar JavaMail es utilizando Maven, una herramienta para la configuración de proyectos. Un proyecto Maven que quiera utilizar JavaMail, debe incorporar la siguiente dependencia en el fichero de configuración (pom.xml): ```xml <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> <version>1.6.2</version> </dependency> ``` Si no se desea configurar el proyecto con Maven, se puede utilizarJavaMail descargando y añadiendo al proyecto las librerías contenidas en los ficheros `javax.mail.jar` y `javax.activation-1.2.0.jar`. El proceso de envío de correos electrónicos compuestos únicamente por textos consta de los siguientes pasos: #### Informática y Comunicaciones ### 4. Generación de Servicios en Red * Creación de la sesión, indicando la URL del servidor de SMTP, el puerto, si utiliza SSL y si se requiere autenticación. * Creación del mensaje (objeto `Message`). En este objeto se incluye la dirección de correo del emisor, la del destinatario, el asunto y el texto del mensaje. * Establecimiento de la conexión (creación de objeto `Transport`), indicando el sistema de transporte. * Envío del mensaje. * Cierre de la conexión. Si el correo lleva ficheros adjuntos, la creación del mensaje se divide en varias etapas. El proceso completo es el siguiente: * Creación de la sesión, indicando la URL del servidor de SMTP, el puerto, si utiliza SSL y si se requiere autenticación. * Creación del mensaje (objeto `Message`). En este objeto se incluyen la dirección de correo del emisor, la del destinatario y el asunto. Además, la creación del mensaje implica: * Creación de la instancia de BodyPart que contiene el texto del mensaje. * Creación de la instancia de MimeBodyPart que contiene el adjunto del mensaje. * Creación de la instancia de Multipart, que agrupa al objeto BodyPart y al objeto MimeBodyPart. * Inclusión del objeto Multipart en el mensaje. * Establecimiento de la conexión (creación de objeto Transport), indicando el sistema de transporte. * Envío del mensaje. * Cierre de la conexión. Por su parte, la lectura de los correos electrónicos almacenados en un servidor IMAP consta de los siguientes pasos: * Creación de la sesión (Session) IMAP, indicando el protocolo, el nombre del host, el puerto, si utiliza SSL y el servidor de confianza asociado. * Configuración y obtención del almacén (Store). * Obtención de la conexión a través del almacén, indicando identificador y contraseña de la cuenta. * Obtención de la carpeta que se desea leer. * Apertura de la carpeta. * Obtención de los mensajes. * Procesado de los mensajes. #### Actividad resuelta 4.5 ##### Configuración de la cuenta de Gmail para el envío de correos electrónicos desde aplicaciones externas (no seguras) Gmail es un servicio de correo electrónico proporcionado por la empresa Google. Proporciona cuentas de correo electrónico gratuitas. Debido a su política de seguridad, la configuración de las cuentas impide que aplicaciones externas accedan a ellas salvo que se realicen ciertos cambios. Para programar aplicaciones en Java, o en cualquier otro lenguaje, que puedan acceder a una cuenta de correo electrónico de Gmail, hay que habilitar la verificación en dos pasos y generar una contraseña de aplicación. El objetivo de esta actividad es realizar dicha activación y poder así generar una contraseña de aplicación. **Solución** Entrar en la cuenta de correo de Gmail desde un navegador web y acceder a la gestión de la cuenta. Para ello, hay que pulsar el icono con la imagen asociada a la cuenta que se encuentra en la parte superior derecha de la página web y, posteriormente, el botón «Gestionar tu cuenta de Google». Figure shows a screenshot of Gmail settings page, showing the logo image followed by "Fernando Paniagua" text, with the button "Gestionar tu cuenta de Google". A continuación, seleccionar la opción «Seguridad» en el panel izquierdo y acceder a la ventana de activación del acceso seguro pulsando «Activar acceso (no se recomienda)». #### ### Informática y Comunicaciones Inicio Contraseña Última modificación: 17 ene > Usar tu teléfono para iniciar sesión No Datos y privacidad Seguridad No Verificación en dos pasos Contactos e información compartida ### Actividad resuelta 4.6 ##### Envío de correos electrónicos con y sin adjuntos desde una cuenta GMail ***Nota***. Esta actividad se tiene que efectuar después de haber realizado la Actividad resuelta 4.5. Esta actividad tiene como objetivos el envío de un correo electrónico que incluya solo texto y de otro correo que incluya un fichero adjunto utilizando una cuenta de Gmail. Durante la ejecución, el programa solicitará al usuario la dirección de correo electrónico de la cuenta y la contraseña. Dicha contraseña no se muestra cifrada en pantalla, por lo que hay que asegurarse de que no hay nadie observando. El texto del mensaje y el adjunto están codificados en el código. ```java package es.paraninfo.psp.email; import java.io.File; import java.io.IOException; import java.util.Properties; import java.util.Scanner; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.NoSuchProviderException; import javax.mail.Session; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.Transport; public class GestorEmail { private Properties propiedades; private Session sesion; private void setPropiedadesServidorSMTP() { propiedades = System.getProperties(); propiedades.put("mail.smtp.auth", "true"); propiedades.put("mail.smtp.host", "smtp.gmail.com"); propiedades.put("mail.smtp.port", "587"); propiedades.put("mail.smtp.starttls.enable", "true"); sesion = Session.getInstance(propiedades, null); } private Transport conectarServidorSMTP(String direccionEmail, String password) throws NoSuchProviderException, MessagingException { Transport t = (Transport) sesion.getTransport("smtp"); t.connect(propiedades.getProperty("mail.smtp.host"),direccionEmail, password); return t; } private Message crearNucleoMensaje (String emisor, String destinatario, String asunto) throws AddressException, MessagingException { Message mensaje = new MimeMessage(sesion); mensaje.setFrom(new InternetAddress(emisor)); mensaje.addRecipient(Message.RecipientType.TO, new InternetAddress(destinatario)); mensaje.setSubject(asunto); return mensaje; } private Message crearMensajeTexto (String emisor, String destinatario, String asunto, String textoMensaje) throws MessagingException, AddressException, IOException { Message mensaje = crearNucleoMensaje(emisor, destinatario, asunto); mensaje.setText(textoMensaje); return mensaje; } private Message crearMensajeConAdjunto (String emisor, String destinatario, String asunto, String textoMensaje, String pathFichero) throws MessagingException, AddressException, IOException { Message mensaje = crearNucleoMensaje(emisor, destinatario, asunto); BodyPart bodyPart = new MimeBodyPart(); bodyPart.setText(textoMensaje); MimeBodyPart mimeBodyPart = new MimeBodyPart(); mimeBodyPart.attachFile(new File(pathFichero)); Multipart multipart = new MimeMultipart(); multipart.addBodyPart(bodyPart); multipart.addBodyPart(mimeBodyPart); mensaje.setContent(multipart); return mensaje; } public void enviarMensajeTexto(String emisor, String destinatario, String asunto, String textoMensaje, String direccionEmail, String password) throws AddressException, MessagingException, IOException { setPropiedadesServidorSMTP(); Message mensaje = crearMensajeTexto(emisor, destinatario, asunto, textoMensaje); Transport t = conectarServidorSMTP(direccionEmail, password); t.sendMessage(mensaje, mensaje.getAllRecipients()); t.close(); return; } public void enviarMensajeConAdjunto(String emisor, String destinatario, String asunto, String textoMensaje, String direccionEmail, String password, String pathFichero) throws AddressException, MessagingException, IOException { setPropiedadesServidorSMTP(); Message mensaje = crearMensajeConAdjunto(emisor, destinatario, asunto, textoMensaje, pathFichero); Transport t = conectarServidorSMTP(direccionEmail, password); t.sendMessage(mensaje, mensaje.getAllRecipients()); t.close(); return; } } ``` Contraseña de aplicaciones Ninguna > ### A continuación, se deberá elegir «Otra» en la selección de aplicación, indicar un hombre para la aplicación y pulsar el botón «Generar». ```java package es.paraninfo.psp.email; import java.io.File; import java.io.IOException; import java.util.Properties; import java.util.Scanner; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; import javax.mail.NoSuchProviderException; import javax.mail.Session; import javax.mail.internet.AddressException; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; import javax.mail.Transport; public class GestorEmail { private Properties propiedades; private Session sesion; private void setPropiedadesServidorSMTP() { propiedades = System.getProperties(); propiedades.put("mail.smtp.auth", "true"); propiedades.put("mail.smtp.host", "smtp.gmail.com"); propiedades.put("mail.smtp.port", "587"); propiedades.put("mail.smtp.starttls.enable", "true"); sesion = Session.getInstance(propiedades, null); } private Transport conectarServidorSMTP(String direccionEmail, String password) throws NoSuchProviderException, MessagingException { Transport t = (Transport) sesion.getTransport("smtp"); t.connect(propiedades.getProperty("mail.smtp.host"),direccionEmail, password); return t; } private Message crearNucleoMensaje (String emisor, String destinatario, String asunto) throws AddressException, MessagingException { Message mensaje = new MimeMessage(sesion); mensaje.setFrom(new InternetAddress(emisor)); mensaje.addRecipient(Message.RecipientType.TO, new InternetAddress(destinatario)); mensaje.setSubject(asunto); return mensaje; } private Message crearMensajeTexto (String emisor, String destinatario, String asunto, String textoMensaje) throws MessagingException, AddressException, IOException {