웹사이트 검색

JavaMail 예 - SMTP를 사용하여 Java로 메일 보내기


오늘은 자바 프로그램에서 이메일을 보내는 JavaMail 예제에 대해 알아보겠습니다. 이메일 보내기는 실제 응용 프로그램의 일반적인 작업 중 하나이므로 Java는 SMTP 서버를 사용하여 이메일을 보내는 데 사용할 수 있는 강력한 JavaMail API를 제공합니다. JavaMail API는 이메일 전송을 위해 TLS 및 SSL 인증을 모두 지원합니다.

자바메일 예제

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

전자 메일을 보내는 Java 프로그램에는 다음 단계가 포함됩니다.

  1. javax.mail.Session 객체 생성
  2. javax.mail.internet.MimeMessage 개체를 생성할 때 수신자 이메일 주소, 이메일 제목, 회신 이메일, 이메일 본문, 첨부 파일 등과 같은 이 개체에 다른 속성을 설정해야 합니다.< /리>
  3. javax.mail.Transport를 사용하여 이메일 메시지를 보냅니다.

세션을 생성하는 논리는 SMTP 서버 유형에 따라 다릅니다. 예를 들어 SMTP 서버에 인증이 필요하지 않은 경우 몇 가지 간단한 속성으로 세션 개체를 생성할 수 있는 반면 TLS 또는 SSL 인증이 필요한 경우 생성하는 논리가 달라집니다. . 따라서 이메일을 보내는 몇 가지 유틸리티 메서드가 포함된 유틸리티 클래스를 만든 다음 이 유틸리티 메서드를 다른 SMTP 서버와 함께 사용할 것입니다.

JavaMail 예제 프로그램

이메일을 보내는 단일 방법이 있는 EmailUtil 클래스는 아래와 같습니다. javax.mail.Session 및 기타 필수 필드가 인수로 필요합니다. 단순하게 유지하기 위해 일부 인수는 하드 코딩되어 있지만 이 메서드를 확장하여 인수를 전달하거나 일부 구성 파일에서 읽을 수 있습니다.

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);
	      //set message headers
	      msg.addHeader("Content-type", "text/HTML; charset=UTF-8");
	      msg.addHeader("format", "flowed");
	      msg.addHeader("Content-Transfer-Encoding", "8bit");

	      msg.setFrom(new InternetAddress("no_reply@example.com", "NoReply-JD"));

	      msg.setReplyTo(InternetAddress.parse("no_reply@example.com", 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();
	    }
	}
}

MimeMessage에서 일부 헤더 속성을 설정하고 있으며 이메일 클라이언트에서 이메일 메시지를 적절하게 렌더링하고 표시하는 데 사용됩니다. 프로그램의 나머지 부분은 간단하고 스스로 이해할 수 있습니다. 이제 인증 없이 이메일을 보내는 프로그램을 만들어 봅시다.

인증 없이 SMTP를 사용하여 Java로 메일 보내기

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_me@example.com";
	    
	    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");
	}

}

Properties 개체를 전달하여 Session 개체를 가져오기 위해 Session.getInstance()를 사용하고 있습니다. SMTP 서버 호스트로 mail.smtp.host 속성을 설정해야 합니다. SMTP 서버가 기본 포트(25)에서 실행되고 있지 않으면 mail.smtp.port 속성도 설정해야 합니다. 인증되지 않은 SMTP 서버에서 이 프로그램을 실행하고 수신자 이메일 ID를 자신의 이메일 ID로 설정하면 즉시 이메일을 받을 수 있습니다. 이 프로그램은 이해하기 쉽고 잘 작동하지만 실생활에서 대부분의 SMTP 서버는 TLS 또는 SSL 인증과 같은 일종의 인증을 사용합니다. 이제 이러한 인증 프로토콜에 대한 세션 개체를 만드는 방법을 살펴보겠습니다.

TLS 인증을 사용하여 Java SMTP로 이메일 보내기

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 = "myemailid@gmail.com"; //requires valid gmail id
		final String password = "mypassword"; // correct password for gmail id
		final String toEmail = "myemail@yahoo.com"; // 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
		
                //create Authenticator object to pass in Session.getInstance argument
		Authenticator auth = new Authenticator() {
			//override the getPasswordAuthentication method
			protected PasswordAuthentication getPasswordAuthentication() {
				return new PasswordAuthentication(fromEmail, password);
			}
		};
		Session session = Session.getInstance(props, auth);
		
		EmailUtil.sendEmail(session, toEmail,"TLSEmail Testing Subject", "TLSEmail Testing Body");
		
	}

	
}

나는 모두가 접근할 수 있는 Gmail SMTP 서버를 사용하고 있기 때문에 위의 프로그램에서 올바른 변수를 설정하고 직접 실행할 수 있습니다. 효과가 있다고 믿으세요!! :)

