본문 바로가기

프로젝트/[JSP]기본 게시판

메일 보내기 (JavaMail)

자바 메일은 자바 API를 이용하여 전자 메일을 주고받을 수 있는 기능으로 POP3, SMTP 등의 메일 프로토콜을 이용하여 메일을 주고받을 수 있도록 제공해주는 API

 

자바 메일 기능은 쇼핑목에서 주문이 완료되면 주문 내용을 자동으로 고객의 메일 주소로 발송하는 기능 등을 구현할 때 빈번히 사용되는 기능이다

자바 메일 기능은 우리가 흔히 웹에서 메일을 주고 받는 기능을 구현하는 것

 

내 프로젝트에서는 관리자계정에서 회원에게 어떤 정보를 전달할 때 사용할 수 있게 구현할 것 (회원 리스트에 이메일 링크 걸고 누르면 메일 쓰는 폼이 뜨고 받는 사람 메일은 디비에서 들고 와서 value가 바로 보이게 구현, 관리자 메일도 디비에서 들고 와서 value가 바로 보이게 구현)

1. 라이브러리 준비

자바로 메일 기능을 구현하려면 mail.jar와 activation.jar 라이브러리 파일이 필요

① mail.jar

https://github.com/javaee/javamail/releases

 

Releases · javaee/javamail

JavaMail API Reference Implementation. Contribute to javaee/javamail development by creating an account on GitHub.

github.com

javax.mail.jar 다운로드 후 WEB-INF lib에 붙여넣기

 

② activation.jar

https://www.oracle.com/java/technologies/java-beans-activation.html

Download -> jaf-1_1_1.zip 다운로드 후 그 안의 activation.jar 파일 복사 후 WEB-INF lib에 붙여 넣기

2. SMTP 서버 준비

SMTP(Simple Mail Transfer Protocol) : 메일을 전송할 수 있도록 해주는 프로토콜

대부분의 메일 서버는 SMTP 서버를 거쳐 메일을 전송

Google SMTP를 사용하여 메일을 전송할 것

 

mailForm.jsp

// body

<form action="./AdminMailSend.ad" method="post">
    <table class="table table-striped" data-effect="fade">
        <tbody>
            <tr>
                <td style="padding: 1.2em; text-align: center;">보내는 사람 메일</td>
                <td><input type="text" class="form-control" name="sender" style="width: 50%" required></td>
            </tr>
            <tr>
                <td style="padding: 1.2em; text-align: center;">받는 사람 메일</td>
                <td><input type="text" class="form-control" name="receiver" style="width: 50%" required></td>
            </tr>
            <tr>
                <td style="padding: 1.2em; text-align: center;">제목</td>
                <td><input type="text" class="form-control" name="subject" required></td>
            </tr>
            <tr>
                <td style="padding: 5.2em; text-align: center;">내용</td>
                <td><textarea class="form-control" rows="10" name="content" required></textarea> </td>
            </tr>
        </tbody>
    </table>

    <div class="form-group pull-right">
        <input type="submit" class="button" value="전송">
    </div>

</form>

 

// 2. 가상주소 매핑

디비를 사용하지 않기 때문에 Action을 이용해야 하나 고민했는데 jsp로 바로 보내자니 jsp는 view로 사용자에게 보이는 페이지이므로 적절하지 않다고 생각해 비즈니스 로직을 처리하는 model(java파일)로 연결시켰다

