이메일 전송 기능 - javaMailSender를 써보자.

jinvicky·2023년 3월 9일
1

2023 Spring Project TIL

목록 보기
28/32

이전 이메일 전송 기능
https://velog.io/@jinvicky/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B9%84%EB%B2%88%EC%B0%BE%EA%B8%B0-%EB%8B%A8%EC%88%9C-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A0%84%EC%86%A1

기존 이메일 전송 기능을 개선해보고 싶었다.
이유

  • 구글 이메일로 메일 전송하는 것을 실패했다. 아쉬웠음
  • 내 이메일 계정 정보를 메서드 내에 lv로 하드코딩하는 것이 맞나? 생각이 들었다. 설정 파일로부터 불러오던지 느낌으로 가고 싶었다.
  • 코드가 javamailsender가 더 간단한 것 같다.
  • javamailsender 설정을 해보고 싶었다. (경험 얻고 싶어)

일단 구글 이메일 전송을 실패했던 이유는 구글은 운영 정책이 바뀌었는데 바뀌기 이전에 구현한 블로그들만 주구장창 시도해서였다.

"스프링 이메일 전송 구현"으로 검색하면 옛날 것만 떴는데
"javemailsender 사용법" 식으로 검색했더니 구글의 최신 정책을 반영해서 개발하는 법이 나와 있었다.

먼저 pom.xml에 mail 의존성 라이브러리를 추가한다.
https://noviceany.tistory.com/61

<dependency>
	<groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
	<groupId>org.apache.commons</groupId>
    <artifactId>commons-email</artifactId>
    <version>1.2</version>
</dependency>

root-context.xml에 javamailsender를 등록한다.
정보만 내 것으로 맞춰서 바꾸면 된다.

<bean id="mailSender" class ="org.springframework.mail.javamail.JavaMailSenderImpl" >
		<property name="host" value="smtp.gmail.com" />
		<property name="port" value="587" />
		<property name="username" value="내 gmail계정 이메일" />
		<property name="password" value="앱 비밀번호" />
		<property name="javaMailProperties">
			<props>
				<prop key="mail.smtp.starttls.enable">true</prop>
			</props>
		</property>
</bean>

property중에 password 항목에 주의하자.
처음에는 그냥 내 구글 계정 비밀번호인 줄 알았는데
이메일 전송이 당최 안되는 것이다. 검색해보니 앱 비밀번호를 인증을 거쳐서 생성해서 그걸 써야 하는 것이었다...

아래 사이트를 참고해서 후다닥 만들어본다.
https://ivvve.github.io/2019/02/09/java/Spring/mail_AuthenticationFailedException/

그리고 스펠링이 틀리지 않았는 지 여러 번 확인한다.
나의 경우에는 1. 앱 비번을 제대로 안 써서 2. 이메일 스펠링 틀려서 오류가 발생했었다.

참고사이트
https://2-jissun.tistory.com/12

이제 코드를 짜 보자.
Email, EmailSender, EmailController 클래스를 생성했다.

package com.fastcampus.ch4.domain;

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Email {

    private String toEmail;

    private String fromEmail;

    private String title;

    private String content;

}

이메일 객체 생성 시 좀 더 편하게 하려고 @Builder를 추가했다.

package com.fastcampus.ch4.service;


import com.fastcampus.ch4.domain.Email;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.mail.internet.MimeMessage;

@Service
public class EmailSender {

    @Autowired
    private JavaMailSender mailSender;
    //can not autowired라고 뜬다면 root-context.xml에 등록을 안 한 것이다.

    public String sendMail(Email email) {
        System.out.println("email = " + email);
        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(message, true, "UTF-8");
            messageHelper.setTo(email.getToEmail());
            messageHelper.setText(email.getContent());
            messageHelper.setFrom(email.getFromEmail());
            messageHelper.setSubject(email.getTitle());	// 메일제목은 생략이 가능하다

            mailSender.send(message);

        } catch(Exception e){
            System.out.println(e);
            return "Error";
        }
        return "Sucess";
    }
}

javamailsender 등록을 root-context.xml에서 제대로 했다면, @Autowired가 문제없이 된다.

이제 controller에서 호출해보자.

package com.fastcampus.ch4.controller;

import com.fastcampus.ch4.domain.Email;
import com.fastcampus.ch4.service.EmailSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class EmailController {

    @Autowired
    EmailSender emailSender;

    @GetMapping("/send/email")
    public ResponseEntity<HttpStatus> getEmail(String toEmail) {

        try {
            Email email = Email.builder()
                    .fromEmail("jinvicky17@gmail.com")
                    .toEmail(toEmail)
                    .title("정석마켓 제목")
                    .content("키키키")
                    .build();

            emailSender.sendMail(email);
        } catch (Exception e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
        return ResponseEntity.ok(HttpStatus.OK);
    }
}

기존 이메일 전송 코드와 비교해봤다.

  • 기존 코드는 한 메서드 안에서 이메일 설정도 하고 보내는 것도 한꺼번에 한다. javamailsender는 설정을 root-context.xml에서 하고 주입받아서 쓰니까 메서드 자체가 간결해졌다.

궁금?한 점

  • 기존 코드도 구글의 앱 비번을 썼다면 제대로 동작했을까? 생각이 들었다. 근데 그냥 javamailsender 쓸 예정이다.

결과 화면

profile
Front-End와 Back-End 경험, 지식을 공유합니다.

0개의 댓글

관련 채용 정보