오늘은 Java 프로그램에서 이메일을 보내는 JavaMail 예제를 살펴보겠습니다. 이메일 보내기는 실생활 애플리케이션에서의 일반적인 작업 중 하나이며, 그래서 Java는 SMTP 서버를 사용하여 이메일을 보낼 수 있는 견고한 JavaMail API를 제공합니다. JavaMail API는 이메일 보내기에 대해 TLS 및 SSL 인증을 모두 지원합니다.
JavaMail 예제
오늘은 SMTP 서버를 사용하여 JavaMail API를 사용하여 이메일을 보내는 방법을 배우고, 인증 없이, TLS 및 SSL 인증을 사용하는 방법, 그리고 첨부 파일을 보내고 이메일 본문에 이미지를 첨부하고 사용하는 방법을 알아보겠습니다. TLS 및 SSL 인증의 경우, 양쪽 모두를 지원하기 때문에 Gmail SMTP 서버를 사용하고 있습니다. 프로젝트 요구 사항에 따라 Java 메일 서버를 선택할 수도 있습니다. JavaMail API는 표준 JDK의 일부가 아니므로 공식 웹 사이트인 JavaMail 홈 페이지에서 다운로드해야 합니다. 최신 버전의 JavaMail 참조 구현을 다운로드하고 프로젝트 빌드 경로에 포함시킵니다. jar 파일 이름은 javax.mail.jar입니다. Maven 기반 프로젝트를 사용하는 경우, 프로젝트에 아래 종속성을 추가하면 됩니다.
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.5</version>
</dependency>
Java 프로그램은 다음과 같은 단계를 포함하여 이메일을 보냅니다:
-
javax.mail.Session
객체 생성 -
javax.mail.internet.MimeMessage
객체 생성, 이 객체에 수신자 이메일 주소, 이메일 제목, 답장 이메일, 이메일 본문, 첨부 파일 등과 같은 다양한 속성을 설정해야 합니다. -
javax.mail.Transport
를 사용하여 이메일 메시지를 보냅니다.
세션을 생성하는 로직은 SMTP 서버의 유형에 따라 다릅니다. 예를 들어 SMTP 서버에 인증이 필요하지 않으면 몇 가지 간단한 속성으로 세션 객체를 생성할 수 있지만 TLS 또는 SSL 인증이 필요하면 세션을 생성하는 로직이 다릅니다. 따라서 여러 SMTP 서버에서 사용할 수 있는 유틸리티 메서드를 가진 유틸리티 클래스를 만들고 이 유틸리티 메서드를 사용하겠습니다.
JavaMail 예제 프로그램
다음과 같은 이메일 유틸 클래스를 가지고 있습니다. 이 클래스는 이메일을 보내는 단일 메서드를 가지고 있으며, 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);
// 메시지 헤더 설정
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();
}
}
}
주목할 것은 제가 MimeMessage에서 몇 가지 헤더 속성을 설정하고 있다는 것입니다. 이것들은 이메일 클라이언트에서 이메일 메시지를 제대로 렌더링하고 표시하는 데 사용됩니다. 프로그램의 나머지 부분은 간단하고 자명합니다. 이제 인증 없이 이메일을 보내는 프로그램을 만들어 보겠습니다.
Java에서 SMTP 인증 없이 메일 보내기
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");
}
}
제가 Session.getInstance()를 사용하여 Properties 객체를 전달하여 Session 객체를 가져오고 있음에 주목하십시오. SMTP 서버 호스트로 mail.smtp.host 속성을 설정해야 합니다. SMTP 서버가 기본 포트(25)에서 실행되지 않는 경우 mail.smtp.port 속성도 설정해야 합니다. 이 프로그램을 인증되지 않은 SMTP 서버로 실행하고 수신자 이메일 ID를 자신의 이메일 ID로 설정하면 곧바로 이메일을 받게 됩니다. 프로그램은 이해하기 쉽고 잘 작동하지만, 실제 생활에서 대부분의 SMTP 서버는 TLS 또는 SSL 인증과 같은 인증을 사용합니다. 이제 이러한 인증 프로토콜용 Session 객체를 만드는 방법을 살펴보겠습니다.
Java SMTP에서 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
//생성 Authenticator 객체를 Session.getInstance 인수로 전달
Authenticator auth = new Authenticator() {
//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");
}
}
나는 모든 사람이 접근할 수 있는 GMail SMTP 서버를 사용하고 있기 때문에, 위의 프로그램에 올바른 변수를 설정하고 직접 실행해 볼 수 있습니다. 믿으세요, 제가 말씀드린대로 작동합니다!! 🙂
Java SMTP 예제와 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() {
//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");
}
}
이 프로그램은 TLS 인증과 거의 동일하지만, 몇 가지 속성이 다릅니다. 저번 예제에서 이미일을 보내는 메서드를 호출한 것을 볼 수 있지만, 아직 정의하지 않았습니다. 사실 저는 나중에 보여주기 위해 그것들을 따로 두었고, 튜토리얼의 시작 부분에서는 간단하게 유지하기 위해 두었습니다.
JavaMail 예제 – 첨부 파일과 함께 자바로 메일 보내기
파일을 첨부 파일로 보내려면 javax.mail.internet.MimeBodyPart
및 javax.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("[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));
// 메시지 본문 부분 생성
BodyPart messageBodyPart = new MimeBodyPart();
// 메시지 채우기
messageBodyPart.setText(body);
// 첨부파일을 위한 멀티파트 메시지 생성
Multipart multipart = new MimeMultipart();
// 텍스트 메시지 부분 설정
multipart.addBodyPart(messageBodyPart);
// 두 번째 부분은 첨부파일
messageBodyPart = new MimeBodyPart();
String filename = "abc.txt";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
// 완전한 메시지 부분 보내기
msg.setContent(multipart);
// 메시지 보내기
Transport.send(msg);
System.out.println("EMail Sent Successfully with attachment!!");
}catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
처음 보기에 프로그램이 복잡해 보일 수 있지만 간단합니다. 텍스트 메시지에 대한 본문 부분을 생성하고 다른 본문 부분을 첨부파일에 만든 다음 멀티파트에 추가하기만 하면 됩니다. 이 방법을 확장하여 여러 파일을 첨부할 수도 있습니다.
JavaMail 예제 – 자바로 이미지와 함께 메일 보내기
HTML 본문 메시지를 생성할 수 있기 때문에 이미지 파일이 서버 위치에 있으면 img 요소를 사용하여 메시지에 표시할 수 있습니다. 하지만 때로는 이메일에 이미지를 첨부한 다음 이메일 본문 자체에서 사용하고 싶을 수도 있습니다. 이미지 첨부파일과 이메일 메시지에서 사용되는 이미지를 많이 보았을 것입니다. 그 요령은 다른 첨부파일과 마찬가지로 이미지 파일을 첨부한 다음 이미지 파일에 대한 Content-ID 헤더를 설정하고 이메일 메시지 본문에서 동일한 콘텐츠 ID를 사용하는 것입니다. 이것은 <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));
// 메시지 본문 부분 생성
BodyPart messageBodyPart = new MimeBodyPart();
messageBodyPart.setText(body);
// 첨부 파일을 위한 멀티파트 메시지 생성
Multipart multipart = new MimeMultipart();
// 텍스트 메시지 부분 설정
multipart.addBodyPart(messageBodyPart);
// 두 번째 부분은 이미지 첨부 파일
messageBodyPart = new MimeBodyPart();
String filename = "image.png";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
// 요령은 여기에 콘텐츠-id 헤더를 추가하는 것입니다
messageBodyPart.setHeader("Content-ID", "image_id");
multipart.addBodyPart(messageBodyPart);
// 이메일 본문에서 이미지를 표시하기 위한 세 번째 부분
messageBodyPart = new MimeBodyPart();
messageBodyPart.setContent("Attached Image
" +
"
", "text/html");
multipart.addBodyPart(messageBodyPart);
// 멀티파트 메시지를 이메일 메시지에 설정
msg.setContent(multipart);
// 메시지 보내기
Transport.send(msg);
System.out.println("EMail Sent Successfully with image!!");
}catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
JavaMail API 문제해결 팁
-
java.net.UnknownHostException
시스템이 SMTP 서버의 IP 주소를 확인할 수 없을 때 발생합니다. 잘못되었거나 네트워크에서 접근할 수 없는 경우입니다. 예를 들어, GMail SMTP 서버는 smtp.gmail.com이고 smtp.google.com을 사용하면 이 예외가 발생합니다. 호스트 이름이 올바른 경우 시스템에서 서버에 대한 ping을 시도하여 시스템에서 접근할 수 있는지 확인하십시오.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
-
프로그램이 Transport send() 메서드 호출에서 멈춘 경우 SMTP 포트가 올바른지 확인하십시오. 올바른 경우 텔넷을 사용하여 시스템에서 접근할 수 있는지 확인하고 다음과 같은 출력을 얻으십시오.
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 프로그램에서 이메일을 보내는 모든 요구 사항을 해결하실 수 있기를 바랍니다.
Source:
https://www.digitalocean.com/community/tutorials/javamail-example-send-mail-in-java-smtp