티스토리 뷰

Spring

java gmail 연동

토마's 2020. 5. 15. 10:54

안녕하세요. 이전에 Java와 slack을 연동해 slack의 기능 중 하나인 webhook을 통해서 알림을 받는 포스팅을 진행했는데, 이번에는 gmail을 통해 메일로 알림을 받을 수 있는 기능을 연동하는 방법에 대해서 포스팅하려고 합니다. Slack을 연동했던 코드에 로직이 추가될 것이며, slack 연동 코드를 확인하시려면 아래 링크를 참고 부탁드립니다.

- Slack 연동 링크 : https://toma0912.tistory.com/95

 

java Slack webhook 연동

안녕하세요. 오늘은 자주 사용하는 협업 메신저 툴인 Slack과 java spring의 연동 방법에 대해서 간략하게 포스팅을 진행해보려고 합니다. 슬랙은 webhook이라는 기능이 지원이 되는데 해당 기능을 사�

toma0912.tistory.com

이번에는 구글의 gmail을 통해서 메일로 알림을 받는 내용을 간략하게 공유드리겠습니다.

gmail이란 구글에서 지원하는 메일 서비스이며 로고는 아래와 같습니다.

개발 환경 설정

서비스 로직으로 2가지를 진행하려고 하는데, commons-email 메일을 사용하는 방법을 위해 pom.xml 에 아래의 dependency를 추가합니다.

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-email -->
<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-email</artifactId>
  <version>1.5</version>
</dependency>

Application Properties 설정

그리고 gmail을 사용할 정보들을 properties 파일에서 관리하기 위해 application.properties 파일에 다음 내용을 추가합니다. 기본적으로 gmail 인증을 위해 username과 password를 사용하려는 이메일의 계정 및 패스워드를 사용하고, from은 보낸 사람, to는 받는 사람으로 ,를 통해 여러 사용자에게 전달 가능합니다. cc 또한 to와 같습니다.

# External Interface (Email)
notification.email.enabled=true
notification.email.smtp.hostname=smtp.gmail.com
notification.email.smtp.port=587
notification.email.smtpauth.enabled=true
notification.email.username=noreply@address
notification.email.password=password
notification.email.ssl.enabled=true
notification.email.starttls.enabled=true
notification.email.from.address=noreply@address
notification.email.to.address=receiver1@address,receiver2@address
notification.email.cc.address=receiver3@address

Java Gmail 연동

그리고 NotificationManager의 코드를 다음과 같이 수정합니다. 사용할 메세지는 기존과 같이 테스트 메세지를 만들어서 진행합니다.

package com.example.demo.notification;

import com.example.demo.notification.sender.EmailSender;
import com.example.demo.notification.sender.SlackSender;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class NotificationManager {

  private Logger logger = LoggerFactory.getLogger(NotificationManager.class);

  private final SlackSender slackSender;
  private final EmailSender emailSender;

  public NotificationManager(SlackSender slackSender,
      EmailSender emailSender) {
    this.slackSender = slackSender;
    this.emailSender = emailSender;
  }

  public void sendNotification() {
    logger.info("#### send Notification.");

    // generated Message
    String contents = generatedMessage();

    // send slack
    //slackSender.sendSlack(contents);

    // send mail
    emailSender.sendMail(contents);  // use commons-email
  }

  /**
   * generated Message.
   *
   * @return
   */
  private String generatedMessage() {
    StringBuilder sb = new StringBuilder();

    sb.append("[Notification]").append(System.getProperty("line.separator"))
      .append("[Name] : ").append("Tester").append(System.getProperty("line.separator"))
      .append("[Message] : ").append("테스트 메시지 !!");

    return sb.toString();
  }
}

 

실질적으로 메일 전송을 하기위한 EmailSender 클래스를 만들어 메일 전달을 위한 작업을 진행해줍니다.

package com.example.demo.notification.sender;

import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.SimpleEmail;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

@Service
public class EmailSender {

  private static Logger logger = LoggerFactory.getLogger(EmailSender.class);

  @Value("${notification.email.enabled}")
  private boolean emailEnabled;
  @Value("${notification.email.smtp.hostname}")
  private String hostName;
  @Value("${notification.email.smtp.port}")
  private int port;
  @Value("${notification.email.smtpauth.enabled}")
  private boolean authEnabled;
  @Value("${notification.email.username}")
  private String userName;
  @Value("${notification.email.password}")
  private String password;
  @Value("${notification.email.ssl.enabled}")
  private boolean sslEnabled;
  @Value("${notification.email.starttls.enabled}")
  private boolean tlsEnabled;
  @Value("${notification.email.from.address}")
  private String from;
  @Value("${notification.email.to.address}")
  private String to;
  @Value("${notification.email.cc.address}")
  private String cc;

  /**
   * commons-email
   *
   * @param contents
   */
  public void sendMail(String contents) {
    String[] contentArr = contents.split(System.getProperty("line.separator"));
    String subject = null;

    for (String str : contentArr) {
      if (str.contains("[Message] : ")) {
        subject = "[Title] " + str.substring(12);
        break;
      }
    }

    if (emailEnabled) {
      try {
        // Create an Email instance
        Email email = new SimpleEmail();
        email.setHostName(hostName);

        if (sslEnabled) {
          email.setSslSmtpPort(Integer.toString(port));
        } else {
          email.setSmtpPort(port);
        }

        if (authEnabled) {
          email.setAuthenticator(new DefaultAuthenticator(userName, password));
        }

        email.setStartTLSEnabled(tlsEnabled);
        email.setFrom(from);
        email.setSubject(subject);
        email.setMsg(contents);

        for (String addr : to.split(",")) {
          email.addTo(addr);
        }

        if (cc != null && !StringUtils.isEmpty(cc)) {
          for (String addr : cc.split(",")) {
            email.addCc(addr);
          }
        }

        // Send the email
        email.send();
      } catch (Exception e) {
        logger.error("Unhandled exception occurred while send Email.", e);
      }
    }
  }
}

 

테스트

메일 발송을 위한 로직이 완료가 되었으니 간단하게 테스트 코드를 실행 시켜서 메일을 발송해보도록 하겠습니다. 테스트 코드는 아래와 같습니다.

package com.example.demo.notification;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class NotificationManagerTest {

  @Autowired
  private NotificationManager notificationManager;

  @Test
  public void NotificationTest() {
    notificationManager.sendNotification();
  }
}

테스트를 실행하게 되면 아래와 같이 에러 메세지가 뜨는 것을 확인할 수 있습니다.

org.apache.commons.mail.EmailException: Sending the email to the following server failed : smtp.gmail.com:25
	at org.apache.commons.mail.Email.sendMimeMessage(Email.java:1469)
	at org.apache.commons.mail.Email.send(Email.java:1496)
			...

Gmail의 보안 수준이 낮은 앱 허용 설정이 되어 있지 않아 차단이 된 것으로 보이며, 구글에 로그인 후, Google 계정 > 보안 > 보안 수준이 낮은 앱 액세스를 허용 해주시면 됩니다. (여기서, 2단계 인증이 되어 있는 경우에는 2단계 인증을 풀어주셔야 됩니다.)

그리고 난 후, 다시 한번 테스트 코드를 실행 할 경우, 아래 이미지와 같이 정상적으로 gmail을 통해 알림을 받을 수 있습니다.

이것으로 java gmail 연동에 대한 포스팅을 마치도록 하겠습니다.