E-mail

Spring Email

이 문서에서는 스프링에서 이메일을 발송하는 방법에 대해서 살펴본다.

SMTP 프로토콜

위키백과에서 SMTP 설명 살펴보기 SMTP(간이 우편 전송 프로토콜, Simple Mail Transfer Protocol)은 인터넷에서 이메일을 보내기 위해 만들어진 프로토콜이다. 사용하는 TCP 포트번호는 25번이고 텍스트 기반의 통신 방식을 사용한다. SMTP 방식은 모든 문자를 7bit ASCII로 처리해야한다고 규정되어 있는데 이 때문에 8bit 이상의 코드를 사용하는 언어나 첨부파일 등은 마임(MIME)이라고 불리는 방식으로 7bit 형식으로 변환하여 전송한다.

Spring dependency

Java와 Spring에서 메일 발송을 하기 위해 필요한 의존성은 다음과 같다.

  • javax.mail.mail

  • org.springframework.spring-context-support

pom.xml에 다음과 같이 추가한다.

<dependencies>
    <!-- 중간 생략 -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>${org.springframework-version}</version>
    </dependency>

    <dependency>
        <groupId>javax.mail</groupId>
        <artifactId>mail</artifactId>
        <version>1.4.7</version>
    </dependency>
    <!-- 중간 생략 -->
</dependencies>

SMTP 서버 구축

윈도우 서버나 리눅스 등의 운영체제에서는 기본적으로 SMTP 서버 구축을 지원한다. 또한 애플리케이션으로 SMTP 서버를 구축하는 방법도 있다(ex : Apache James) 하지만 직접 만든 서버는 도메인을 등록하기 전까지는 스팸으로 필터링되는 등 상용 서비스에 이용하기 위한 절차가 복잡하다. 따라서, 이 문서에서는 상용 SMTP 서비스(ex : Gmail)을 이용하여 메일을 발송하는 방법에 대해서 다룬다.

Gmail SMTP 사용 설정

Spring에서 Gmail을 이용하려면 보안 수준이 낮은 앱 접근 허용 설정을 해야한다. 여기 를 눌러서 설정 페이지로 이동할 수 있다.

Spring에서 Gmail을 발송하면 Gmail 입장에서는 외부 액세스이므로 이를 허용해야 한다.

네이버에서는 이메일 환경설정을 통해 SMTP 접근을 허용할 수 있다.

위와 같이 설정하면 하단에 접속 관련 설정 정보가 표기된다.

간편 텍스트 메일 발송 코드

테스트 코드를 작성하여 메일을 발송해본다.

public class Test01{
    private JavaMailSender sender;
	
    @Before
    public void prepare() {
        JavaMailSenderImpl senderImpl = new JavaMailSenderImpl();
        senderImpl.setHost("smtp.gmail.com");
        senderImpl.setPort(587);
        senderImpl.setUsername("이메일계정");
        senderImpl.setPassword("이메일비밀번호");
		
        Properties prop = new Properties();
        prop.put("mail.smtp.auth", true);
        prop.put("mail.smtp.starttls.enable", true);
		
        senderImpl.setJavaMailProperties(prop);
		
        sender = senderImpl;
    }
	
    @Test
    public void sendMail() {
        SimpleMailMessage message = new SimpleMailMessage();
		
        String[] to = {"받을사람이메일"};
        message.setTo(to);
		
        String[] cc = {"참조이메일"};
        message.setCc(cc);
		
        String[] bcc = {"숨은참조이메일"};
        message.setBcc(bcc);
		
        message.setSubject("테스트 메일");
		
        message.setText("테스트 메일을 발송해봤습니다~ 참 쉽죠?");
		
        sender.send(message);
    }
}

간편 텍스트 메일 발송 코드 설명

메일 전송 도구 생성

Spring에서는 JavaMailSender를 이용하여 메일을 전송한다.

JavaMailSender는 인터페이스 형태이며, 실제 구현체는 JavaMailSenderImpl이다.

