Está en la página 1de 7

JavaMail (parte 2): enviando mails de texto

Fecha de creación: 01.12.2002

Revisión 1.0 (17.1.2003)

Alberto Molpeceres (al AT javahispano DOT org)

http://www.javaHispano.org

Copyright (c) 2002, Alberto Molpeceres. Este documento puede ser distribuido solo bajo los
términos y condiciones de la licencia de Documentación de javaHispano v1.0 o posterior (la última
versión se encuentra en http://www.javahispano.org/licencias/).
JavaMail (parte 2): enviando mails de texto

JavaMail (parte 2): enviando mails de texto


En el artículo anterior [1] explicamos como recoger nuestros mails (de texto)
por medio del API JavaMail, explicando también los preparativos necesarios
para usar este API, así que si no lo habeis leido os lo recomiendo, varias de las
cosas comentadas allí os serán necesarias.
En este artículo veremos como enviar mails de texto por medio del protocolo
SMTP (Simple Mail Transport Protocol), sin duda el protocolo más usado, y
seguiremos creando nuestras clases que nos faciliten el uso de JavaMail.

Un envoltorio para la sesión: SMTPSession


Al igual que hicimos al recoger el correo con POP, crearemos una clase sencilla que
represente una session con un servidor de correo SMTP, cuyos métodos iremos creando
a lo largo del artículo. Se esqueleto, más o menos autoexplicativo podría ser así:

package org.javahispano.mailer;
import javax.mail.internet.*;
import javax.mail.*;
import java.util.*;
import javax.activation.*;
public class SMTPSession {
private String host;
private String user;
private String password;
private int port = 25;
private boolean debug = false;
private static int DEFAULT_PORT = 25;
public SMTPSession(String host) {
this(host, DEFAULT_PORT , null, null);
}
public SMTPSession(String host, String user, String password) {
this(host, DEFAULT_PORT, user, password);
}
public SMTPSession(String host, int port, String user, String
password) {
this.host = host;
this.user = user;
this.password = password;
this.port = port;
}
public void setDebug(boolean value) {
debug = value;
}
}

Un mail
Página 2
JavaMail (parte 2): enviando mails de texto

Ya que un mail se compone de diversas partes (remitente, distintos tipos de receptores,


texto, archivos adjuntos, aunque estos últimos no los veremeos en este artículo),
tendremos que crear también una clase que represente a un mail (sigo insistiendo que en
este artículo sólo serán de texto, dejaremos los mensajes HTML, con attachments, o
MIME, para el siguiente) que aún no se ha enviado. Algo así como esta:

package org.javahispano.mailer;
import java.util.*;
import java.io.File;
import javax.mail.internet.*;
public class SMTPMail {
protected Map toAddresses = new HashMap();
protected Map ccAddresses = new HashMap();
protected Map bccAddresses = new HashMap();
protected Map replyToAddresses = new HashMap();
protected String fromName = null;
protected String fromAddress = null;
protected String subject = null;
protected String messageText = new String();
protected SMTPMail(String fromName, String fromAddress, String
subject) {
this.fromName = fromName;
this.fromAddress = fromAddress;
this.subject = subject;
}
public void setMessageText(String messageText) {
this.messageText = messageText;
}
public void addToAddress(String name, String address) {
toAddresses.put(name, address);
}
public void addCcAddress(String name, String address) {
ccAddresses.put(name, address);
}
public void addBccAddress(String name, String address) {
bccAddresses.put(name, address);
}
public void addReplyToAddress(String name, String address) {
replyToAddresses.put(name, address);
}
}

A esta clase le faltan varios métodos que nos harán hacer falta, como por ejemplo para
recuperar el asunto del mail o las direcciones de los destinatarios, pero en todo caso eso
no es del todo necesario para nuestro ejemplo (supongo que os los podeis imaginar) y
haría el mismo demasiado largo. Estos métodos os harían falta, por ejemplo, si quereis
almacenar de alguna forma estos mails antes de enviarlos (algo así como el Enviar
después de muchos clientes de correo) para su posterior envio o registro.
En general el uso de esta clase es bastante sencillo, hay los atributos clásicos
(remitente, dirección del remitente y asunto del mail) que se recogen con el contructor, el
texto del mensaje que se ajusta por medi ode un método (setMessageText), y diferentes

Página 3
JavaMail (parte 2): enviando mails de texto

Map para almacenar las distintas dirección de los destinatarios (para To, copia CC y copia
ciega u oculta BCC) y de las respuestas (ReplyTo).

Enviar mensajes
Ahora añadiremos un método a nuestra clase SMTPSession que será el que se encargue
de enviar nuestro mensaje. Como he dicho, no prentendo hacer un cliente de correo
completo, así que se enviará el mensaje inmediatamente, no esta implementada (aún) la
opción de almacenar varios mensajes y enviarlos conjuntamente.

public void sendMail(SMTPMail mail)


throws Exception {
// creamos algunas de las propiedades y la sesión real en si misma
Properties props = new Properties();
props.put("mail.smtp.host", host);
Session session = Session.getDefaultInstance(props, null);
session.setDebug(debug);
//creamos un mensaje de JavaMail real!
MimeMessage message = new MimeMessage(session);
//rellenamos ese mail real con los datos de nuestra clase auxiliar
this.prepareMessage(message, mail);
//finalmente nos conectamos y enviamos el mail
Transport transport = session.getTransport("smtp");
if (user != null && password != null) {
transport.connect(host, user, password);
}
else {
transport.connect();
}
transport.send(message);
transport.close();
}

Este este código aparecen algunas clases del API JavaMail nuevas, Session,
MimeMessage y Transport. Session es bastante sencilla de entender, el contexto donde se
realizan todas las tareas de una conexión, y Transport es la conexión real al servidor, con
los métodos típicos de conexión, envio y cierre de la conexión.
MimeMessage es también sencillo, es la representación que utiliza JavaMail para los
mensaje electrónicos. Como podeis ver, se trata de MIME, por lo que usaremos esa clase
también en artículos posteriores para enviar HTML con imagenes y/o archivos adjuntos.

Direcciones de internet
Como habreís visto, en el método sendMail utilizamos otro método prepareMessage que
se encarga de convertir nuestra representación partículas de los mensajes a la adecuada
para JavaMail. Su código es el siguiente:

private MimeMessage prepareMessage(MimeMessage message, SMTPMail


mail)
throws Exception {
// ajustamos las iferentes propiedades del mensaje
message.setFrom(mail.getFrom());

Página 4
JavaMail (parte 2): enviando mails de texto

message.setSubject(mail.getSubject());
message.setSentDate(new java.util.Date());
message.setText(mail.getMessageText());
//ahora las distintas direcciones
InternetAddress[] addresses = mail.getReplyToAddresses();
if (addresses != null) {
message.setReplyTo(addresses);
}
addresses = mail.getToAddresses();
if (addresses != null) {
message.setRecipients(Message.RecipientType.TO, addresses);
}
addresses = mail.getCcAddresses();
if (addresses != null) {
message.setRecipients(Message.RecipientType.CC, addresses);
}
addresses = mail.getBccAddresses();
if (addresses != null) {
message.setRecipients(Message.RecipientType.BCC, addresses);
}
//almacenamos estos cambios en el mesnaje y listos
message.saveChanges();
return message;
}

Como podemos ver, este método recupera las direcciones de email de los destinatarios
en forma de array de InternetAddress, pero nosotros las habiamos añadido en forma de
parejas de String representando nombre y dirección de correo electrónico del
destinatario.
Estas InternetAddress son la implementación Java de las direcciones de correo
electrónico en internet tal y como marca el RFC822. De esta forma necesitaremos un
método dentro de nuestra clase envoltorio SMTPMail para convertir las dirección de parejas
de String a InternetAddress.

private InternetAddress[] getAddresses(HashMap addresses)


throws Exception {
InternetAddress address = null;
ArrayList list = new ArrayList();
String name = null;
String email = null;
Iterator i = addresses.keySet().iterator();
while (i.hasNext()) {
name = (String) i.next();
email = (String) addresses.get(name);
try {
list.add(new InternetAddress(email, name));
}
catch (Exception ex) {
System.out.println("Dirección de correo inválida: " + email);
}
}
if (list.isEmpty()) {
return null;
}
InternetAddress all[] = new InternetAddress[list.size()];
all = (InternetAddress[]) list.toArray(all);
return all;
Página 5
JavaMail (parte 2): enviando mails de texto

Por supuesto podríamos haber optado por convertirlas al añadirlas pero he optado por
hacerlo así simplemente por no incluir todos los conceptos a la vez. Además, JavaMail
realiza comprobaciones sobre las existencia de los servidores destinatarios, por lo que es
mejor hacerlas todas a la vez que una a una, sobre todo si no tenemos conexión
permanente a internet.

Probando.
Ahora simplemente crearemos una clase de prueba que envie un sencillo email de texto
para ver si todo funciona.

package org.javahispano.mailer.test;
import org.javahispano.mailer.*;
public class SendMailTest {
public static void main(String[] args) {
SMTPSession smtp = new SMTPSession("serviodor.com", "usuario",
"password");
// smtp.setDebug(true);
SMTPMail mail = new SMTPMail("yo", "yo@servidor.com", "Mail de
prueba");
mail.addToAddress("Tu", "tu@servidor.com");
mail.setMessage("Mailer test. \r\n Simple ASCII text");
mail.setMessage(text);
try {
smtp.sendMail(mail);
System.out.println("Mail enviado con exito");
}
catch (Exception e) {
System.out.println("No se puedo enviar el mail: " +
e.getMessage());
e.printStackTrace();
}
}
}

Perfecto, ¿no?.

El código.
Por supuesto tenéis disponible el código de este artículo para su descarga [2].

Conclusión
En estos dos primeros artículos hemos mostrado lo fácil que puede resultar usar
JavaMail, e incluso hacer una pequenya libreria que nos facilite su reutilización siempre
que lo necesitemos.
Hasta ahora nos hemos dedicado a los mensajes de texto, pero todos sabemos que no
siempre es así, y que en muchos casos nos interesa leer/enviar mensajes que contengan
HTML o archivos adjuntos. Esos artículos llegarán, espero (todo depende del tiempo), asi

Página 6
JavaMail (parte 2): enviando mails de texto

que si alguno de vosotros esta interesado en tomar el relevoque me lo haga saber

Recursos y referencias
[1] JavaMail (parte 1): recuperando mails con POP,
http://www.javahispano.org/articulos/ver_articulo.jsp?id=69
[2] Código del artículo, /download/articulos/javamail2_src.zipCódigo del artículo

Acerca del autor


Alberto es ahora mismo desarrollador de aplicaciones en ámbito cliente/servidor para la
empresa T-Systems International GmbH en Dresden (Alemania). Cuando no está
trabajando o "metiendo caña" al resto de los integrantes de javaHispano intenta pasear
con su novia, buscar la desaparecida lógica del idioma alemán o intenta disfrutar del buen
ambiente de la Neustadt.

Copyright (c) 2002, Alberto Molpeceres. Este documento puede ser distribuido solo bajo los
términos y condiciones de la licencia de Documentación de javaHispano v1.0 o posterior (la última
versión se encuentra en http://www.javahispano.org/licencias/).

Página 7