안녕하세요. 명월입니다.
이 글은 Java에서 메일(javax.mail)을 보내는 방법에 대한 글입니다.
프로그램상에서 우리가 메일 발송에 관해서는 여러가지 형태로 사용할 수 있습니다. 회원 가입시에 가입 인증이나 패스워드 찾기 등등이 있고, 또 여러가지 알람 기능으로도 메일을 많이 보냅니다.
최근에는 sns가 많이 생겨서 sns으로 메시지를 보내는 방법으로도 많이 사용됩니다만 그래도 아직도 메일 발송 기능은 없어지는 경우는 없는 것 같네요.
저는 google mail(gmail)를 통해서 메일을 보내는 예제입니다. 이전에 python으로 메일 보내는 방법에 대해 소개할 때 설정한 적이 있습니다.
링크 - [Python] 메일(smtplib)을 보내는 방법
Gmail이외에 Naver나 Daum을 통해서도 설정이 가능합니다.
구글 메일 참조 - https://support.google.com/a/answer/176600?hl=ko
네이버 메일 참조 - https://mail.naver.com/option/imap
다음 메일 참조 - https://cs.daum.net/faq/43/9234.html#35953
먼저 크롬에 접속해서 오른쪽 상단에 회원 정보로 갑니다.(로그인이 되지 않았으면 로그인을 먼저 합니다.)
글 계정으로 가서 보안 탭의 보안 수준이 낮은 앱의 액세스 탭으로 갑니다.
보안 수준이 낮은 앱의 사용을 체크합니다. 이 체크를 안하면 외부에서 구글 메일을 사용하지 못하게 하는 것이기 때문에 사용하기로 바꿔도 아이디 패스워드 노출이 안 된다면 보안상의 큰 문제는 없습니다.
java에서 메일을 발송하는 소스를 작성하기 전에 pom.xml에 메일 라이브러리를 등록해야 합니다.
레포지토리 - https://mvnrepository.com/artifact/javax.mail/mail
<!-- https://mvnrepository.com/artifact/javax.mail/mail -->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
메일 발송은 꼭 웹 환경에서 만들 필요는 없기 때문에 저는 console 환경에서 작성했습니다.
import java.io.File;
import java.util.Properties;
import javax.activation.DataHandler;
import javax.activation.DataSource;
import javax.activation.FileDataSource;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.Part;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;
// 시작함수는 아래쪽에 있습니다.
public class Program implements Runnable {
// main에서 run 함수가 호출되면 메일 발송을 시작합니다.
@Override
public void run() {
try {
// 메일 환경 변수 설정입니다.
Properties props = new Properties();
// 메일 프로토콜은 gmail를 이용할 것이기 때문에 smtp로 사용합니다.
props.setProperty("mail.transport.protocol", "smtp");
// 메일 호스트 주소를 설정합니다.
props.setProperty("mail.host", "smtp.gmail.com");
// ID, Password 설정이 필요합니다.
props.put("mail.smtp.auth", "true");
// port는 465입니다.
props.put("mail.smtp.port", "465");
// ssl를 사용할 경우 설정합니다.
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.quitwait", "false");
// id와 password를 설정하고 session을 생성합니다.
Session session = Session.getInstance(props, new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("id", "password");
}
});
// 디버그 모드입니다.
session.setDebug(true);
// 메일 메시지를 만들기 위한 클래스를 생성합니다.
MimeMessage message = new MimeMessage(session);
// 송신자 설정
message.setFrom(getAddress("nowonbun@gmail.com"));
// 수신자 설정
message.addRecipients(Message.RecipientType.TO, getAddresses("nowonbun@gmail.com,nowonbun@gmail.com"));
// 참조 수신자 설정
message.addRecipients(Message.RecipientType.CC, getAddresses("nowonbun@gmail.com"));
// 숨은 참조 수신자 설정
message.addRecipients(Message.RecipientType.BCC, getAddresses("nowonbun@gmail.com"));
// 메일 제목을 설정합니다.
message.setSubject("Test Mail");
// 메일 내용을 설정을 위한 클래스를 설정합니다.
message.setContent(new MimeMultipart());
// 메일 내용을 위한 Multipart클래스를 받아온다. (위 new MimeMultipart()로 넣은 클래스입니다.)
Multipart mp = (Multipart) message.getContent();
// html 형식으로 본문을 작성해서 바운더리에 넣습니다.
mp.addBodyPart(getContents("<html><head></head><body>Hello Test<br><img src=\"cid:image\" ></body></html>"));
// 첨부 파일을 추가합니다.
mp.addBodyPart(getFileAttachment("test.xlsx"));
// 이미지 파일을 추가해서 contextId를 설정합니다. contextId는 위 본문 내용의 cid로 링크가 설정 가능합니다.
mp.addBodyPart(getImage("capture.png", "image"));
// 메일을 보냅니다.
Transport.send(message);
} catch (Throwable e) {
e.printStackTrace();
}
}
// 이미지를 로컬로 부터 읽어와서 BodyPart 클래스로 만든다. (바운더리 변환)
private BodyPart getImage(String filename, String contextId) throws MessagingException {
// 파일을 읽어와서 BodyPart 클래스로 받는다.
BodyPart mbp = getFileAttachment(filename);
if (contextId != null) {
// ContextId 설정
mbp.setHeader("Content-ID", "<" + contextId + ">");
}
return mbp;
}
// 파일을 로컬로 부터 읽어와서 BodyPart 클래스로 만든다. (바운더리 변환)
private BodyPart getFileAttachment(String filename) throws MessagingException {
// BodyPart 생성
BodyPart mbp = new MimeBodyPart();
// 파일 읽어서 BodyPart에 설정(바운더리 변환)
File file = new File(filename);
DataSource source = new FileDataSource(file);
mbp.setDataHandler(new DataHandler(source));
mbp.setDisposition(Part.ATTACHMENT);
mbp.setFileName(file.getName());
return mbp;
}
// 메일의 본문 내용 설정
private BodyPart getContents(String html) throws MessagingException {
BodyPart mbp = new MimeBodyPart();
// setText를 이용할 경우 일반 텍스트 내용으로 설정된다.
// mbp.setText(html);
// html 형식으로 설정
mbp.setContent(html, "text/html; charset=utf-8");
return mbp;
}
// String으로 된 메일 주소를 Address 클래스로 변환
private Address getAddress(String address) throws AddressException {
return new InternetAddress(address);
}
// String으로 된 복수의 메일 주소를 콤마(,)의 구분으로 Address array형태로 변환
private Address[] getAddresses(String addresses) throws AddressException {
String[] array = addresses.split(",");
Address[] ret = new Address[array.length];
for (int i = 0; i < ret.length; i++) {
ret[i] = getAddress(array[i]);
}
return ret;
}
// 시작 함수 Program을 생성해서 run을 실행합니다.
public static void main(String[] args) {
Program p = new Program();
p.run();
}
}
제가 session의 디버그 모드를 했기 때문에 메일 서버와 주고 받는 메시지의 상태가 나옵니다. 혹시 프로토콜에 추가할 내용이 있으면 이 로그를 보고 추가하면 됩니다.
메일이 발송이 되었기 때문에 이제 제 메일함에 메일이 제대로 도착했는지 확인합니다.
메일이 잘 전송이 되었습니다.
여기까지 Java에서 메일(javax.mail)을 보내는 방법에 대한 설명이었습니다.
궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.
'Development note > Java' 카테고리의 다른 글
[Java] WebSocket의 Session 사용 방법(Broadcast)과 웹 채팅 소스 예제 (12) | 2020.02.20 |
---|---|
[Java] Servlet에서 사용하는 웹 소켓 (WebSocket) (6) | 2020.02.20 |
[Java] FTP에 접속하여 파일 다운로드, 업로드하는 방법(FTPClient) (0) | 2020.02.18 |
[Java] NIO(Non-Blocking IO) Socket 통신 (0) | 2020.02.04 |
[Java] 한글에서 유니코드로 변환하고 다시 한글에서 유니코드로 변환하는 방법 (0) | 2020.02.03 |
[Java] JSP Spring framework 환경에서 scheduler의 cron 사용법 (0) | 2020.01.16 |
[Java] POI를 이용한 Excel 다루기 (0) | 2019.11.24 |
[Java] PDF를 출력하는 방법(itextpdf) (0) | 2019.10.31 |