관리 메뉴

거니의 velog

(8) 스프링에서 지원하는 여러 가지 기능 2 본문

Java_Spring Framework part2

(8) 스프링에서 지원하는 여러 가지 기능 2

Unlimited00 2023. 11. 15. 21:25

3. 스프링 이메일 사용하기

* 스프링에서는 이메일 기능도 설정만으로 쉽게 구현할 수 있다. 우리는 구글에서 제공하는 SMTP 서버를 이용해 메일을 보낼 것이므로  www.google.com 으로 접속하여 구글 메일 계정을 미리 만들어 놓아야 한다.

1. 이메일 기능 설정을 위한 XML 파일들을 준비한다.

2. pom.xml 파일을 다음과 같이 작성한다. 이메일 기능을 사용하기 위해 코어 스프링 라이브러리 버전을 4.1.1.RELEASE로 변경한 후 관련 라이브러리를 추가한다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.myspring</groupId>
    <artifactId>pro28</artifactId>
    <name>pro28</name>
    <packaging>war</packaging>
    <version>1.0.0-BUILD-SNAPSHOT</version>
    <properties>
        <java-version>1.6</java-version>
        <org.springframework-version>4.1.1.RELEASE</org.springframework-version> <!-- 스프링 라이브러리 버전을 4.1.1.RELEASE로 변경한다. -->
        <org.aspectj-version>1.6.10</org.aspectj-version>
        <org.slf4j-version>1.6.6</org.slf4j-version>
    </properties>
    <dependencies>

	...
    
		<!-- 이메일 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${org.springframework-version}</version>
        </dependency> <!-- 스프링 4 이상 사용시 추가한다. -->
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>javax.mail-api</artifactId>
            <version>1.5.4</version>
        </dependency>
        <dependency>
            <groupId>com.sun.mail</groupId>
            <artifactId>javax.mail</artifactId>
            <version>1.5.3</version>
        </dependency> <!-- 자바 메일 라이브러리들을 추가한다. -->
        
	...

