Exemplo de JavaMail – Enviar e-mail em Java usando SMTP

Hoje vamos examinar um exemplo de JavaMail para enviar e-mails em programas Java. O envio de e-mails é uma das tarefas comuns em aplicações da vida real e é por isso que o Java fornece uma API robusta JavaMail que podemos usar para enviar e-mails usando um servidor SMTP. A API JavaMail suporta autenticação tanto TLS quanto SSL para envio de e-mails.

Exemplo de JavaMail

Hoje aprenderemos como usar a API JavaMail para enviar e-mails usando um servidor SMTP sem autenticação, com autenticação TLS e SSL, e como enviar anexos e incorporar imagens no corpo do e-mail. Para autenticação TLS e SSL, estou usando o servidor SMTP do Gmail porque ele suporta ambos. Você também pode optar por usar um servidor de e-mail Java dependendo das necessidades do seu projeto. A API JavaMail não faz parte do JDK padrão, então você terá que baixá-la do site oficial, ou seja, da Página Inicial do JavaMail. Baixe a versão mais recente da implementação de referência do JavaMail e inclua-a no caminho de construção do seu projeto. O nome do arquivo JAR será javax.mail.jar. Se você estiver usando um projeto baseado no Maven, basta adicionar a seguinte dependência ao seu projeto.

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

Um programa Java para enviar e-mails contém os seguintes passos:

  1. Criando objeto javax.mail.Session
  2. Criando objeto javax.mail.internet.MimeMessage, precisamos definir diferentes propriedades neste objeto, como endereço de e-mail do destinatário, Assunto do E-mail, e-mail de Resposta, corpo do e-mail, anexos etc.
  3. Usando javax.mail.Transport para enviar a mensagem de e-mail.

A lógica para criar a sessão difere com base no tipo de servidor SMTP, por exemplo, se o servidor SMTP não exigir autenticação, podemos criar o objeto Session com algumas propriedades simples, enquanto se exigir autenticação TLS ou SSL, então a lógica para criar será diferente. Portanto, vou criar uma classe utilitária com alguns métodos utilitários para enviar e-mails e depois vou usar este método utilitário com diferentes servidores SMTP.

Exemplo de Programa JavaMail

Nossa classe EmailUtil que possui um único método para enviar e-mail se parece com abaixo, ela requer javax.mail.Session e alguns outros campos necessários como argumentos. Para mantê-lo simples, alguns dos argumentos são codificados, mas você pode estender este método para passá-los ou lê-los de alguns arquivos de configuração.

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);
	      //definir cabeçalhos da mensagem
	      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();
	    }
	}
}

Observe que estou definindo algumas propriedades de cabeçalho no MimeMessage, elas são usadas pelos clientes de e-mail para renderizar e exibir corretamente a mensagem de e-mail. O restante do programa é simples e autoexplicativo. Agora vamos criar nosso programa para enviar e-mail sem autenticação.

Enviar email em Java usando SMTP sem autenticação

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");
	}

}

Observe que estou usando Session.getInstance() para obter o objeto de Sessão passando o objeto Properties. Precisamos definir a propriedade mail.smtp.host com o host do servidor SMTP. Se o servidor SMTP não estiver sendo executado na porta padrão (25), então você também precisará definir a propriedade mail.smtp.port. Basta executar este programa com seu servidor SMTP sem autenticação e definir o ID de email do destinatário como seu próprio ID de email e você receberá o email em pouco tempo. O programa é simples de entender e funciona bem, mas na vida real a maioria dos servidores SMTP usa algum tipo de autenticação, como autenticação TLS ou SSL. Portanto, veremos agora como criar um objeto de Sessão para esses protocolos de autenticação.

Enviar Email em Java SMTP com Autenticação 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
		
                //criar objeto Authenticator para passar como argumento em Session.getInstance
		Authenticator auth = new Authenticator() {
			//sobrescrever o método 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");
		
	}

	
}

Já que estou usando o servidor SMTP do GMail que é acessível a todos, você pode configurar as variáveis corretas no programa acima e executá-lo por conta própria. Acredite em mim, funciona!! 🙂