JavaMailSenderImpl senderImpl = new JavaMailSenderImpl();

senderImpl에 다음 정보를 설정한다.

  • Host : 이메일 서버의 주소를 설정한다.

    • Gmail의 경우 smtp.gmail.com으로 설정한다.

    • Naver의 경우 smtp.naver.com으로 설정한다.

  • Port : 이메일 서버의 포트를 설정한다.

    • 587번 포트는 SSL 포트

    • 465번 포트는 TLS 포트

  • Username : 이메일 서비스 계정을 설정한다.

  • Password : 이메일 서비스 계정의 비밀번호를 설정한다.

메일 작성

전송 도구를 생성했으면 이번에는 메시지를 작성해야 한다. 메시지는 다음 두 가지 형태로 사용한다.

  • SimpleMailMessage : 간편한 텍스트 메시지를 전송

  • MimeMessage : 다양한 형태의 메시지를 전송

현재 테스트 코드에서는 SimpleMailMessage를 사용한다.

SimpleMailMessage message = new SimpleMailMessage();

//.. 메시지 관련 설정

sender.send(message);

작성된 메시지는 JavaMailSendersend() 를 이용하여 발송하며, 정보가 올바르지 않을 경우 예외가 발생한다.

메일 정보 설정

메일에는 다음 정보들을 설정할 수 있다.

  • 수신자(to)

    • 복수 지정 가능

  • 참조(cc)

    • 복수 지정 가능

  • 숨은 참조(bcc)

    • 복수 지정 가능

  • 발신자(from)

    • 외부 메일 서비스를 이용할 경우 사용 불가

  • 제목(subject)

  • 내용(text)

SSL vs TLS

SSL(Secure Socket Layers)TLS(Transport Layer Security)는 모두 네트워크를 통해 작동하는 서버, 시스템, 응용프로그램 간의 인증 및 데이터 암호화를 제공하는 암호화 프로토콜이니다. SSL이 더 이전에 나온 프로토콜이며 TLSSSL 3.0을 기반으로 만들진 프로토콜이다.

SSL은 취약점이 발견되어 사용 중지되어가는 추세이며, TLS를 사용할 것을 권장하고 있다.

참조 위키문서 : https://ko.wikipedia.org/wiki/전송_계층_보안

MIME 메시지 발송 코드

SimpleMailMessage로는 간단한 텍스트만 보낼 수 있기 때문에 다음과 같은 내용을 전송하고 싶을 경우 MimeMessage를 사용해야 한다.

  • html 양식의 문서

  • 첨부파일

public class Test02{
    
    @Autowired
    private JavaMailSender sender;
    
    @Before
    public void prepare() {
        JavaMailSenderImpl senderImpl = new JavaMailSenderImpl();
        senderImpl.setHost("smtp.gmail.com");
        senderImpl.setPort(587);
        senderImpl.setUsername("이메일계정");
        senderImpl.setPassword("이메일비밀번호");
		
        Properties prop = new Properties();
        prop.put("mail.smtp.auth", true);
        prop.put("mail.smtp.starttls.enable", true);
		
        senderImpl.setJavaMailProperties(prop);
		
        sender = senderImpl;
    }
    
    @Test
    public void sendMimeMessage() throws MessagingException, UnsupportedEncodingException {
        MimeMessage message = sender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");

        String[] to = {"수신자 메일주소"};
        helper.setTo(to);

        //참조(cc), 숨은참조(bcc) 설정 생략

        helper.setSubject("마임 메시지 테스트");
        helper.setText("<h1>테스트 메시지입니다</h1>", true);

        DataSource source = new FileDataSource("D:/lion.png");
        helper.addAttachment("테스트", source);

        sender.send(message);
    }
    
}

MIME 메시지 발송 코드 설명

MimeMessageSimpleMailMessage와 생성 절차가 약간 다르다.

메일 전송 도구 생성

