인생을 코딩하다.

[SMTP, SPRING, EC2] SMTP 메일 인증 시, 로컬에서는 잘 작동하는데 EC2에서는 왜 FAIL이 발생할까? 본문

Spring

[SMTP, SPRING, EC2] SMTP 메일 인증 시, 로컬에서는 잘 작동하는데 EC2에서는 왜 FAIL이 발생할까?

Hyung1 2022. 5. 1. 03:46
728x90
반응형

최근에 디프만 프로젝트를 진행하며  회원가입을 위해 이메일 인증 API를 개발하고 있었습니다. 약관 및 정책 등의 링크를 메일로 보내고, 메일에서 링크를 클릭하면 이메일 인증이 되는 flow 였습니다.

 

허나 이게 로컬에선 잘 돼는데, ec2 서버에서 계속 인증 메일을 보낼 때 AUTH LOGIN failed 발생했습니다. 두 가지 이유가 있엇습니다.

첫 번째 이유는

SMTP의 기본 port는 25입니다. 하지만,  Amazon EC2 서버에서는 SMTP port 25을 이용해서 메일을 보내는 것이 전송이 제한이 되어 있기 때문이였습니다. 따라서 Ec2 환경에서 기본 port인 25를 사용하게 돼면 이메일 인증에 실패하게 됩니다.

 

이는 메일 보내기를 25번 포트가 아닌 다른 포트 465, 587 포트를 사용해서 해결하는 방법이 존재합니다. 이 경우에 해당 연결은 제한되지 않아서 mail을 보내는데 문제는 없습니다.

@Component
@RequiredArgsConstructor
public class MailSenderConfig {

    private final MailProperties mailProperties;

    @Bean
    public JavaMailSender getJavaMailSender() {

        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(mailProperties.getHost());
        mailSender.setPort(mailProperties.getPort());

        mailSender.setUsername(mailProperties.getUserName());
        mailSender.setPassword(mailProperties.getPassword());

        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.debug", "true");

        return mailSender;
    }
}
 spring:
 
  mail:
    host: smtp.gmail.com
    port: 587
    username: ..
    password: ..
    auth-mail: ${AUTH_MAIL}
    auth-token: ${AUTH_TOKEN}
    
 // application.yml

위의 코드는 587로 cutom한 경우 입니다.  하지만 윗처럼 비즈니스 로직으로 작성하는 것 말고  yml에서 작성하는 것이 더 편리하고 private 합니다.

 

그리고 물론, 25 port를 쓰는 방법도 있습니다.

 

https://us-east-1.console.aws.amazon.com/support/contacts?region=us-east-1#/rdns-limits 에서 25 port를 사용하는 이유에 관해 작성하고 제출한 후에 승인을 받으면 가능합니다.

두 번째 이유는

https://myaccount.google.com/lesssecureapps?pli=1&rapt=AEjHL4NQ2SQPFXW7pKmmv8coQpa57m_Z58wGNKz9Bk7xrDOuYkqVO_9qpIDmXmqVveJxJw2cL4-ibpu9JCCmW6yQ5eTwng1nw 

 

로그인 - Google 계정

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

accounts.google.com

엑세스 접근 허용 및 2차 인증- 앱 비밀번호 설정을 해주지 않았기 때문이였습니다.

 

우선 여기서 엑세스 접근을 허용해주어야 합니다. 하지만 위의 엑세스 접근만 허용하게 되면, 로컬에서는 동작하나 Ec2에서는 AUTH LOGIN failed이 발생합니다.

 

보통 구글링으로 smtp 이메일 인증 하는 것에 관한 글만 보면 위의 엑세스 접근 방법 까지만 설명해주는 글이 많더라구요. 위의 엑세스 접근 방법에서만이 끝이아니라, 더 중요한게 있습니다. 저도 이 부분때메 꽤나 삽질을 하였는데요,

 

 

1. 보안 탭에서

2. 2단게 인증을 해줍니다. 인증 후,

3. 앱 비밀번호를 생성합니다.

 

앱 비밀번호를 생성하게 되면, 16자리의 비빌번호를 생성해줍니다. 비밀번호는 잘 보관해주시는게 좋습니다.

spring:

  ...
  
  mail:
    host: ${MAIL_HOST}
    port: ${MAIL_PORT}
    username: 이메일 아이디
    password: 방금 생성된 16자리 비밀번호 (기존 구글 계정 비밀번호 X) 
    auth-mail: ${AUTH_MAIL}
    auth-token: ${AUTH_TOKEN}
    
  ...

yml 파일에서 방금 생성된 16자리의 비밀번호를 적어줍니다. 기존의 구글 계정 비밀번호를 사용하게 되면 로컬에서는 동작하나 ec2에서는 동작하지 않게 됩니다.

@Component
@RequiredArgsConstructor
public class MailSenderConfig {

    private final MailProperties mailProperties;

    @Bean
    public JavaMailSender getJavaMailSender() {

        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        mailSender.setHost(mailProperties.getHost());
        mailSender.setPort(mailProperties.getPort());

        mailSender.setUsername(mailProperties.getUserName());  
        mailSender.setPassword(mailProperties.getPassword()); 

        Properties props = mailSender.getJavaMailProperties();
        props.put("mail.transport.protocol", "smtp");
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.starttls.enable", "true");
        props.put("mail.debug", "true");

        return mailSender;
    }
}

그리고 실행하시면 메일이 잘 전송되는 것을 확인하실 수 있습니다.

728x90
반응형
Comments