자바(JAVA)/JSP 웹 프로그래밍 공부 (성낙현의 JSP 자바 웹 프로그래밍 참고)

JAVA/JSP 45. SMTP를 활용한 이메일 전송하기 - 개요 및 프로젝트 구상, 네이버 SMTP 설정, 이메일 전송 프로그램 작성

개발학생 2025. 5. 13. 20:40
반응형

*JAVA/JSP 35번 글의 시점부터는 노트북이 고장나는 바람에.. 다른 분의 글과 이전에 올렸던 글들을 참고하여, 다른 데스크탑의 윈도우 환경에 환경설정을 다시 진행한 후 작성하였습니다. 환경설정 관련 글들은 아래를 참고해 주세요.

  • JDK11 설치 및 환경 변수(JAVA_HOME) 설정 - CLASSPATH는 추가하지 않음
 

자바(JAVA) 11 설치 및 환경설정 | 자바 11 환경 변수

자바로 코딩 공부를 하려면 개발 할 수 있는 환경을 만들어 주어야 한다. 그 순서를 먼저 작성하자면JAVA SE JDK 설치 -> JAVA 환경 변수 설정 -> IDE 설치 이렇게 볼 수 있겠다. 이 포스팅은 자바로 개

velog.io

  • 톰캣 설치, 이클립스 설치 - 이 글을 쓰는 시점에서는 Tomcat 8버전이 없어, Tomcat 9버전 설치
 

JSP) JDK, 이클립스(eclipse), 톰캣 설치 및 환경 설정

1. JDK 설치 → Path 설정 2.eclipse JAVA EE버전 다운로드 3.웹컨테이너 톰캣 설치 →톰캣 환경설정 1. JDK 설치 - JAVA) 1. JDK 참고하여 설치하고 설정한다. -https://storyblogger.tistory.com/15?category=984696 2. 구글에

storyblogger.tistory.com

  • 이클립스 JDK 버전 설정 - JDK11로 설정
 

[이클립스] JDK 버전 바꾸는 법

스프링을 사용하는 에러가 난다? 그러면 JRE 버전을 확인해보자! 프로젝트의 JRE System Library의 오른쪽을 살펴보면 [JavaSE-17]이라고 되어있다. 스프링이나 하이버네이트를 사용할 때, 자바 8이나 자

myvelop.tistory.com

  • JDK 설치 및 환경 변수(JAVA_HOME) 설정, 톰캣 설치, 이클립스 설치 및 JDK 버전 설정 이후~ ⇒ 톰캣 버전과 jsp 파일 경로는 글 내용과 다르게 아래 이미지와 같음

 

JAVA/JSP 1. 개발 환경 구축 - 이클립스 기본 설정

*JDK 설치 및 환경 변수(JAVA_HOME) 설정, 톰캣 설치, 이클립스 설치를 완료한 상태OpenJDK 11: 자바 프로그램을 컴파일하고 실행해주는 기본 도구*이클립스 JDK-17이 설치되어있어서, https://coding-house.tisto

keep-programming-study.tistory.com

 

 

JAVA/JSP 1. 개발 환경 구축 - JSP 예제 테스트

1. 프로젝트 생성1) [File] → [New] → [Dynamic Web Project] 선택 2) 프로젝트 설정 화면 → Project name: HelloJSP, Target runtime: Apache Tomcat v9.0, Dynamic web module version: 4.0으로 설정 후 Next 클릭 3) 자바 소스 파일

keep-programming-study.tistory.com

 

 

JAVA/JSP 1. 개발 환경 구축 - 마지막 추가 설정

1. 외부 웹 브라우저로 실행하기-크롬이클립스는 웹 애플리케이션 실행 시, 자체 브라우저를 통해 실행 결과 출력웹 애플리케이션 배포 시 사용자는 크롬/파이어폭스 같은 전용 웹 브라우저로

keep-programming-study.tistory.com

  • 오라클(Oracle Database 11gR2 Express Edition) 설치 및 설정 
 

JAVA/JSP 14. 데이터베이스 - 특징, 오라클 설치(Oracle Database 11gR2 Express Edition), 사용자 계정 생성 및

