Esempio di JavaMail – Invio di Email in Java Usando SMTP

Oggi esamineremo un esempio di JavaMail per inviare email nei programmi Java. L’invio di email è una delle attività comuni nelle applicazioni della vita reale ed è per questo che Java fornisce una robusta API JavaMail che possiamo utilizzare per inviare email tramite il server SMTP. L’API JavaMail supporta sia l’autenticazione TLS che SSL per l’invio di email.

Esempio di JavaMail

Oggi impareremo come utilizzare l’API JavaMail per inviare email tramite il server SMTP senza autenticazione, con autenticazione TLS e SSL e come inviare allegati e allegare e utilizzare immagini nel corpo dell’email. Per l’autenticazione TLS e SSL, sto utilizzando il server SMTP di GMail perché supporta entrambi. Puoi anche optare per un server di posta Java in base alle esigenze del tuo progetto. L’API JavaMail non fa parte del JDK standard, quindi dovrai scaricarlo dal suo sito ufficiale, ovvero Pagina principale di JavaMail. Scarica l’ultima versione dell’implementazione di riferimento di JavaMail e includila nel percorso di build del tuo progetto. Il nome del file jar sarà javax.mail.jar. Se stai utilizzando un progetto basato su Maven, aggiungi semplicemente la dipendenza seguente al tuo progetto.

<dependency>
	<groupId>com.sun.mail</groupId>
	<artifactId>javax.mail</artifactId>
	<version>1.5.5</version>
</dependency>

Il programma Java per inviare email contiene i seguenti passaggi:

  1. Creazione dell’oggetto javax.mail.Session
  2. Creazione dell’oggetto javax.mail.internet.MimeMessage, dobbiamo impostare diverse proprietà in questo oggetto come l’indirizzo email del destinatario, l’oggetto dell’email, l’email di risposta, il corpo dell’email, gli allegati, ecc.
  3. Utilizzo di javax.mail.Transport per inviare il messaggio email.

La logica per creare la sessione differisce in base al tipo di server SMTP, ad esempio se il server SMTP non richiede alcuna autenticazione possiamo creare l’oggetto Session con alcune proprietà semplici mentre se richiede l’autenticazione TLS o SSL, allora la logica per creare sarà diversa. Quindi creerò una classe utility con alcuni metodi di utilità per inviare email e poi userò questo metodo di utilità con diversi server SMTP.

Esempio di programma JavaMail

La nostra classe EmailUtil che ha un singolo metodo per inviare email appare come segue, richiede javax.mail.Session e alcuni altri campi richiesti come argomenti. Per mantenere la semplicità, alcuni degli argomenti sono codificati ma è possibile estendere questo metodo per passarli o leggerli da alcuni file di configurazione.

package com.journaldev.mail;

import java.io.UnsupportedEncodingException;
import java.util.Date;

import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

public class EmailUtil {

	/**
	 * Utility method to send simple HTML email
	 * @param session
	 * @param toEmail
	 * @param subject
	 * @param body
	 */
	public static void sendEmail(Session session, String toEmail, String subject, String body){
		try
	    {
	      MimeMessage msg = new MimeMessage(session);
	      //imposta gli header del messaggio
	      msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
	      msg.addHeader("format", "flowed");
	      msg.addHeader("Content-Transfer-Encoding", "8bit");

	      msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));

	      msg.setReplyTo(InternetAddress.parse("[email protected]", false));

	      msg.setSubject(subject, "UTF-8");

	      msg.setText(body, "UTF-8");

	      msg.setSentDate(new Date());

	      msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
	      System.out.println("Message is ready");
    	  Transport.send(msg);  

	      System.out.println("EMail Sent Successfully!!");
	    }
	    catch (Exception e) {
	      e.printStackTrace();
	    }
	}
}

Nota che sto impostando alcune proprietà dell’header nel MimeMessage, sono utilizzate dai client di posta elettronica per visualizzare correttamente il messaggio email. Il resto del programma è semplice e autoesplicativo. Ora creiamo il nostro programma per inviare email senza autenticazione.

