Java Mail
Java Mail
El API
JavaMail
Java Mail i
Tabla de Contenidos
ii Java Mail
Índice de figuras
Figura 1: Servidor de e-mails y su cliente. Página 1
El API JavaMail es un paquete opcional para leer, componer y enviar mensajes electrónicos. Se
usa este paquete para crear programas similares a Eudora y Microsoft Outlook, por
ejemplo. Su propósito principal es leer y escribir e-mails e interaccionar con los
programas que se encargan del envío de estos mensajes usando el lenguaje de
programación Java.
JavaMail está formada por un conjunto de clases abstractas que modelan las partes de un
sistema de correo electrónico. Estas clases son:
- session: define una sesión de correo básica.
- message: representa un mensaje de correo electrónico.
- address: indica la dirección a la que se va a enviar el mensaje
- authenticator: se utiliza para proteger accesos a recursos mediante un nombre de
usuario y una contraseña
- transport: representa un protocolo de transporte específico
- store: representa una base de datos de mensajes que es mantenida por un servidor de
correos electrónicos y agrupada por el usuario.
- folder: proporciona un método para recuperar los mensajes.
Los sistemas de correo electrónico están formados por dos componentes principales: un
cliente de correo, o agente del usuario (UA) y un servidor de correo, o agente de
transferencia de mensajes (MTA).
-1-
El API JavaMail
Los agentes de usuario permiten a los usuarios redactar y enviar mensajes de correo
electrónico y recuperarlos de los agentes de transferencia de mensajes. Ejemplos de agentes de
usuario son, por ejemplo Eudora y Outlook.
Los agentes de transferencia de mensajes son los que almacenan y reenvían el correo
electrónico de los agentes de usuario y admiten el intercambio de correo por una red o grupo de
redes, como por ejemplo los programas que actúan de servidor de correo electrónico como
Sendmail y Exchange.
Para que los agentes de usuarios se puedan comunicar con los agentes de
transferencia de mensajes son necesarios una serie de protocolos, que se describen
brevemente en el siguiente punto.
Los protocolos que se utilizan con el API JavaMail son básicamente cuatro: SMTP, POP, IMAP
y MIME, aunque también se utiliza, por ejemplo, NNTP.
· SMTP
El protocolo Simple Mail Transfer Protocol (SMTP) define el mecanismo para enviar e-
mail. En el contexto del API JavaMail, un programa basado en JavaMail comunicará con
el servidor SMTP del proveedor de servicios que dejará el mensaje en el servidor SMTP
del receptor para que sea recogido por los usuarios.
· POP
-2-
A. Rodríguez y R. Rodríguez
· IMAP
IMAP (Internet Message Access Protocol) es un protocolo más avanzado para recibir
mensajes y está actualmente en la versión 4. Para usar el IMAP, el servidor de correo
debe soportar este protocolo. Si el servidor de correo soporta IMAP, el programa basado
en JavaMail puede aprovecharse de los usuarios que tienen carpetas múltiples en el
servidor y estas carpetas se pueden compartir por varios usuarios
· MIME
· NNTP
2.1 session
La clase session define una sesión de correo básica. El objeto session utiliza un objeto
java.util.Properties para obtener información, como el servidor de correo, el nombre de
usuario, la contraseña, y otra información que puede compartirse a lo largo de toda la
aplicación.
El constructor para la clase session es privado. Es posible obtener una sola sesión por
defecto que puede ser compartida con el método getDefaultInstance():
-3-
El API JavaMail
En la mayoría de los casos, es suficiente usar la sesión compartida, incluso si se trabaja con
una sesión de correo para múltiples buzones de usuario. Se podrá añadir una combinación de
nombre de usuario y contraseña en un paso posterior en el proceso de comunicación.
2.2 message
Una vez que se tiene el objeto session, se puede crear un mensaje para enviar. Esto puede
hacerse con un objeto message.
-4-
A. Rodríguez y R. Rodríguez
- Mensajes Multipart: son los mensajes que contienen varios objetos que representan el
contenido. El objeto DataHandler va a contener un objeto Multipart, que a su vez,
contiene objetos BodyPart. La estructura de un objeto BodyPart es similar a la de
un objeto simple ya que ambos implementan la parte que se corresponde con la interfaz
del mensajes:
- Si se tiene una aplicación y el proveedor permite trabajar con mensajes que soportan el
estilo MIME, cosa que es bastante frecuente se puede implementar un mensaje con la
clase: javax.mail.internet.MimeMessage.
-5-
El API JavaMail
message.setContent("Hello", "text/plain");
2.3 address
Una vez que se ha definido una sesión y se ha creado un mensaje con contenido, hay que poner
dirección al e-mail con un objeto address de la clase:
javax.mail.internet.InternetAddress.
Para crear una dirección con sólo la dirección e-mail, se le pasa al constructor:
Address address = new InternetAddress("[email protected] ");
Es necesario crear objetos address para los campos from y to del mensaje. Una vez que
se han definido las direcciones, se conectan al mensaje de una de estas dos formas.
-6-
A. Rodríguez y R. Rodríguez
2.4 authenticator
Para usar el authenticator se debe registrar con la sesión cuando se crea. Luego, el
authenticator será notificado cuando sea necesaria una autentificación. En ese momento, se
mostrará una ventana o se leerá el nombre del usuario y su contraseña de un fichero (si no está
encriptado no es seguro). Finalmente, se devuelve un objeto PasswordAuthentication del
método getPasswordAuthentication() al llamador.
Properties props = new Properties();
// rellenar props con la información necesaria.
Authenticator auth = new MyAuthenticator();
Session session = Session.getDefaultInstance(props, auth);
2.5 transport
La parte final del envío de un mensaje es usar la clase transport. Esta clase establece el
lenguaje específico del protocolo para enviar mensajes.
Se puede usar la versión por defecto de la clase sólo llamando al método estático send():
Transport.send(message);
Otra opción es obtener un ejemplar específico desde la sesión para el protocolo, pasándole
el nombre de usuario y la contraseña (en blanco si no son necesarias), enviar el mensaje, y
cerrar la conexión:
message.saveChanges();
Transport transport = session.getTransport("smtp");
transport.connect(host, username, password);
transport.sendMessage(message, message.getAllRecipients());
transport.close();
Esta última forma es mejor cuando es necesario enviar varios mensajes, porque mantendrá
activa la conexión entre mensajes. El mecanismo básico send() hace una conexión separada al
servidor para cada llamada a método.
-7-
El API JavaMail
2.6 store
La clase store modela una base de datos de mensajes y su protocolo de acceso para obtener
estos mensajes. Después de obtener la sesión, se conecta a una clase store, probablemente
con un nombre de usuario y una contraseña y se le indica qué protocolo utilizar:
2.7 folder
Después de conectar al store, se debe obtener un folder, que debe estar abierto antes de
poder leer los mensajes que hay en su interior:
Una vez que se recuperan los mensajes, se puede obtener sus contenidos con
getContent() o escribirlos en una cadena con writeTo() cuya salida también incluye las
cabeceras.
System.out.println(((MimeMessage)message).getContent());
Enviar un mensaje de e-mail implica obtener una sesión, crear y rellenar un mensaje y enviarlo.
Se puede especificar el servidor SMTP configurando la propiedad mail.smtp.host del
objeto Properties cuando se obtiene la sesión:
-8-
A. Rodríguez y R. Rodríguez
Para leer mensajes, se debe obtener una sesión, conectarse con el store apropiado para el
buzón, abrir la carpeta apropiada, y obtener los mensajes. No se debe olvidar cerrar la conexión
cuando se haya terminado.
String host = ...;
String username = ...;
String password = ...;
Properties props = new Properties();
// se obtiene la sesión
Session session = Session.getDefaultInstance(props, null);
// conexión con el buzón en el que se almacenan los mensajes
Store store = session.getStore("pop3");
store.connect(host, username, password);
// se indica la carpeta en la que se van a almacenar los mensajes
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
// se obtienen los mensajes
Message message[] = folder.getMessages();
for (int i=0, n=message.length; i<n; i++)
{
System.out.println(i + ": " + message[i].getFrom()[0]
+ "\t" + message[i].getSubject());
-9-
El API JavaMail
}
// se cierra la conexión
folder.close(false);
store.close();
El bloque de código anterior sólo muestra de quién viene el mensaje y el asunto. Para
mostrar el mensaje completo, se le preguntará al usuario si quiere verlo después de haya visto
los campos anteriores.
3.3 Reenvío
No existe una llamada para reenviar un mensaje, sino que se va a construir el mensaje a reenviar
trabajando con cada una de las partes que componen un mensaje.
Un mensaje puede estar compuesto por varias partes. Cada una de ellas es un BodyPart.
Las distintas partes del cuerpo de un mensaje se combinan en un objeto Multipart. Para
reenviar un mensaje, se crea una parte para el texto de un mensaje y una segunda parte para el
mensaje a reenviar. Ambas partes se combinan en un objeto Multipart. Para terminar se
añade el objeto al mensaje creado para reenviar, se le pone una dirección y se envía como si se
tratara de un mensaje normal.
- 10 -
A. Rodríguez y R. Rodríguez
forward.setFrom(new InternetAddress(from));
forward.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
// Se crea la parte del mensaje correspondiente al texto
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(
"Te reenvío el mensaje original:\n\n");
// Se crea un objeto Multipart
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
// Se crea la parte en la que se incluirá el mensaje inicial
messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(message.getDataHandler());
// Se añade esta parte al objeto Multipart
multipart.addBodyPart(messageBodyPart);
// Finalmente se asocia el objeto Multipart con el mensaje
forward.setContent(multipart);
// Y se envía.
Transport.send(forward);
Borrar mensajes implica trabajar con las banderas asociadas con los mensajes. Para borrar
mensajes se deben seguir los siguientes pasos:
- Primero se debe abrir la carpeta en modo READ_WRITE:
folder.open(Folder.READ_WRITE);
- Después se selecciona la bandera DELETED del mensaje:
message.setFlag(Flags.Flag.DELETED, true);
- Luego, cuando se haya procesado todos los mensajes, se cierras la carpeta, pasando un valor
true para purgar todos los mensajes borrados:
folder.close(true);
Los archivos adjuntos son ficheros asociados a un mensaje de correo electrónico que
normalmente son mantenidos fuera del mensaje. JavaMail permite adjuntar recursos a los
mensajes y enviarlos.
Para enviar un mensaje que tenga un archivo adjunto se construye un mensaje completo,
con la dirección, y el contenido, que será un objeto Multipart. A continuación se añade una
- 11 -
El API JavaMail
parte para el texto del mensaje, que estará contenida en un objeto BodyPart y finalmente se crea
otra parte en la que el DataHandler para dicha parte será el archivo adjunto.
Para terminar hay que darle un nombre a este archivo que se ha adjuntado con la función
setFileName
- 12 -
A. Rodríguez y R. Rodríguez
{
Part part = multipart.getBodyPart(i));
- 13 -
El API JavaMail
Ejemplo: expresión lógica que busca los mensajes que bien hayan sido enviados por la dirección
de correo [email protected] o bien que contengan la palabra “búsqueda” en el asunto
del mensaje
SearchTerm st = new OrTerm(new SubjectTerm("búsqueda"),
new FromStringTerm("[email protected]"));
Message[] msgs = folder.search(st);
El programa comienza estableciendo la dirección del host a la variable mailHost. Una vez
que éste queda identificado, se crearán los componentes que forman la GUI (Interfaz Gráfica de
Usuario) en la función IniciarComponentes.
Finalmente la clase ButtonHandler maneja los eventos que están asociados con la
interfaz del programa.
import java.atw.*;
import java.atw.event.*;
import java.util.*;
import java.mail.*;
import java.mail.event.*;
import java.mail.internet.*;
public class ClienteDeCorreo extends Frame
{
String mailHost = “javamail.com”;
Label etiqPara = new Label (“Para: “);
Label etiqDe = new Label (“De: “);
Label etiqAsunto = new Label (“Asunto: “);
Label etiqConten = new Label (“Contenido: “);
TextField destino = new TextField ();
TextField origen = new TextField ();
- 14 -
A. Rodríguez y R. Rodríguez
- 15 -
El API JavaMail
add(etiqConten);
add(conten);
}
void sendMessage()
{
Properties props = new Properties();
props.put(“mail.smtp.host”, mailHost);
props.put(“mail.from”, erogen.getText());
Session session = Session.getInstance(props, null);
try
{
Message mens = new MimeMessage(sesion);
InternetAddress[] dir =
new InternetAddress(destino.getText());
mens.setRecipients(Message.RecipientType.TO, dir);
mens.setFrom(new IntenetAddress (origen.getText()));
mens.setSubject(subject.getText());
mens.setContent(content.getText(), “text/plain”);
Transport tr = sesion.getTransport(dir[0]);
tr.connect();
tr.sendMessage(mens,dir);
}
}
class ButtonHandler implements ActionListener
{
public void actionPerformed(ActionEvent ev)
{
String s = ev.getActionCommand();
if (s.equals(“Send Message”))
sendMessage();
}
}
}
4. Conclusiones
El API JavaMail ofrece una plataforma independiente para poder construir aplicaciones Java
basadas en el correo electrónico, ya sea para crear programas clientes de correo electrónico o
para permitir correo en programas como editores o navegadores.
- 16 -
A. Rodríguez y R. Rodríguez
5. Referencias bibliográficas
- “Java 1.2 al descubierto” de Jamie Jaworski, editorial Prentice Hall-Sams.
- Tutorial de Sun sobre JavaMail: http://java.sun.com/products/javamail
- Tutorial de Programación de JavaMail: http://programacion.com/java/tutorial/javamail
- 17 -