1. 데이터베이스의 특징우리가 매일 PC나 스마트폰을 통해 접하는 거의 모든 웹 애플리케이션에서 사용함매일 업데이트되는 뉴스나 날씨 등의 정보는 데이터베이스가 없다면 클라이언트에 전달

keep-programming-study.tistory.com

 

 

 

JAVA/JSP 15. 데이터베이스 - 테이블 및 시퀀스 생성, JDBC 설정 및 데이터베이스 연결

*회원제 게시판 만들기-회원 인증 필요4. 테이블 및 시퀀스 생성1) 테이블 생성(1) member 테이블 - 아이디, 패스워드, 이름, 가입 날짜테이블 정의컬럼명데이터 타입 null 허용 키 기본값 설명idvarchar2

keep-programming-study.tistory.com

 

JAVA/JSP 16. 데이터베이스 - 커넥션 풀로 성능 개선, 간단한 쿼리 작성 및 실행

6. 커넥션 풀로 성능 개선웹은 클라이언트의 요청에 서버가 응답하는 구조→ Connection 객체 생성 때마다 네트워크 통신이 이뤄지며, 시간이 걸리는 작업들이 수반됨 == 시스템 성능에 큰 영향을

keep-programming-study.tistory.com

  • 시퀀스 설정
 

JAVA/JSP 15. 데이터베이스 - 테이블 및 시퀀스 생성, JDBC 설정 및 데이터베이스 연결

*회원제 게시판 만들기-회원 인증 필요4. 테이블 및 시퀀스 생성1) 테이블 생성(1) member 테이블 - 아이디, 패스워드, 이름, 가입 날짜테이블 정의컬럼명데이터 타입 null 허용 키 기본값 설명idvarchar2

keep-programming-study.tistory.com

 

1. 개요 및 프로젝트 구상

1) 개요

  • SMTP(Simple Mail Transfer Protocol): 이메일을 전송하는 역할을 하는 이 서버가 따로 필요
  • POP3(Post Office Protocol 3): 클라이언트(사용자)가 메일 서버에서 메일을 받아오는 프로토콜 중 하나 
    -> 메일 서버에 저장된 메일을 사용자 컴퓨터로 가져와서 확인/삭제 가능(MS 아웃룩과 같은 프로그램 사용)
  • IMAP(Internet Message Access Protocol): POP3과 마찬가지로 사용자가 메일 서버에서 메일을 받아오는 프로토콜 중 하나
    -> 단, 중앙 서버에서 동기화가 이루어지므로 같은 계정으로 연결된 모든 장치에서 똑같은 내용이 보임 

2) 프로젝트 구상 

  • SMTP 서버를 직접 구축하지 않고, 포털 사이트인 네이버 메일 서버 이용

이메일 전송 프로세스

2. 네이버 SMTP 설정

1) www.naver.com(네이버 사이트)에 들어가서 로그인한 후, [메일] 클릭 

네이버 사이트에서 로그인한 후 [메일] 클릭

2) 아래에 메일 내역과 새로운 버튼이 생기는데, 아래의 [메일]을 또 클릭 

아래의 [메일]을 또 클릭

3) 네이버 메일 페이지로 넘어가면, [환경설정] 클릭 

네이버 메일 페이지에서 [환경설정] 클릭

4) 네이버 메일의 환경설정 페이지로 넘어가면, [POP3/IMAP 설정] 클릭 

네이버 메일의 환경설정 페이지에서 [POP3/IMAP 설정] 클릭

5) POP3/SMTP 설정 탭에서 다음과 같이 선택하고, [저장] 클릭

POP3/SMTP 사용에서 옵션을 모두 선택하고 [저장] 클릭

 

**(중요)프로그램 작성 시 사용할 정보

  • POP3/SMTP 설정 탭에서 더 아래로 내려가면 있음: 개인 회원의 아이디/비밀번호 부분을 제외하고는 모두 공통임

검은칠: 본인의 네이버 아이디/비밀번호

3. 이메일 전송 프로그램 작성

1) 이메일 작성 화면(JSP 파일)