Invia posta in Java usando SMTP senza autenticazione

package com.journaldev.mail;

import java.util.Properties;

import javax.mail.Session;

public class SimpleEmail {
	
	public static void main(String[] args) {
		
	    System.out.println("SimpleEmail Start");
		
	    String smtpHostServer = "smtp.example.com";
	    String emailID = "[email protected]";
	    
	    Properties props = System.getProperties();

	    props.put("mail.smtp.host", smtpHostServer);

	    Session session = Session.getInstance(props, null);
	    
	    EmailUtil.sendEmail(session, emailID,"SimpleEmail Testing Subject", "SimpleEmail Testing Body");
	}

}

Nota che sto utilizzando Session.getInstance() per ottenere l’oggetto Session passando l’oggetto Properties. Dobbiamo impostare la proprietà mail.smtp.host con l’host del server SMTP. Se il server SMTP non è in esecuzione sulla porta predefinita (25), allora sarà necessario impostare anche la proprietà mail.smtp.port. Basta eseguire questo programma con il tuo server SMTP senza autenticazione e impostando l’indirizzo email del destinatario come il tuo indirizzo email e otterrai l’email in poco tempo. Il programma è semplice da capire e funziona bene, ma nella vita reale la maggior parte dei server SMTP utilizza qualche tipo di autenticazione come autenticazione TLS o SSL. Quindi vedremo ora come creare un oggetto Session per questi protocolli di autenticazione.

Invia Email in Java SMTP con Autenticazione TLS

package com.journaldev.mail;

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;

public class TLSEmail {

	/**
	   Outgoing Mail (SMTP) Server
	   requires TLS or SSL: smtp.gmail.com (use authentication)
	   Use Authentication: Yes
	   Port for TLS/STARTTLS: 587
	 */
	public static void main(String[] args) {
		final String fromEmail = "[email protected]"; //requires valid gmail id
		final String password = "mypassword"; // correct password for gmail id
		final String toEmail = "[email protected]"; // can be any email id 
		
		System.out.println("TLSEmail Start");
		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
		props.put("mail.smtp.port", "587"); //TLS Port
		props.put("mail.smtp.auth", "true"); //enable authentication
		props.put("mail.smtp.starttls.enable", "true"); //enable STARTTLS
		
                //crea oggetto Authenticator da passare come argomento a Session.getInstance
		Authenticator auth = new Authenticator() {
			//sovrascrivi il metodo getPasswordAuthentication
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(fromEmail, password);
			}
		};
		Session session = Session.getInstance(props, auth);
		
		EmailUtil.sendEmail(session, toEmail,"TLSEmail Testing Subject", "TLSEmail Testing Body");
		
	}

	
}

Dato che sto usando il server SMTP di GMail che è accessibile a tutti, puoi impostare le variabili corrette nel programma sopra e eseguirlo tu stesso. Credimi, funziona!! 🙂

Esempio di Java SMTP con autenticazione SSL

package com.journaldev.mail;

import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;

public class SSLEmail {

	/**
	   Outgoing Mail (SMTP) Server
	   requires TLS or SSL: smtp.gmail.com (use authentication)
	   Use Authentication: Yes
	   Port for SSL: 465
	 */
	public static void main(String[] args) {
		final String fromEmail = "[email protected]"; //requires valid gmail id
		final String password = "mypassword"; // correct password for gmail id
		final String toEmail = "[email protected]"; // can be any email id 
		
		System.out.println("SSLEmail Start");
		Properties props = new Properties();
		props.put("mail.smtp.host", "smtp.gmail.com"); //SMTP Host
		props.put("mail.smtp.socketFactory.port", "465"); //SSL Port
		props.put("mail.smtp.socketFactory.class",
				"javax.net.ssl.SSLSocketFactory"); //SSL Factory Class
		props.put("mail.smtp.auth", "true"); //Enabling SMTP Authentication
		props.put("mail.smtp.port", "465"); //SMTP Port
		
		Authenticator auth = new Authenticator() {
			//sovrascrivere il metodo getPasswordAuthentication
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(fromEmail, password);
			}
		};
		