3. web.xml에서는 설정 파일이 여러 개인 경우 톰캣 컨테이너 실행 시 spring 폴더에 있는 모든 설정 파일들을 읽어 들이도록 지정한다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

	<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/spring/*.xml</param-value> 
	</context-param>

4. 구글 SMTP 서버와 연동해서 실습하므로 스프링의 JavaMailSenderImpl 클래스를 이용해 메일 서버와 관련된 정보를 설정하도록 mail-context.xml을 작성한다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
        <property name="host" value="smtp.gmail.com" /> <!-- 메일을 보냈을 때 실제 수신자에게 메일을 보내는 host 서버에 구글의 SMTP 서버를 설정한다. -->
        <property name="port" value="587" /> <!-- 구글 SMTP 메일 서버의 포트는 465 또는 587 이다. -->
        <property name="username" value="송신자@gmail.com" />
        <property name="password" value="메일비밀번호" /> <!-- 자신의 구글 메일 계정과 비밀번호를 설정한다. -->
        <property name="javaMailProperties">
            <props>
                <prop key="mail.transport.protocol">smtp</prop>
                <prop key="mail.smtp.auth">true</prop>
                <prop key="mail.smtp.starttls.enable">true</prop>
                <prop key="mail.smtp.socketFactory.class">javax.net.ssl.SSLSocketFactory</prop>
                <prop key="mail.debug">true</prop>
            </props>
        </property> <!-- 메일 전달 프로토콜 세부 속성을 설정한다. -->
    </bean>

    <!-- You can have some pre-configured messagess also which are ready to send -->
    <bean id="preConfiguredMessage" class="org.springframework.mail.SimpleMailMessage">
        <property name="to" value="수신자@naver.com"></property>
        <property name="from" value="송신자@gmail.com"></property>
        <property name="subject" value="테스트 메일입니다." />
    </bean> <!-- 수신자에게 메일을 정기적으로 보내는 경우 송수긴 메일 주소와 제목을 미리 지정해서 보낼 수 있다. -->
    
</beans>

5. 이제 실제 자바 코드로 메일을 전송해 보자. 다음과 같이 자바 클래스 파일들을 준비한다.

6. MailController 클래스를 다음과 같이 작성한다. @EnableAsync를 지정해서 메서드를 호출할 경우 비동기로 동작하게 하는 @Async 애너테이션 기능을 사용할 수 있다.

package com.myspring.pro28.ex03;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@EnableAsync
public class MailController {
	
    @Autowired
    private MailService mailService;
 
    @RequestMapping(value = "/sendMail.do", method = RequestMethod.GET)
    public void sendSimpleMail(HttpServletRequest request, HttpServletResponse response) 
                                                          throws Exception{
    	request.setCharacterEncoding("utf-8");
    	response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();
        mailService.sendMail("수신자@naver.com","테스트 메일","안녕하세요.보낸 메일 내용입니다."); // mailService의 sendMail() 메서드로 메일 관련 값(주소, 제목, 내용)을 전달한다.
        mailService.sendPreConfiguredMail("테스트 메일입니다."); // mail-context.xml에 설정한 메일 주소로 내용을 보낸다.
        out.print("메일을 보냈습니다!!");
    }
    
}

7. 이번에는 MailService 클래스이다. @Async 애너테이션으로 지정된 메서드는 비동기로 동작한다. 따라서 보내는 메일 수가 많을 경우에는 메일 보내는 작업을 따로 수행하므로 작업이 끝날 때까지 기다릴 필요가 없다.

package com.myspring.pro28.ex03;

import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMailMessage;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service("mailService")
public class MailService {

	@Autowired
	private JavaMailSender mailSender;
	@Autowired
	private SimpleMailMessage preConfiguredMessage; // mail-context.xml에서 설정한 빈을 자동으로 주입한다.

	@Async
	public void sendMail(String to, String subject, String body) {
		MimeMessage message = mailSender.createMimeMessage(); // MimeMessage 타입 객체를 생성한다.
		try {
			MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8"); // 메일을 보내기 위해 MimeMessageHelper 객체를 생성한다.
			// messageHelper.setCc("zzzzzz@naver.com");
			messageHelper.setFrom("송신자@naver.com", "홍길동"); // 메일 수신 시 지정한 이름으로 표시되게 한다. 지정하지 않으면 송신 메일 주소가 표시된다.
			messageHelper.setSubject(subject);
			messageHelper.setTo(to);
			messageHelper.setText(body);
			mailSender.send(message); // 제목, 수신처, 내용을 설정해 메일을 보낸다.
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Async
	public void sendPreConfiguredMail(String message) {
		SimpleMailMessage mailMessage = new SimpleMailMessage(preConfiguredMessage);
		mailMessage.setText(message);
		mailSender.send(mailMessage);
	} // mail-context.xml에서 미리 설정한 수신 주소로 메일 내용을 보낸다.

}

8. 다음의 주소로 요청한다.

- http://localhost:8090/pro28/sendMail.do

9. 설정한 메일 계정에 접속하여 수신 메일함을 확인해 보면 홍길동으로부터 메일이 온 것을 볼 수 있다.


[메일 보내기 실행 시 오류가 발생했다면?]

* 브라우저에서 메일을 보내려는데 아래 그림처럼 이클립스 콘솔에서 오류 메시지가 출력되었다면?

* 그러면 구글 계정 관리에서 보안 설정을 다시 해줘야 한다.

1. 구글 계정으로 로그인한 후 사용자 계정의 Google 계정을 클릭한다.

2. Signin & security(로그인 및 보안) 항목 중 Apps with account access를 클릭한다.

3. 항목들 중 Allow less secure apps를 ON으로 설정한다.



4. HTML 형식 메일 보내기

* 이번에는 스프링의 이메일 기능을 알아보기 위해 일부러 짧은 텍스트로만 작성된 메일을 보냈다.

* 하지만 실제로 쇼핑몰 들에서 보내온 판촉 메일을 열어보면 짧은 텍스트로만 이뤄진 메일은 거의 없다. 대부분은 아래 그림처럼 상품 이미지나 링크 등으로 구성된 HTML 형식의 이메일로, 이를 클릭하면 해당 상품 페이지로 이동하도록 되어 있다.

* 그럼 이번에는 HTML로 작성된 메일 내용을 보내보자.

1. 다음과 같이 MailController 클래스에 HTML 태그를 작성해 StringBuffer에 저장한 후 문자열로 내용을 보낸다.

package com.myspring.pro28.ex04;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@EnableAsync
public class MailController {
	@Autowired
	private MailService mailService;

	@RequestMapping(value = "/sendMail.do", method = RequestMethod.GET)
	public void sendSimpleMail(HttpServletRequest request, HttpServletResponse response) throws Exception {
		request.setCharacterEncoding("utf-8");
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		StringBuffer sb = new StringBuffer(); // StringBuffer 변수 sb를 선언한다.
		sb.append("<html><body>");
		sb.append("<meta http-equiv='Content-Type' content='text/html; charset=euc-kr'>");
		sb.append("<h1>" + "제품소개" + "<h1><br>");
		sb.append("신간 도서를 소개합니다.<br><br>");
		sb.append("<a href='http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788956746425&orderClick=LAG&Kc=#N'>");
		sb.append("<img  src='http://image.kyobobook.co.kr/images/book/xlarge/425/x9788956746425.jpg' /> </a><br>");
		sb.append("</a>");
		sb.append("<a href='http://www.kyobobook.co.kr/product/detailViewKor.laf?ejkGb=KOR&mallGb=KOR&barcode=9788956746425&orderClick=LAG&Kc=#N'>상품보기</a>");
		sb.append("</body></html>"); // 문자열로 HTML 태그를 작성한 후 sb에 저장한다.
		String str = sb.toString(); // 문자열로 변환한다.
		mailService.sendMail("수신자@naver.com", "신상품을 소개합니다.", str); // HTML 형식의 내용을 메일로 보낸다.

		out.print("메일을 보냈습니다!!");
	}
}

2. 메일 내용이 HTML로 표시되게 하려면 반드시 MineMessageHelper의 setText() 메서드의 두 번째 인자 값을 true로 설정해야 한다.

package com.myspring.pro28.ex04;

import javax.mail.internet.MimeMessage;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMailMessage;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service("mailService")
public class MailService {
	@Autowired
	private JavaMailSender mailSender;
	@Autowired
	private SimpleMailMessage preConfiguredMessage;

	@Async
	public void sendMail(String to, String subject, String body) {
		MimeMessage message = mailSender.createMimeMessage();

		try {
			MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8");
			messageHelper.setSubject(subject);
			messageHelper.setTo(to);
			messageHelper.setFrom("송신자@naver.com", "홍길동");
			messageHelper.setText(body, true); // 반드시 true로 설정해야 한다.
			mailSender.send(message);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Async
	public void sendPreConfiguredMail(String message) {
		SimpleMailMessage mailMessage = new SimpleMailMessage(preConfiguredMessage);
		mailMessage.setText(message);
		mailSender.send(mailMessage);
	}
}

3. 브라우저에 요청하여 메일을 수신한다. 그리고 수신 메일 본문에 있는 이미지를 클릭한다.

4. 그러면 지정한 웹 페이지가 브라우저에 나타난다.


[pom.xml에 설정하는 라이브러리 정보를 찾는 방법]

* 스프링 프레임워크에서 라이브러리가 필요할 경우 pom.xml에 <dependency> 태그를 이용해 중앙 서버에서 라이브러리를 설치한다. 그러면 필요한 라이브러리 정보는 어떻게 찾을까?

* 다음은 MySQL 드라이버에 대한 설정 정보를 가져오는 과정이다. 

1. https://mvnrepository.com/으로 접속한다.

2. 검색창에 mysql이라 입력하고 Search를 클릭한다.

3. 검색 목록에서 MySQL Connector/J를 클릭한다.

4. 8.0.33 버전을 클릭한다.

5. Maven 탭의 <dependency> 태그 부분을 복사해 pom.xml에 붙여 넣는다.

6. 스프링 부트에서 설정하려면 Gradle 탭을 클릭한 후 그루비로 된 정보를 복사해 붙여 넣는다.

7. pom.xml 에 설정한 후 라이브러리를 다운로드한다.

8. Maven Dependency에 MySQL 드라이버가 설치된 것을 확인할 수 있다.