<!-- src/main/webapp/email/EmailSendMain.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>   
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SMTP 이메일 전송</title>
</head>
<body>
<h2>이메일 전송하기</h2>
<form method="post" action="SendProcess.jsp">
<table border=1>
  <tr>    
    <td>
      보내는 사람 : <input type="text" name="from" value="" />
    </td>
  </tr>
  <tr>    
    <td>
      받는 사람 : <input type="text" name="to" value="" />
    </td>
  </tr>
  <tr>    
    <td>
      제목 : <input type="text" name="subject" size="50" value="" />
    </td>
  </tr>
  <tr>    
    <td>
      형식 :
      <input type="radio" name="format" value="text" checked />Text
      <input type="radio" name="format" value="html" />HTML
    </td>
  </tr>
  <tr>
    <td>
      <textarea name="content" cols="60" rows="10"></textarea>
    </td>
  </tr>
  <tr>
    <td>
      <button type="submit">전송하기</button>
    </td>
  </tr>
</table>
</form>
</body>
</html>

2) 이메일 전송 클래스 작성

(1) 확장 라이브러리 2가지 설치: https://mvnrepository.com/ 에서 검색 및 다운로드 후, 프로젝트에 추가 

  • 자바메일(JavaMail) API: 메일 서비스 관련 전반적 기능 수행
    -> Java EE 플랫폼에는 기본적으로 포함되어 있음(Java SE이므로 설치 필요)
    • 영어로 검색 후 1.4.7 버전을 클릭하고, jar 파일 다운로드 

1.4.7 버전 클릭
jar 클릭하여 파일 다운로드

  • 자바빈즈 액티베이션 프레임워크(JavaBeans(TM) Activation Framework): 자바메일 API로 MIME 데이터를 관리 
    • 영어로 검색 후 1.1.1 버전을 클릭하고, jar 파일 다운로드 

1.1.1 버전 클릭
jar 클릭하여 파일 다운로드

  • 두 라이브러리 모두 프로젝트에 추가한 모습

자바메일(JavaMail) API , 자바빈즈 액티베이션 프레임워크(JavaBeans(TM) Activation Framework) 프로젝트에 추가

(2) Java 파일 작성 - 네이버 아이디/비밀번호 부분은 개인의 아이디 및 비밀번호 입력 

// Java Resources/src/email/NaverSMTP.java

package email;

import java.util.Map;
import java.util.Properties;

import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

// 네이버 SMTP 서버를 통해 이메일을 전송하는 클래스
public class NaverSMTP {
  private final Properties serverInfo; // 서버 정보
  private final Authenticator auth;    // 인증 정보

  public NaverSMTP() {
    // 네이버 SMTP 서버 접속 정보(아까 언급한 POP3/SMTP 설정 탭의 아래에서 확인)
    serverInfo = new Properties();
    serverInfo.put("mail.smtp.host", "smtp.naver.com");
    serverInfo.put("mail.smtp.port", "465");
    serverInfo.put("mail.smtp.starttls.enable", "true");
    serverInfo.put("mail.smtp.auth", "true");
    serverInfo.put("mail.smtp.debug", "true");
    serverInfo.put("mail.smtp.socketFactory.port", "465");
    serverInfo.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
    serverInfo.put("mail.smtp.socketFactory.fallback", "false");

    // 사용자 인증 정보
    auth = new Authenticator() {
      @Override
      protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication("네이버 아이디", "네이버 패스워드");
      }
    };
  }

  // 주어진 메일 내용을 네이버 SMTP 서버에서 전송
  public void emailSending(Map<String, String> mailInfo) throws MessagingException {
    // 1. 세션 생성
    Session session = Session.getInstance(serverInfo, auth);
    session.setDebug(true);

    // 2. 메일 작성
    MimeMessage msg = new MimeMessage(session);
    msg.setFrom(new InternetAddress(mailInfo.get("from")));     // 보내는 사람
    msg.addRecipient(Message.RecipientType.TO, new InternetAddress(mailInfo.get("to")));  // 받는 사람
    msg.setSubject(mailInfo.get("subject"));                    // 제목
    msg.setContent(mailInfo.get("content"), mailInfo.get("format"));  // 내용

    // 3. 메일 전송
    Transport.send(msg);
  }
}//

3) HTML 형식 메일 템플릿 준비

  • 메일 본문을 HTML 형식으로 전송하기 위함