		Session session = Session.getDefaultInstance(props, auth);
		System.out.println("Session created");
	        EmailUtil.sendEmail(session, toEmail,"SSLEmail Testing Subject", "SSLEmail Testing Body");

	        EmailUtil.sendAttachmentEmail(session, toEmail,"SSLEmail Testing Subject with Attachment", "SSLEmail Testing Body with Attachment");

	        EmailUtil.sendImageEmail(session, toEmail,"SSLEmail Testing Subject with Image", "SSLEmail Testing Body with Image");

	}

}

Il programma è quasi identico all’autenticazione TLS, solo alcune proprietà sono diverse. Come puoi vedere, sto chiamando alcuni altri metodi dalla classe EmailUtil per inviare l’allegato e l’immagine via email, ma non li ho ancora definiti. In realtà li ho mantenuti per mostrarli in seguito e mantenerlo semplice all’inizio del tutorial.

Esempio di JavaMail – invio di email in Java con allegato

Per inviare un file come allegato, è necessario creare un oggetto di javax.mail.internet.MimeBodyPart e javax.mail.internet.MimeMultipart. Prima aggiungi la parte del corpo per il messaggio di testo nell’email e quindi usa FileDataSource per allegare il file nella seconda parte del corpo multipart. Il metodo assomiglia a quello sotto.

/**
 * Utility method to send email with attachment
 * @param session
 * @param toEmail
 * @param subject
 * @param body
 */
public static void sendAttachmentEmail(Session session, String toEmail, String subject, String body){
	try{
         MimeMessage msg = new MimeMessage(session);
         msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
	     msg.addHeader("format", "flowed");
	     msg.addHeader("Content-Transfer-Encoding", "8bit");
	      
	     msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));

	     msg.setReplyTo(InternetAddress.parse("[email protected]", false));

	     msg.setSubject(subject, "UTF-8");

	     msg.setSentDate(new Date());

	     msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
	      
         // Crea la parte del corpo del messaggio
         BodyPart messageBodyPart = new MimeBodyPart();

         // Compila il messaggio
         messageBodyPart.setText(body);
         
         // Crea un messaggio multipart per l'allegato
         Multipart multipart = new MimeMultipart();

         // Imposta la parte del messaggio di testo
         multipart.addBodyPart(messageBodyPart);

         // La seconda parte è l'allegato
         messageBodyPart = new MimeBodyPart();
         String filename = "abc.txt";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         multipart.addBodyPart(messageBodyPart);

         // Invia le parti complete del messaggio
         msg.setContent(multipart);

         // Invia il messaggio
         Transport.send(msg);
         System.out.println("EMail Sent Successfully with attachment!!");
      }catch (MessagingException e) {
         e.printStackTrace();
      } catch (UnsupportedEncodingException e) {
		 e.printStackTrace();
	}
}

Il programma potrebbe sembrare complesso a prima vista ma è semplice, basta creare una parte del corpo per il messaggio di testo e un’altra parte del corpo per l’allegato e quindi aggiungerle al multipart. È possibile estendere questo metodo per allegare anche più file.

Esempio di JavaMail – invia email in Java con immagine

Dato che possiamo creare un corpo messaggio HTML, se il file immagine si trova in qualche posizione del server possiamo utilizzare l’elemento img per mostrarlo nel messaggio. Ma a volte vogliamo allegare l’immagine nell’email e poi usarla nel corpo dell’email stesso. Avrai visto tante email che hanno allegati di immagini e vengono anche utilizzate nel messaggio dell’email. Il trucco è allegare il file immagine come qualsiasi altro allegato e quindi impostare l’intestazione Content-ID per il file immagine e poi utilizzare lo stesso ID contenuto nel corpo del messaggio email con <img src='cid:image_id'>.

