JavaMail

JavaMail
Ing. Cesar Julio Bustacara Medina
Proceso de envío de correo
Protocolos
• MIME (Multipurpose Internet Mail
Extensions)
• SMTP (Simple Mail Transfer Protocol)
• POP3 (Post Office Protocol)
• IMAP (Internet Message Access
Protocol – IMAP4)
Clases Fundamentales
•
•
•
•
•
Session
Message / MimeMessage
InternetAddress
Authenticator
Transport
Session
• Representa una sesión de correo
• Usa Properties para obtener los
elementos necesarios como el mail host
– mail.host
– mail.smtp.host
• Usar getInstance() - no constructor
– Session sesion = Session.getInstance(props,
null); // null para el Authenticator
– Session session =
Session.getDefaultInstance(props, null);
Jerarquía de clases de
JavaMail
Message / MimeMessage
• Representa un mensaje de correo
– Message es una clase abstracta
– Implementa la interface Part
– MimeMessage es un MIME para definir el estilo
del mensaje
– Implementa la interface MimePart
• Forma de la constructora
– MimeMessage mensaje = new
MimeMessage(sesion);
• Asignación de partes
– mensaje.setContent() / mimeMessage.setText()
InternetAddress
• RFC822 Address
• Constructoras:
– new InternetAddress(”[email protected]");
– new InternetAddress(”[email protected] ",
”Cesar Bustacara");
• Encabezado (To, From, CC, BCC)
– mensaje.setFrom(address)
– mensaje.addRecipient(tipo, address)
– Tipos
• Message.RecipientType.TO
• Message.RecipientType.CC
• Message.RecipientType.BCC
Authenticator
• Ofrece mecanismos para visualizar la
solicitud de username y password
– javax.mail.Authenticator !=
java.net.Authenticator
• Heredar de Authenticator
• Sobreescribir:
public PasswordAuthentication
getPasswordAuthentication() {
String username, password;
return new PasswordAuthentication(username,
password);
}
Transport
• Mecanismo de transporte de los mensajes
• Se obtiene de la sesión
– Transport transporte =
sesion.getTransport("smtp");
• Conexión
– transporte.connect(host, username, password);
• Envío - repite si es necesario
– transporte.sendMessage(mensaje,
mensaje.getAllRecipients());
• Finalmente
– transporte.close();
Envío de Correo
• Se necesita un servidor SMTP
• Una dirección de origen
• Una dirección de destino.
• No necesariamente validas, a menos
que el servidor SMTP pueda validarlas.
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class EnvioMensajes {
public static void main(String[] args) {
try {
Properties props = new Properties();
// Nombre del host de correo, es smtp.gmail.com
props.setProperty("mail.smtp.host", "smtp.gmail.com");
// TLS si está disponible
props.setProperty("mail.smtp.starttls.enable", "true");
// Puerto de gmail para envio de correos
props.setProperty("mail.smtp.port", "465");
// Nombre del usuario
props.setProperty("mail.smtp.user", "[email protected]");
// Si requiere o no usuario y password para conectarse.
props.setProperty("mail.smtp.auth", "true");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.transport.protocol", "smtps");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.quitwait", "false");
Ejemplo01
//Obtener la instancia de Session.
Session session = Session.getDefaultInstance(props);
Ejemplo01…
//setDebug(true) para obtener más información por pantalla
//de lo que está sucediendo. Una vez que el programa funcione,
//se puede quitar esta línea sin problemas.
session.setDebug(true);
MimeMessage message = new MimeMessage(session);
// Quien envía el correo
message.setFrom(new InternetAddress("[email protected]"));
// A quien va dirigido
message.addRecipient(Message.RecipientType.TO, new InternetAddress("[email protected]"));
message.setSubject("Hola");
message.setText("Mensaje de prueba con Java Mail.");
Transport t = session.getTransport("smtp");
t.connect("[email protected]", "bustacara");
t.sendMessage(message, message.getAllRecipients());
t.close();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
Incluyendo Attachments
• Se crea un objeto de tipo
MimeMultipart
• Cada attachment se asigna a una
MimeBodyPart
• La clase DataHandler permite leer el
contenido del archivo adjunto
– Se necesita un DataSource
• URLDataSource
• FileDataSource
Incluyendo Attachments
// crear un objeto mensaje de tipo mime y asignar los parámetros requeridos
MimeMessage mensaje = createMessage(to, cc, subject);
// crear las partes del mensaje
MimeBodyPart messageBodyPart = new MimeBodyPart();
//Llenar la parte del mensaje
messageBodyPart.setText(msg);
Multipart multipart = new MimeMultipart();
multipart.addBodyPart(messageBodyPart);
// Se llena un arreglo con los archivos a ser adjuntados
File [] attachments = { .... }
Incluyendo Attachments
for( int i = 0; i < attachments.length; i++ ) {
messageBodyPart = new MimeBodyPart();
FileDataSource fileDataSource =new FileDataSource(attachments[i]);
messageBodyPart.setDataHandler(new DataHandler(fileDataSource));
messageBodyPart.setFileName(attachments[i].getName());
multipart.addBodyPart(messageBodyPart);
}
// Se adiciona el objeto Multipart al mensaje
mensaje.setContent(multipart);
// Se envía el mensaje
Transport.send(mensaje);
Ejemplo de datos adjuntos
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
public class EnviarMensajes {
public static void main(String[] arg) {
try {
Properties props = new Properties();
// Nombre del host de correo, es smtp.gmail.com
props.setProperty("mail.smtp.host", "smtp.gmail.com");
// TLS si está disponible
props.setProperty("mail.smtp.starttls.enable", "true");
// Puerto de gmail para envio de correos
props.setProperty("mail.smtp.port", "465");
// Nombre del usuario
props.setProperty("mail.smtp.user", "[email protected]");
// Si requiere o no usuario y password para conectarse.
props.setProperty("mail.smtp.auth", "true");
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.transport.protocol", "smtps");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.quitwait", "false");
//Obtener la instancia de Session.
Session session = Session.getDefaultInstance(props);
//setDebug(true) para obtener más información por pantalla
//de lo que está sucediendo. Una vez que el programa funcione,
//se puede quitar esta línea sin problemas.
session.setDebug(true);
// Construir un mensaje de texto sencillo
MimeMessage message = new MimeMessage(session);
// Quien envia el correo
message.setFrom(new InternetAddress("[email protected]"));
// A quien va dirigido
message.addRecipient(Message.RecipientType.TO,
new InternetAddress("[email protected]"));
message.setSubject("Asunto del mensaje");
//Construir un mensaje complejo con datos adjuntos
//Para un mensaje complejo con adjuntos, por ejemplo,
//un texto con una imagen adjunta, se debe construir cada una
//de las partes y juntarlas todas en un solo mensaje.
//Primero se construye la parte de texto
BodyPart texto = new MimeBodyPart();
texto.setText("Texto del mensaje");
//Luego se construye la parte del adjunto con la imagen.
BodyPart adjunto = new MimeBodyPart();
//Luego se construye la parte del adjunto con la imagen.
adjunto.setDataHandler(new DataHandler(new FileDataSource("d:/futbol.gif")));
// Asignar el nombre del archivo adjunto.
adjunto.setFileName("futbol.gif");
//Ahora juntamos las partes en una sola que luego se debe añadir al mensaje
MimeMultipart multiParte = new MimeMultipart();
multiParte.addBodyPart(texto);
multiParte.addBodyPart(adjunto);
// Asignar el grupo de partes al mensaje
message.setContent(multiParte);
Transport t = session.getTransport("smtp");
// Aqui usuario y password de gmail
t.connect("[email protected]", "bustacara");
t.sendMessage(message, message.getAllRecipients());
t.close();
} catch (MessagingException ex) {
ex.printStackTrace();
}
}
}
Uso de un Authenticator
• Colocar el host en el Properties
Properties props = new Properties();
props.put("mail.host", host);
• Iniciar la autenticación, obtener la sesión
Authenticator auth = new PopupAuthenticator();
Session session = Session.getInstance(props,
auth);
• Obtener el store
Store store = session.getStore("pop3");
store.connect();
Ejemplo Authenticator
public class EnviarMensajes {
String d_email = "[email protected]", d_password = "bustacara",
d_host = "smtp.gmail.com", d_port = "465",
m_to = "[email protected]", m_subject = "Prueba JavaMail",
m_text = "Este es un mensaje de prueba de javaMail.";
public void SSL() {
Properties props = new Properties();
props.put("mail.smtp.host", d_host);
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.port", d_port);
props.put("mail.smtp.user", d_email);
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.socketFactory.class",
"javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.debug", "true");
props.put("mail.smtp.socketFactory.port", d_port);
props.put("mail.transport.protocol", "smtps");
props.put("mail.smtp.socketFactory.fallback", "false");
props.put("mail.smtp.quitwait", "false");
SecurityManager security = System.getSecurityManager();
try {
Authenticator auth = new SMTPAuthenticator();
Session session = Session.getInstance(props, auth);
// session.setDebug(true);
Ejemplo
Authenticator
MimeMessage msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(d_email));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress(m_to));
msg.setText(m_text);
msg.setSubject(m_subject);
Transport.send(msg);
} catch (Exception mex) {
mex.printStackTrace();
}
}
public static void main(String[] args) {
EnviarMensajes blah = new EnviarMensajes();
blah.SSL();
}
private class SMTPAuthenticator extends javax.mail.Authenticator {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(d_email, d_password);
}
}
Lectura de Correo usando
POP3
• POP3 no provee un almacenamiento
local.
• Se necesita un servidor SMTP
• Una dirección de origen
• Un protocolo de acceso a los mensajes
(POP3 o IMAP).
Ejemplo lectura de Correo
(POP3)
public class LeerMensajes {
public static void main(String arg[]){
try {
Properties props = new Properties();
// Deshabilitar TLS
props.setProperty("mail.pop3.starttls.enable", "false");
// Hay que usar SSL
props.setProperty("mail.pop3.socketFactory.class","javax.net.ssl.SSLSocketFactory"
);
props.setProperty("mail.pop3.socketFactory.fallback", "false");
// Puerto 995 para conectarse.
props.setProperty("mail.pop3.port","995");
props.setProperty("mail.pop3.socketFactory.port", "995");
// crear la sesion y obtener un log de salida más extenso
Session session = Session.getInstance(props);
session.setDebug(true);
Store store = session.getStore("pop3");
store.connect("pop.gmail.com", "[email protected]", "bustacara");
// abrir el folder
Folder folder = store.getFolder("INBOX");
if (folder == null) {
System.out.println("No INBOX");
System.exit(1);
}
folder.open(Folder.READ_ONLY);
// Obtener la lista de mensajes del servidor
Message[] mensajes = folder.getMessages();
for (int i = 0; i < mensajes.length; i++) {
System.out.println("------------ Mensaje " + (i+1) + " ------------");
mensajes[i].writeTo(System.out);
}
// Cerrar las conexiones
folder.close(false);
store.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (MessagingException ex) {
ex.printStackTrace();
}
}
}
Ejemplo
Lectura
Partes de un mensaje de
correo
Partes del mensaje
public static void printMessage(Message m) throws Exception {
// Imprimir el encabezado(Header)
Address[] from = m.getFrom();
if (from != null) {
for (int i = 0; i < from.length; i++) {
System.out.println("From: " + from[i]);
}
}
Address[] to = m.getRecipients(Message.RecipientType.TO);
if (to != null) {
for (int i = 0; i < to.length; i++) {
System.out.println("To: " + to[i]);
}
}
String subject = m.getSubject();
if (subject != null) {
System.out.println("Subject: " + subject);
}
Date d = m.getSentDate();
if (d != null) {
System.out.println("Date: " + d);
}
Partes del mensaje
// Imprimir una linea en blanco para separar el Encabezado del
Cuerpo
System.out.println();
// Imprimir el cuerpo del mensaje
Object content = m.getContent();
if (content instanceof String) {
System.out.println(content);
}
else if (content instanceof InputStream) {
InputStream in = (InputStream) content;
int c;
while ((c = in.read()) != -1) System.out.write(c);
}
else {
// El mensaje puede contener multi-part MIME.
System.out.println(”Tipo de contenido NO reconocido");
}
}
Responder Mensajes
• Usar Message.reply(boolean)
– Asignar al mensaje los headers
adecuados
– boolean responder a todos
– true responder al Sender únicamente
– No es necesario asignar contenido al
mensaje
Borrado de Mensajes
• Colocar el flag del mensaje para borrar:
– mensaje.setFlag(Flags.Flag.DELETED, true);
• Abrir el folder en modo lectura-escritura:
– folder.open(Folder.READ_WRITE);
• Borrar cuando el folder se cierre:
– folder.close(true); // true = eliminar
Referencia útil
• http://java.sun.com/blueprints/guidelin
es/designing_enterprise_applications_
2e/glossary.html