SSL 인증을 사용하는 Java SMTP 예제

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 = "myemailid@gmail.com"; //requires valid gmail id
		final String password = "mypassword"; // correct password for gmail id
		final String toEmail = "myemail@yahoo.com"; // 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() {
			//override the getPasswordAuthentication method
			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");

	}

}

이 프로그램은 TLS 인증과 거의 동일하며 일부 속성만 다릅니다. 보시다시피 이메일에 첨부 파일과 이미지를 보내기 위해 EmailUtil 클래스에서 다른 메서드를 호출하고 있지만 아직 정의하지는 않았습니다. 사실 나는 그것들을 나중에 보여주기 위해 보관했고 튜토리얼의 시작 부분에서 간단하게 유지했습니다.

JavaMail 예 - 첨부 파일이 있는 Java로 메일 보내기

파일을 첨부 파일로 보내려면 javax.mail.internet.MimeBodyPartjavax.mail.internet.MimeMultipart 객체를 만들어야 합니다. 먼저 이메일의 텍스트 메시지에 대한 본문 부분을 추가한 다음 FileDataSource를 사용하여 멀티파트 본문의 두 번째 부분에 파일을 첨부합니다. 방법은 아래와 같습니다.

/**
 * 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("no_reply@example.com", "NoReply-JD"));

	     msg.setReplyTo(InternetAddress.parse("no_reply@example.com", false));

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

	     msg.setSentDate(new Date());

	     msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
	      
         // Create the message body part
         BodyPart messageBodyPart = new MimeBodyPart();

         // Fill the message
         messageBodyPart.setText(body);
         
         // Create a multipart message for attachment
         Multipart multipart = new MimeMultipart();

         // Set text message part
         multipart.addBodyPart(messageBodyPart);

         // Second part is attachment
         messageBodyPart = new MimeBodyPart();
         String filename = "abc.txt";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         multipart.addBodyPart(messageBodyPart);

         // Send the complete message parts
         msg.setContent(multipart);

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

이 프로그램은 처음에는 복잡해 보일 수 있지만 간단합니다. 문자 메시지용 본문 부분과 첨부 파일용 본문 부분을 만든 다음 멀티파트에 추가하면 됩니다. 이 방법을 확장하여 여러 파일을 첨부할 수도 있습니다.

JavaMail 예제 - 이미지와 함께 Java로 메일 보내기

HTML 본문 메시지를 만들 수 있으므로 이미지 파일이 일부 서버 위치에 있으면 img 요소를 사용하여 메시지에 표시할 수 있습니다. 그러나 때때로 우리는 이메일에 이미지를 첨부한 다음 이메일 본문 자체에서 사용하기를 원합니다. 이미지 첨부 파일이 있고 이메일 메시지에도 사용되는 이메일을 많이 보셨을 것입니다. 요령은 다른 첨부 파일처럼 이미지 파일을 첨부한 다음 이미지 파일의 Content-ID 헤더를 설정한 다음. 와 함께 이메일 메시지 본문에 동일한 콘텐츠 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("no_reply@example.com", "NoReply-JD"));

	     msg.setReplyTo(InternetAddress.parse("no_reply@example.com", false));

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

	     msg.setSentDate(new Date());

	     msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(toEmail, false));
	      
         // Create the message body part
         BodyPart messageBodyPart = new MimeBodyPart();

         messageBodyPart.setText(body);
         
         // Create a multipart message for attachment
         Multipart multipart = new MimeMultipart();

         // Set text message part
         multipart.addBodyPart(messageBodyPart);

         // Second part is image attachment
         messageBodyPart = new MimeBodyPart();
         String filename = "image.png";
         DataSource source = new FileDataSource(filename);
         messageBodyPart.setDataHandler(new DataHandler(source));
         messageBodyPart.setFileName(filename);
         //Trick is to add the content-id header here
         messageBodyPart.setHeader("Content-ID", "image_id");
         multipart.addBodyPart(messageBodyPart);

         //third part for displaying image in the email body
         messageBodyPart = new MimeBodyPart();
         messageBodyPart.setContent("<h1>Attached Image</h1>" +
        		     "<img src='cid:image_id'>", "text/html");
         multipart.addBodyPart(messageBodyPart);
         
         //Set the multipart message to the email message
         msg.setContent(multipart);

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

JavaMail API 문제 해결 팁

  1. java.net.UnknownHostException comes when your system is not able to resolve the IP address for the SMTP server, it might be wrong or not accessible from your network. For example, GMail SMTP server is smtp.google.com, I will get this exception. If the hostname is correct, try to ping the server through command line to make sure it’s accessible from your system.

    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. If your program is stuck in Transport send() method call, check that SMTP port is correct. If it’s correct then use telnet to verify that it’s accessible from you machine, you will get output like below.

    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
    

JavaMail 예제에서 인증 프로토콜, 첨부 파일 및 이미지가 다른 SMTP 서버를 사용하여 Java로 메일을 보내는 것이 전부입니다. Java 프로그램에서 이메일을 보내는 데 필요한 모든 요구 사항을 해결하기를 바랍니다.