Introduccrión a JavaMail (parte 2)
sábado, febrero 1, 2003 at 1:00AM 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
|
Introducción
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.
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;
}
}
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 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).
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.
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());
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;
}
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.
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?.
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 que si alguno de vosotros esta interesado en tomar el relevoque me lo haga saber
Recursos
[1] JavaMail (parte 1): recuperando mails con POP,
/articulos/ver_articulo.jsp?id=69
Acerca del autor
Alberto Molpeceres
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.
j2ee 
Reader Comments