<!-- src/main/wabapp/email/MailForm.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>메일 템플릿</title>
</head>
<body>
  <h2>메일 템플릿</h2>
  <table border=1 width="100%">
    <tr>
      <td width="50">내용</td>
      <!-- 실제 이메일 내용으로 대체할 예정 -->
      <td>__CONTENT__</td>
    </tr>
    <tr>
      <td>이미지</td>
      <!-- 외부 메일 서버로 보내는 것이므로, 반드시 http나 https를 포함한 절대 경로 사용 -->
      <td><img src="https://cdn.dailyvet.co.kr/wp-content/uploads/2024/05/15231647/20240515ceva_experts4.jpg" alt="고양이" /></td>
    </tr>
  </table>
</body>
</html>

4) 이메일 전송 처리 페이지 작성(JSP 파일)

<!-- src/main/webapp/email/SendProcess.jsp -->
<%@ page import="java.io.BufferedReader"%>
<%@ page import="java.io.FileReader"%>
<%@ page import="java.util.HashMap"%>
<%@ page import="java.util.Map"%>
<%@ page import="email.NaverSMTP"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
// 이메일 내용 저장
Map<String, String> emailInfo = new HashMap<String, String>();
emailInfo.put("from", request.getParameter("from"));  // 보내는 사람
emailInfo.put("to", request.getParameter("to"));      // 받는 사람
emailInfo.put("subject", request.getParameter("subject"));  // 제목

// 내용은 메일 포맷에 따라 다르게 처리
String content = request.getParameter("content");  // 내용
String format = request.getParameter("format");    // 메일 포맷(text 혹은 html)
if (format.equals("text")) {
  // 텍스트 포맷일 때는 그대로 저장
  emailInfo.put("content", content);
  emailInfo.put("format", "text/plain;charset=UTF-8");
} else if (format.equals("html")) {
  // HTML 포맷일 때는 HTML 형태로 변환해 저장
  content = content.replace("\r\n", "<br/>");  // 줄바꿈을 HTML 형태로 수정

  String htmlContent = ""; // HTML용으로 변환된 내용을 담을 변수
  
  try {
    // HTML 메일용 템플릿 파일 읽기
    String templatePath = application.getRealPath("/email/MailForm.html");
    BufferedReader br = new BufferedReader(new FileReader(templatePath));

    // 한 줄씩 읽어 htmlContent 변수에 저장
    String oneLine;
    
    while ((oneLine = br.readLine()) != null) {
      htmlContent += oneLine + "\n";
    }
    br.close();
  } catch (Exception e) {
    e.printStackTrace();
  }

  // 템플릿의 "__CONTENT__" 부분을 메일 내용으로 대체 (변환 완료)
  htmlContent = htmlContent.replace("__CONTENT__", content);
  // 변환된 내용을 저장
  emailInfo.put("content", htmlContent);
  emailInfo.put("format", "text/html;charset=UTF-8");
}

try {
  NaverSMTP smtpServer = new NaverSMTP();  // 메일 전송 클래스 생성
  smtpServer.emailSending(emailInfo);      // 전송
  out.print("이메일 전송 성공");
} catch (Exception e) {
  out.print("이메일 전송 실패");
  e.printStackTrace();
}
%>

5) 동작 확인(EmailSendMain.jsp를 우클릭하고 Run On Server로 실행)

이메일 내용을 작성하고 형식을 [Text]로 선택한 다음, [전송하기] 클릭 후 오류 발생:  이메일 전송 실패

이메일 작성 후 [전송하기] 클릭
이메일 전송 실패

DEBUG: setDebug: JavaMail version 1.4.7

DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]

DEBUG SMTP: useEhlo true, useAuth true

DEBUG SMTP: useEhlo true, useAuth true

DEBUG SMTP: trying to connect to host "smtp.naver.com", port 465, isSSL false

javax.mail.MessagingException: Could not connect to SMTP host: smtp.naver.com, port: 465;

nested exception is:

javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1961)

at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:654)

at javax.mail.Service.connect(Service.java:317)

at javax.mail.Service.connect(Service.java:176)

at javax.mail.Service.connect(Service.java:125)

at javax.mail.Transport.send0(Transport.java:194)

at javax.mail.Transport.send(Transport.java:124)

at email.NaverSMTP.emailSending(NaverSMTP.java:57)

 