Exemplo de SMTP em Java com Autenticação 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() {
			//substitua o método 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");

	}

}

O programa é quase o mesmo que a autenticação TLS, apenas algumas propriedades são diferentes. Como você pode ver, estou chamando alguns outros métodos da classe EmailUtil para enviar anexos e imagens por email, mas ainda não os defini. Na verdade, mantive-os para mostrar mais tarde e manter simples no início do tutorial.

Exemplo de JavaMail – enviar email em java com anexo

Para enviar um arquivo como anexo, precisamos criar um objeto de javax.mail.internet.MimeBodyPart e javax.mail.internet.MimeMultipart. Primeiro, adicione a parte do corpo para a mensagem de texto no email e depois use FileDataSource para anexar o arquivo na segunda parte do corpo multipart. O método parece com o abaixo.

/**
 * 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));
	      
         // Criar a parte do corpo da mensagem
         BodyPart messageBodyPart = new MimeBodyPart();

         // Preencher a mensagem
         messageBodyPart.setText(body);
         
         // Criar uma mensagem multipart para anexo
         Multipart multipart = new MimeMultipart();

         // Definir parte da mensagem de texto
         multipart.addBodyPart(messageBodyPart);

         // A segunda parte é o anexo
         messageBodyPart = new MimeBodyPart();
         String filename = "abc.txt";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         multipart.addBodyPart(messageBodyPart);

         // Enviar as partes completas da mensagem
         msg.setContent(multipart);

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

Exemplo de JavaMail – enviar email em Java com imagem

Como podemos criar uma mensagem de corpo HTML, se o arquivo de imagem estiver em algum local do servidor, podemos usar o elemento img para exibi-los na mensagem. No entanto, às vezes desejamos anexar a imagem no email e, em seguida, usá-la na própria mensagem de email. Você deve ter visto muitos emails que têm anexos de imagem e também são usados na mensagem de email. A astúcia está em anexar o arquivo de imagem como qualquer outro anexo e, em seguida, definir o cabeçalho Content-ID para o arquivo de imagem e, em seguida, usar o mesmo ID de conteúdo na mensagem de email do corpo com <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));
	      
         // Criar a parte do corpo da mensagem
         BodyPart messageBodyPart = new MimeBodyPart();

         messageBodyPart.setText(body);
         
         // Criar uma mensagem multiparte para anexo
         Multipart multipart = new MimeMultipart();

         // Definir a parte de mensagem de texto
         multipart.addBodyPart(messageBodyPart);

         // A segunda parte é o anexo de imagem
         messageBodyPart = new MimeBodyPart();
         String filename = "image.png";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         //A astúcia está em adicionar o cabeçalho content-id aqui
         messageBodyPart.setHeader("Content-ID", "image_id");
         multipart.addBodyPart(messageBodyPart);

         //terceira parte para exibir a imagem na mensagem de email
         messageBodyPart = new MimeBodyPart();
         messageBodyPart.setContent("

Attached Image

" + "", "text/html"); multipart.addBodyPart(messageBodyPart); //Definir a mensagem multiparte para a mensagem de email msg.setContent(multipart); // Enviar mensagem Transport.send(msg); System.out.println("EMail Sent Successfully with image!!"); }catch (MessagingException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }

Dicas de Solução de Problemas da API JavaMail

  1. java.net.UnknownHostException ocorre quando o seu sistema não consegue resolver o endereço IP do servidor SMTP, pode estar errado ou inacessível a partir da sua rede. Por exemplo, o servidor SMTP do GMail é smtp.gmail.com e se eu usar smtp.google.com, irei receber essa exceção. Se o nome do host estiver correto, tente fazer ping no servidor através da linha de comando para garantir que ele seja acessível a partir do seu 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 o seu programa estiver preso na chamada do método Transport send(), verifique se a porta SMTP está correta. Se estiver correta, use o telnet para verificar se está acessível a partir da sua máquina, você obterá uma saída como abaixo.

    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
    

Isso é tudo para o exemplo do JavaMail para enviar e-mails em Java usando um servidor SMTP com diferentes protocolos de autenticação, anexos e imagens. Espero que resolva todas as suas necessidades para enviar e-mails em programas Java.

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