/**
 * Utility method to send image in email body
 * @param session
 * @param toEmail
 * @param subject
 * @param body
 */
public static void sendImageEmail(Session session, String toEmail, String subject, String body){
	try{
         MimeMessage msg = new MimeMessage(session);
         msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
	     msg.addHeader("format", "flowed");
	     msg.addHeader("Content-Transfer-Encoding", "8bit");
	      
	     msg.setFrom(new InternetAddress("[email protected]", "NoReply-JD"));

	     msg.setReplyTo(InternetAddress.parse("[email protected]", false));

	     msg.setSubject(subject, "UTF-8");

	     msg.setSentDate(new Date());

	     msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
	      
         // Crea la parte del corpo del messaggio
         BodyPart messageBodyPart = new MimeBodyPart();

         messageBodyPart.setText(body);
         
         // Crea un messaggio multipart per l'allegato
         Multipart multipart = new MimeMultipart();

         // Imposta la parte del messaggio di testo
         multipart.addBodyPart(messageBodyPart);

         // La seconda parte è l'allegato dell'immagine
         messageBodyPart = new MimeBodyPart();
         String filename = "image.png";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         // Il trucco è aggiungere l'intestazione content-id qui
         messageBodyPart.setHeader("Content-ID", "image_id");
         multipart.addBodyPart(messageBodyPart);

         // Terza parte per visualizzare l'immagine nel corpo dell'email
         messageBodyPart = new MimeBodyPart();
         messageBodyPart.setContent("

Attached Image

" + "", "text/html"); multipart.addBodyPart(messageBodyPart); // Imposta il messaggio multipart nel messaggio email msg.setContent(multipart); // Invia il messaggio Transport.send(msg); System.out.println("EMail Sent Successfully with image!!"); }catch (MessagingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }

Suggerimenti per la risoluzione dei problemi di JavaMail API

  1. java.net.UnknownHostException si verifica quando il sistema non è in grado di risolvere l’indirizzo IP del server SMTP, potrebbe essere errato o non accessibile dalla tua rete. Ad esempio, il server SMTP di GMail è smtp.gmail.com e se uso smtp.google.com, otterrò questa eccezione. Se il nome host è corretto, prova a pingare il server tramite la riga di comando per assicurarti che sia accessibile dal tuo sistema.

    pankaj@Pankaj:~/CODE$ ping smtp.gmail.com
    PING gmail-smtp-msa.l.google.com (74.125.129.108): 56 data bytes
    64 bytes from 74.125.129.108: icmp_seq=0 ttl=46 time=38.308 ms
    64 bytes from 74.125.129.108: icmp_seq=1 ttl=46 time=42.247 ms
    64 bytes from 74.125.129.108: icmp_seq=2 ttl=46 time=38.164 ms
    64 bytes from 74.125.129.108: icmp_seq=3 ttl=46 time=53.153 ms
    
  2. Se il tuo programma è bloccato nella chiamata del metodo send() di Transport, controlla che la porta SMTP sia corretta. Se è corretta, utilizza telnet per verificare che sia accessibile dal tuo computer, otterrai un output come quello riportato di seguito.

    pankaj@Pankaj:~/CODE$ telnet smtp.gmail.com 587
    Trying 2607:f8b0:400e:c02::6d...
    Connected to gmail-smtp-msa.l.google.com.
    Escape character is '^]'.
    220 mx.google.com ESMTP sx8sm78485186pab.5 - gsmtp
    HELO
    250 mx.google.com at your service
    

Questo è tutto per l’esempio di JavaMail per inviare email in Java utilizzando un server SMTP con diversi protocolli di autenticazione, allegati e immagini. Spero che risolva tutte le tue esigenze per l’invio di email nei programmi Java.

Source:
https://www.digitalocean.com/community/tutorials/javamail-example-send-mail-in-java-smtp