JavaMail è un API che con l'aiuto di JavaBeans Activation Framework (JAF) permette l'accesso all'ormai famoso servizio per la posta elettronica. Si tratta di un package opzionale che, sfruttando i servizi di rete offerti dai livelli sottostanti, consente di inviare e ricevere l'email. L'obiettivo principale di JavaMail è la realizzazione di un accesso al servizio indipendente dai protocolli sottostanti, realizza cioè un'interfaccia al servizio.
Nella prima parte di questo articolo ci occuperemo di richiamare le funzioni dei protocolli di rete usati per il servizio della posta elettronica, quindi passeremo a una breve presentazione delle classi che compongono il package. Al termine di questa prima parte sarà quindi possibile usare il package per scrivere semplici programmi.
Nella seconda parte vedremo un uso più avanzato della libreria.
E' giunto il momento di rivedere i principali protocolli di rete usati da JavaMail: SMTP, POP ed IMAP. Ciò non può che essere di aiuto per la comprensione di tutto quello che faremo a breve con l'API. E' opportuno ricordare che ogni protocollo di rete è stato ideato per precisi scopi ed implementa di conseguenza le dovute funzionalità. Pertanto, se una funzione non viene in alcun modo realizzata presso i protocolli di rete è inutile chiedere a JavaMail di fare il miracolo!
SMTP
Il protocollo SMTP (Simple Mail Transfer Protocol) definito nell'RFC 821 si preoccupa della consegna, quindi dell'invio, dei messaggi. Quando inviamo un messaggio di posta elettronica il nostro client dialoga con il server SMTP del provider.
POP
Il protocollo POP (Post Office Protocol) definito nell'RFC 1939 permette la lettura dei propri messaggi di posta elettronica. Se vogliamo prelevare la nostra posta elettronica dobbiamo necessariamente dialogare con un server POP (attualmente giunto alla versione POP3).
IMAP
Il protocollo IMAP (Internet Message Access Protocol) definito nell'RFC 2060 permette la ricezione della posta elettronica. IMAP è più evoluto di POP3, anche se aggiunge più lavoro al server!
MIME
MIME non è un vero e proprio protocollo di rete, l'acronimo sta per Multipurpose Internet Mail Extensions. Viene usato da JavaMail e non potevo non menzionarlo! Esso definisce la struttura dei messaggi, i contenuti, gli allegati, etc...
Le classi dell'API
Prima
ancora di vedere un programma completo ho preferito descrivere
sommariamente le principali classi che compongono l'API, queste sono: Session, Message, Address,
 Authenticator, Transport, Store e Folder. Tutte nel package javax.mail.

Session
La classe Session descrive una sessione utile all'invio o ricezione di messaggi di posta elettronica. La nostra applicazione che fa uso di JavaMail dovrà sempre istanziare un oggetto Session e caratterizzarne le proprietà. Le informazioni che caratterizzano un oggetto Session vengono passate attraverso l'oggetto Properties, della classe java.util. Poiché i costruttori della classe sono privati è possibile ottenere un oggetto Session mediante il metodo getDefaultInstance():
Properties props=new Properties();
Session session=Session.getDefaultInstance(props, null);
Il valore null passato al metodo va a un eventuale oggetto Authenticator che per adesso non usiamo. Un utile metodo di questa classe è il metodo setDebug(boolean debug) che permette di vedere o meno la sequenza di comandi scambiata con il server. Per caratterizzare una sessione occorre prima definire i valori di nuove proprietà, ad esempio con:
String host = "smtp.tiscali.it";
props.put("mail.smtp.host",host);
impostiamo il server SMTP da contattare. Il metodo setProperty(String key, String value) imposta il valore value alla chiave key. Ecco un elenco di alcuni dei dei possibili valori di key:
  • mail.debug: può essere true oppure false (valore di default) e abilita la modalità di debugging;
  • mail.user: una stringa con il nome utente da usare quando l'API contatta il server per la posta elettronica;
  • mail.from: una stringa con l'indirizzo dell'utente (che può essere aggiunto al messaggio con il metodo setFrom());
  • mail.smtp.host: una stringa con l'indirizzo del server SMTP;