메일 전송 도구 생성 방법은 기존 SimpleMailMessage와 동일하다.

메시지 객체 생성

MimeMessage는 여러 가지 생성 방법이 있는데, JavaMailSender를 이용하여 생성하는 방법을 사용한다.

MimeMessage message = sender.createMimeMessage();

MimeMessage는 복잡한 데이터 설정이 가능하기 때문에, 편한 설정을 위하여 MimeMessageHelper를 사용하여 설정한다.

MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");

생성자에 전달할 수 있는 값은 다음과 같다.

  • message : 마임 메시지 객체

  • multipart : 멀티파트(파일전송) 여부

  • encoding : 전송 데이터의 인코딩 방식

메시지 정보 설정

메시지 정보 설정은 SimpleMailMessage와 동일하게 설정한다. 단, MimeMessageHelper에 설정한다.

String[] to = {"수신자 메일주소"};
helper.setTo(to);

//참조(cc), 숨은참조(bcc) 설정 생략

helper.setSubject("마임 메시지 테스트");

메시지 내용 설정

메시지 내용은 두 가지로 나누어 설정할 수 있다.

  • HTML 문서 형태로 작성하는 경우

  • 일반 텍스트 형태로 작성하는 경우

두 번째 인자는 HTML 모드 사용 여부 이므로 true로 설정하면 HTML 태그로 인식하여 변환 처리된다.

helper.setText("<h1>테스트 메시지입니다</h1>", true);

만약 다음과 같이 작성한다면 HTML을 사용하지 않는 것으로 간주하여 일반 글자 처리된다.

helper.setText("일반 텍스트 메시지입니다", false);

모드를 작성하지 않아도 일반 텍스트 글자로 처리된다.

helper.setText("일반 텍스트 메시지입니다");

첨부파일 추가

첨부파일은 DataSource 형태로 불러와 첨부해야 한다. 단, 주의사항은 javax.sql.DataSource가 아니라 javax.activation.DataSource를 사용해야 하므로 import에 주의한다.

DataSource source = new FileDataSource("D:/lion.png");
helper.addAttachment("테스트", source);

메일 전송 도구 등록

테스트를 마쳤으므로 메일 전송 도구와 같은 경우 프로젝트 내에서 사용할 수 있도록 등록해야 한다. 등록 설정은 전역 설정인 root-context.xml 파일에 작성한다.

<bean id="emailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="smtp.gmail.com"></property>
    <property name="port" value="587"></property>
    <property name="username" value="이메일 계정"></property>	 
    <property name="password" value="이메일 비밀번호"></property>

    <property name="javaMailProperties">
        <props>
            <prop key="mail.smtp.auth">true</prop>
            <prop key="mail.smtp.starttls.enable">true</prop>
        </props>
    </property>
</bean>

메일 전송 도구 등록(property 활용)

메일 정보의 경우 변하는 경우가 많으므로 property로 저장해두면 관리가 용이하다.

email.properties

email.host=smtp.gmail.com
email.port=587
email.username=이메일 계정
email.password=이메일 비밀번호

email.properties.auth=true
email.properties.starttls=true

properties를 작성할 경우 띄어쓰기는 지양하며, src/main/resources/properties에 작성한다.

전송 도구 등록 설정

<context:property-placeholder location="classpath:/properties/*.properties"/>

<bean id="emailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
    <property name="host" value="${email.host}"></property>
    <property name="port" value="${email.port}"></property>
    <property name="username" value="${email.username}"></property>	 
    <property name="password" value="${email.password}"></property>

    <property name="javaMailProperties">
        <props>
            <prop key="mail.smtp.auth">${email.properties.auth}</prop>
            <prop key="mail.smtp.starttls.enable">${email.properties.starttls}</prop>
        </props>
    </property>
</bean>

등록한 도구의 사용

등록이 완료되었다면 @Autowired 설정을 통하여 원하는 Component에서 사용할 수 있다.

@Autowired
private JavaMailSender sender;

Last updated