코파일럿에 질문하고 해결했다.. 네이버 SMTP 서버가 TLS 1.3을 강제하기 때문에 명시적으로 TLS 1.2를 설정해야 한다고 한다. 
-> NaverSMTP.java 파일의 public NaverSMTP() 내부의 마지막 줄에 
serverInfo.put("mail.smtp.ssl.protocols", "TLSv1.2");을 추가하여 해결했다! 

이메일 전송 실패 원인

이메일 전송 성공 화면
이메일 전송 성공 콘솔창1
이메일 전송 성공 콘솔창2

받는 사람의 메일함(gmail)을 확인했는데 한글이 다 깨져 보이는 오류 발생.... 
-> 코파일럿과 2시간 삽질한 끝에 성공..! NaverSMTP.java의 메서드를 다음과 같이 수정해서 성공했다

  // 주어진 메일 내용을 네이버 SMTP 서버에서 전송
  public void emailSending(Map<String, String> mailInfo) throws MessagingException, UnsupportedEncodingException {
    // 1. 세션 생성
    Session session = Session.getInstance(serverInfo, auth);
    session.setDebug(true);

    // 2. 메일 작성
    MimeMessage msg = new MimeMessage(session);
    msg.setFrom(new InternetAddress(mailInfo.get("from")));     // 보내는 사람
    msg.addRecipient(Message.RecipientType.TO, new InternetAddress(mailInfo.get("to")));  // 받는 사람
    String subject = new String(mailInfo.get("subject").getBytes("ISO-8859-1"), "UTF-8");
    msg.setSubject(MimeUtility.encodeText(subject, "UTF-8", "Q"));
    String content = new String(mailInfo.get("content").getBytes("ISO-8859-1"), "UTF-8");
    msg.setText(content, "UTF-8");  // 내용
    msg.setHeader("Content-Transfer-Encoding", "quoted-printable");  // 헤더 추가

    // 3. 메일 전송
    Transport.send(msg);
  }

한글이 다 깨져 보이는 오류
한글이 다 깨져 보이는 오류 해결!

문제는 네이버 STMP 서버에서 인코딩을 UTF-8로 처리하지 않아서 였다.... 코파일럿이 말한 이유는 아래와 같다...

문제 해결 내역(코파일럿)

이번엔 이메일 내용을 작성하고 형식을 [HTML]로 선택한 다음, [전송하기] 클릭 -> 전송 성공!

HTML 형식 이메일 작성
HTML 형식 이메일 전송 성공

전송에 성공했는데... HTML 양식이 그대로 텍스트로 출력되는 오류 발생 
-> 아래와 같이 NaverSMTP.java의 emailSending 메서드를 수정하긴 했는데 완전히 해결하진 못함.. HTML 형식 이메일 전송은 실무에서 쓸 일이 없어 보여서 다행이랄까... (제발 없었으면 좋겠다) 

  // 주어진 메일 내용을 네이버 SMTP 서버에서 전송
  public void emailSending(Map<String, String> mailInfo) throws MessagingException, UnsupportedEncodingException {
    // 1. 세션 생성
    Session session = Session.getInstance(serverInfo, auth);
    session.setDebug(true);

    // 2. 메일 작성
    MimeMessage msg = new MimeMessage(session);
    msg.setFrom(new InternetAddress(mailInfo.get("from")));     // 보내는 사람
    msg.addRecipient(Message.RecipientType.TO, new InternetAddress(mailInfo.get("to")));  // 받는 사람
    String subject = new String(mailInfo.get("subject").getBytes("ISO-8859-1"), "UTF-8");
    msg.setSubject(MimeUtility.encodeText(subject, "UTF-8", "Q"));
    String content = new String(mailInfo.get("content").getBytes("ISO-8859-1"));
    //msg.setText(content, "UTF-8");  // 내용
    msg.setContent(content, "text/html; charset=UTF-8");  // 내용
    // 헤더 추가
    msg.setHeader("Content-Disposition", "inline");
    msg.setHeader("Content-Transfer-Encoding", "8bit");  

    // 3. 메일 전송
    Transport.send(msg);
  }
  • 시도했는데 안 된 방법은 아래와 같다 

시도했는데 안 된 방법(코파일럿)
HTML 양식이 그대로 텍스트로 출력되는 오류
HTML 양식이 그대로 텍스트로 출력되는 오류 부분 해결

반응형