Qui trovate una lista completa di valori. Se impostiamo una o più proprietà va poi chiamato il metodo getInstance(Property props) per costruire un oggetto Session con quelle caratteristiche!
Message
Con la classe Message descriviamo il messaggio da inviare (contiene il testo dell'email). Siccome Message è una classe astratta nei programmi si avrà a che fare con una delle sue sottoclassi. Una di queste è la classe MimeMessage, definita in javax.mail.internet. Come avete ben capito la classe MimeMessage rispetta lo standard descritto dal protocollo MIME. Per creare un oggetto Message, a partire da un oggetto Session, si ha queste sequenza di istruzioni:
MimeMessage message=new MimeMessage(session);
message.setContent("Hello world!","text/plain");
dove con il metodo setContent(Object o, String type) ho impostato il contenuto e l'attributo MIME. E' possibile indicare anche solo il contenuto in questo modo:
MimeMessage message=new MimeMessage(session);
message.setContent("Hello world!");
Per specificare il campo subject dell'email esiste il metodo setSubject(String subject):
message.setSubject("An "Hello world!" e-mail!");
Altri metodi della classe MimeMessage si trovano in questa pagina.
Address
Con la classe Address possiamo costruire oggetti capaci di descrivere un indirizzo di posta elettronica. Anche la classe Address, così come Message, è una classe astratta. Gli oggetti Address vengono allora costruiti attraverso una delle sue sottoclassi, come la classe InternetAddress in javax.mail.internet.
Address fromAddress=new InternetAddres("writer@domain.site");
Address toAddress=new InternetAddres("user@domain.site");
Se vogliamo far apparire un nome al posto dell'indirizzo (che va sempre indicato) possiamo allora usare una variante del metodo visto prima:
Address fromAddress=new InternetAddres("writer@domain.site","Luca");
L'aggiunta di questi oggetti al messaggio avviene con i metodi setFrom(), che imposta l'header From del messaggio, e addRecipients(Message.RecipientType type, Address[] addresses), che imposta invece l'header To. Quest'ultimo metodo permette l'invio multiplo del messaggio a più utenti. Possiamo costruire un array di indirizzi e passare la struttura al metodo! Possibili valori di type sono: Message.RecipientType.TO, Message.RecipientTypeCCcopia carbone del messaggio) e Message.RecipientType.BCC (indirizzo nascosto a cui inviare una copia del messaggio). Ecco un esempio:
Address toAddress=new InternetAddress("mrRed@color.rgb");
Address ccAddress=new InternetAddress("msRed@color.rgb");
message.addRecipient(Message.RecipientType.TO, toAddress);
message.addRecipient(Message.RecipientTypeCC, ccAddress);
Attenzione, l'API non prevede alcun meccanismo per convalidare un indirizzo di posta elettronica! Si potrebbe costruire qualcosa usando le espressioni regolari.
Authenticator
La classe Authenticator permette l'accesso a servizi protetti da password e che richiedono quindi una forma di autenticazione. Attenzione, la classe Authenticator di java.net è diversa da quella in javax.mail (pur avendo lo stesso nome, proprio per questo si trovano in package differenti!). Se un servizio di posta elettronica richiede il riconoscimento dell'utente è importante, allora, implementare il metodo getPasswordAuthentication(), che crea un oggetto PasswordAuthentication contenente il nome dell'utente e la sua password per accedere al servizio.
Authenticator authenticator = new Authenticator();
Session sessione = new Session.getdefaultInstance(properties,authenticator);
Transport
La classe Transport rende possibile l'invio del messaggio fin qui costruito. Il metodo che permette di inviare il messaggio è:
Transport.sendMessage(messagge);
Viene usato di default il protocollo SMTP. Attenzione, il metodo lancia un eccezione di tipo MessagingException. Se voglio invece caratterizzare l'invio del messaggio disponiamo poi di altri metodi.
Store e Folder
La classe Store si preoccupa della ricezione dei messaggi di posta elettronica, realizzando la connessione al server. I messaggi vengono poi organizzati all'interno di cartelle, modellate con oggetti della classe Folder.
Esempio: inviare un e-mail
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

public class Invio {
   public static void main(String[] args) {
      String to="user@domain.site";
      String from="writer@domain.site";
      String host="smtp.server.site";
      Properties props = new Properties();
      props.put("mail.smtp.host",host);
      props.put("mail.debug","true");
      Session session=Session.getInstance(props);
      try {
         Message msg=new MimeMessage(session);
         msg.setFrom(new InternetAddress(from));
         InternetAddress[] address ={new InternetAddress(to)};
         msg.setRecipients(Message.RecipientType.TO, address);
         msg.setSubject("An "Hello World e-mail"!");
         msg.setSentDate(new Date());
         msg.setText("Hello world!");
         Transport.send(msg);
      }
      catch (MessagingException mex) {
         mex.printStackTrace();
      }
   }
}