else if(command.equals("/AdminMailSend.ad")){
    System.out.println(" C : /AdminMailSend.ad 호출 ");
    // DB연결은 안하지만 비즈니스 로직처리해야되니까 Model이 필요하지 않을까
    // view페이지 이동

    action = new AdminMailSendAction();

    try {
        forward = action.execute(request, response);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

 

AdminMailSendAction.java

package com.town.admin.action;

import java.io.PrintWriter;
import java.util.Properties;

import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class AdminMailSendAction implements Action {

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {

		System.out.println(" M : AdminMailSendAction_execute 호출 ");
		
		// 세션제어
		HttpSession session = request.getSession();
		String id = (String)session.getAttribute("id");
		
		ActionForward forward = new ActionForward();
		if(id == null){
			forward.setPath("./MemberLogin.me");
			forward.setRedirect(true);
			return forward;
		}
		
		// 한글 처리(생략)
		// 전달받은 정보 저장
		String sender = request.getParameter("sender");
		String receiver = request.getParameter("receiver");
		String subject= request.getParameter("subject");
		String content = request.getParameter("content");
		response.setContentType("text/html; charset=UTF-8");
		PrintWriter out = response.getWriter();
		
		Properties properties = System.getProperties();
		properties.put("mail.smtp.starttls.enable", "true");
		properties.put("mail.smtp.host", "smtp.gmail.com");
		properties.put("mail.smtp.auth", "true");
		properties.put("mail.smtp.port", "587");	// gmail 포트
		Authenticator auth = new GoogleAuthentication();
		Session s = Session.getDefaultInstance(properties, auth);
		Message message = new MimeMessage(s);
		Address sender_address = new InternetAddress(sender);
		Address receiver_address = new InternetAddress(receiver);
		message.setHeader("content-type", "text/html; charset=UTF-8");
		message.setFrom(sender_address);
		message.addRecipient(Message.RecipientType.TO, receiver_address);
		message.setSubject(subject);
		message.setContent(content, "text/html; charset=UTF-8");
		message.setSentDate(new java.util.Date());
		Transport.send(message);
		out.println("<script>");
		out.println(" alert('메일이 정상적으로 전송되었습니다.'); ");
		out.println(" location.href='./AdminMemberList.ad'; ");
		out.println("</script>");
		
		return null;
	}

}

 

GoogleAuthentication.java

package com.town.main.action;

import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;

public class GoogleAuthentication extends Authenticator {
	PasswordAuthentication passAuth;
	
	public GoogleAuthentication(){
		// 첫번째 인자 : 구글 아이디
		// 두번째 인자 : 구글 비번
		passAuth = new PasswordAuthentication("anmedi3623", "***************");
	}
	
	public PasswordAuthentication getPasswordAuthentication(){
		return passAuth;
	}
	
}

 

코드를 입력해보면 아래와 같은 에러 발생

 

 

https://myaccount.google.com/signinoptions/two-step-verification/enroll-welcome

 

로그인 - Google 계정

하나의 계정으로 모든 Google 서비스를 Google 계정으로 로그인

accounts.google.com

위 링크에서 gmail 2단계 인증 설정 -> 재로그인 -> 보안 -> 앱 비밀번호 사용 선택 -> 생성

 

그러면 노란색 박스에 앱 비밀번호가 뜨는데 이것을 복사해서 GoogleAuthentication.java에서 비밀번호 부분(*******)에 붙여 넣기

 

보내는 사람 메일과 받는 사람 메일을 각각 메일 형식에 맞게 올바르게 작성하고 전송하면 메일을 정상적으로 받을 수 있다

메일을 전송하는데 시간이 좀 걸림, 메일 전송이 완료될 때까지 페이지 이동이 불가능

→ 메일 전송 버튼을 누르고 바로 다른 동작을 할 수 있게 쓰레드 형식으로 메일을 처리하도록 수정하기

멀티쓰레드를 이용한 메일 전송

메일 전송 버튼을 누르면 바로 다시 회원 목록 페이지로 이동하여 다른 작업을 할 수 있도록 구현

(다른 작업을 하고 있을 때 메일은 알아서 전송되도록)

+ 메일을 보내고 다시 목록으로 돌아갈 때 마지막으로 접속했던 목록 페이지로 이동이 되도록 pageNum을 처음부터 받아오도록 다른 페이지도 수정 (계속해봤던 것이므로 pageNum을 어떻게 받아오는지는 생략)

package com.town.admin.action;

import java.util.Properties;

import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

public class AdminMailSendAction implements Action {

	@Override
	public ActionForward execute(HttpServletRequest request, HttpServletResponse response) throws Exception {

		System.out.println(" M : AdminMailSendAction_execute 호출 ");
		
		// 세션제어
		HttpSession session = request.getSession();
		String id = (String)session.getAttribute("id");
		
		ActionForward forward = new ActionForward();
		if(id == null){
			forward.setPath("./MemberLogin.me");
			forward.setRedirect(true);
			return forward;
		}
		
		// 한글 처리(생략)
		// 전달받은 정보 저장 + pageNum
		String sender = request.getParameter("sender");
		String receiver = request.getParameter("receiver");
		String subject= request.getParameter("subject");
		String content = request.getParameter("content");
		
		String pageNum = request.getParameter("pageNum");
		
		
		// 멀티 쓰레드를 이용한 메일 전송(메일을 전송하는 동안 다른 동작을 할 수 있도록)
		new Thread(new Runnable() {
			
			@Override
			public void run() {
				try {
					Thread.sleep(5000);
					
					response.setContentType("text/html; charset=UTF-8");
					
					Properties properties = System.getProperties();
					properties.put("mail.smtp.starttls.enable", "true");
					properties.put("mail.smtp.host", "smtp.gmail.com");
					properties.put("mail.smtp.auth", "true");
					properties.put("mail.smtp.port", "587");	// gmail 포트
					Authenticator auth = new GoogleAuthentication();
					Session s = Session.getDefaultInstance(properties, auth);
					Message message = new MimeMessage(s);
					Address sender_address = new InternetAddress(sender);
					Address receiver_address = new InternetAddress(receiver);
					message.setHeader("content-type", "text/html; charset=UTF-8");
					message.setFrom(sender_address);
					message.addRecipient(Message.RecipientType.TO, receiver_address);
					message.setSubject(subject);
					message.setContent(content, "text/html; charset=UTF-8");
					message.setSentDate(new java.util.Date());
					Transport.send(message);
					
					System.out.println(" M : 메일 전송 완료 ");
					
				} catch (InterruptedException e) {
					e.printStackTrace();
				} catch (AddressException e) {
					e.printStackTrace();
				} catch (MessagingException e) {
					e.printStackTrace();
				}
			}
		}).start();
		
		
		forward.setPath("./AdminMemberList.ad?pageNum="+pageNum);
		forward.setRedirect(true);
		
		return forward;
	}

}

'프로젝트 > [JSP]기본 게시판' 카테고리의 다른 글

게시글작성 - 내용 줄바꿈  (0) 2022.06.04