728x90
반응형
들어가기 전에
하기 포스팅은 일반적으로 많이 사용하는 Google SMTP나 Naver SMTP 서버가 아닌 따로 구성된 SMTP 서버를 통해 email을 전송하는 법에 대해 다룹니다.
- 사내 SMTP 서버의 경우 relay server이기 때문에,
postfix
의mynetworks
변수로 관리되는 IP를 통해 email이 전송된다면 따로 username/password가 필요하지 않습니다.
이로 인해, Google SMTP 또는 Naver SMTP를 통해 email을 전송하기 위해서는 application.yml
과 같은 설정 파일 내 추가 설정이 필요할 수 있습니다. 이 점 고려하시고 봐주시길 바랍니다.
SpringBoot를 이용한 Email 전송하기
Dependencies 추가하기
먼저, SpringBoot를 이용해 Email을 전송할 수 있도록 dependencies를 추가해줍니다.
[ Maven을 사용하는 경우 ]
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
<version>VERSION 명</version>
</dependency>
[ Gradle을 사용하는 경우 ]
implementation 'org.springframework.boot:spring-boot-starter-mail:VERSION 명'
Java mail이 제공하는 interfaces & class
interface & class | description |
---|---|
MailSender interface | email 전송 시 가장 기본이 되는 top-level interface |
JavaMailSender interface | MailSender의 sub-interface로 MIME message를 지원하고 MimeMessageHelper class와 함께 사용됩니다. |
JavaMailSenderImpl class | JavaMailSender interface를 어떻게 실행할 지 제공하며, MimeMessage와 SimpleMailMessage를 지원합니다. |
SimpleMailMessage class | simple mail message를 만드는데 사용하며, 보내는 사람/받는 사람/참조/숨은 참조/메일 내용 필드를 제공합니다. |
MimeMessagePreparator interface | MIME messages를 준비하기 위한 callback interface를 제공합니다. |
MimeMessageHelper class | MIME messages를 만들 수 있는 class이며, image와 전형적인 메일의 첨부파일과 text 컨텐츠를 HTML 형식으로 제공합니다. |
SpringBoot Mail Server Properties
spring:
mail:
host: SMTP 서버 IP
port: SMTP PORT
properties:
mail:
debug: true
smtp:
connectiontimeout: 5000
auth: false
starttls:
enable: false
ssl:
enable: false
- 필자의 경우, 사내 SMTP 서버를 사용하였기 때문에 많은 예제에서 볼 수 있는
smtp.gmail.com
에서 사용하는 587 포트를 사용하지 않았습니다. 사용하고자하는 SMTP 서버를 확인하시어spring.mail.host
와spring.mail.port
를 넣어야 합니다. spring.mail.properties.mail.debug
의 경우 메일 전송 시 어떻게 전송되고 있는지 상황을 파악하고자 켜두었습니다.spring.mail.properties.mail.smtp
의auth/starttls/ssl
의 경우, 사내 SMTP 서버 특성상 relay server이고,mynetworks
라는 설정값을 통해 mail 전송이 가능한 IP를 제한하고 있어 따로 인증이 필요하지 않아 false로 하였습니다.- google이나 naver의 SMTP를 사용할 때에는 해당 값을 true로 한 후,
spring.mail.username
과spring.mail.password
를 작성하셔서 사용해야 합니다.
- google이나 naver의 SMTP를 사용할 때에는 해당 값을 true로 한 후,
MailService.java와 MailServiceImpl.java
package earth.mail.service;
public interface MailService {
public void sendMail(MailDto mailDto);
}
- MailService 구현부를 여러개 만들 일은 없을 것 같지만 기존 프로젝트 구조와 맞추기 위해 interface와 implement 부분으로 나누었습니다. 상황에 따라 interface 없이 바로 class로 생성하여 사용하셔도 됩니다.
package earth.mail.service;
import java.io.File;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import earth.common.utils.MailUtil;
import earth.mail.dto.AttachFileDto;
import earth.mail.dto.MailDto;
@Service
public class MailServiceImpl implements MailService {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private JavaMailSenderImpl javaMailSender;
@Override
public void sendMail(MailDto mailDto) {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
try {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "UTF-8"); // use multipart (true)
InternetAddress[] toAddress = MailUtil.listToArray(mailDto.getToAddressList(), "UTF-8");
InternetAddress[] ccAddress = MailUtil.listToArray(mailDto.getCcAddressList(), "UTF-8");
InternetAddress[] bccAddress = MailUtil.listToArray(mailDto.getBccAddressList(), "UTF-8");
mimeMessageHelper.setSubject(MimeUtility.encodeText(mailDto.getSubject(), "UTF-8", "B")); // Base64 encoding
mimeMessageHelper.setText(mailDto.getContent(), mailDto.isUseHtmlYn());
mimeMessageHelper.setFrom(new InternetAddress(mailDto.getFromAddress(), mailDto.getFromAddress(), "UTF-8"));
mimeMessageHelper.setTo(toAddress);
mimeMessageHelper.setCc(ccAddress);
mimeMessageHelper.setBcc(bccAddress);
if(!CollectionUtils.isEmpty(mailDto.getAttachFileList())) {
for(AttachFileDto attachFileDto: mailDto.getAttachFileList()) {
FileSystemResource fileSystemResource = new FileSystemResource(new File(attachFileDto.getRealFileNm()));
mimeMessageHelper.addAttachment(MimeUtility.encodeText(attachFileDto.getAttachFileNm(), "UTF-8", "B"), fileSystemResource);
}
}
javaMailSender.send(mimeMessage);
logger.info("MailServiceImpl.sendMail() :: SUCCESS");
} catch (Exception e) {
logger.info("MailServiceImpl.sendMail() :: FAILED");
e.printStackTrace();
}
}
}
- 메일 전송 시, 첨부 파일도 함께 보낼 수 있도록
MimeMessageHelper
를 통해 메일 전송 서비스를 작성했습니다.- 메일 전송과 관련된 Dto(MailDto) 내에
isUseHtmlYn
속성을 넣어 HTML 형식으로 메일을 전송하고자 할 때 사용했습니다. - 특히, 기존 메일이 HTML 형식으로 보내고 있던터라 실 사용시, 해당 속성을 true로 하고 진행했습니다.
- 메일 전송과 관련된 Dto(MailDto) 내에
- 메일 받는 사람(to), 참조(cc), 숨은 참조(bcc) 모두 넣어서 보낼 수 있도록 Dto(MailDto)를 구성하여 해당 Dto의 내용을
mimeMessageHelper
에 세팅하여 전송하고 있습니다. - 첨부파일의 경우 첨부파일용 Dto를 따로 구성하여 해당 첨부파일의 실제 경로와 파일 명을 Dto에 담아 가져왔습니다. 가져온 Dto를 통해 어디 위치에 있는 파일을 어떤 이름으로 첨부할지 작성했습니다.
- 메일 깨짐 방지를 위해 Base 64 encoding을 사용하였으며, 관련된 참고 자료는 하단에 첨부하였습니다.
MailDto.java와 AttachFileDto.java
package earth.mail.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import earth.common.BaseDto;
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class MailDto extends BaseDto {
private String fromAddress;
private List<String> toAddressList = new ArrayList<>();
private List<String> ccAddressList = new ArrayList<>();
private List<String> bccAddressList = new ArrayList<>();
private String subject; // 제목
private String content; // 메일 내용
private boolean isUseHtmlYn; // 메일 형식이 HTML인지 여부(true, false)
private List<AtchFileDto> attachFileList = new ArrayList<>();
}
- 앞서
MailServiceImpl.java
에서 사용하는MailDto
입니다. - 기본적으로, 메일 보내는 이는 한명이지만 받는 사람/참조/숨은 참조는 각각 여러명이 될 수 있기 때문에
List
형식으로 작성하였고, 첨부 파일 역시 여러개를 한 번에 보낼 수 있기 때문에List
로 구성했습니다.
package earth.mail.dto;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import earth.common.BaseDto;
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class AttachFileDto extends BaseDto {
private String realFileNm;
private String attachFileNm;
}
- 첨부파일의 실제 경로 및 경로 내 파일명을 뽑기 위해 첨부파일용 Dto를 따로 뽑았습니다.
sendMail() 메소드 실 사용 예시
@Component
public class EarthJob extends BaseJob {
@Autowired
protected ConfigLoader configLoader;
@Autowired
private EarthService earthService;
@Autowired
private MailService mailService;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private static final String FROM_ADDRESS = "보내는 이 메일주소";
@Override
public void execute() throws Exception {
try {
/ *
* 다른 로직을 통해 첨부파일로 등록할 파일 경로(attachPath)와 첨부파일명(attachName)을 들고 왔다고 가정합니다.
* /
String mailSubject = "첨부파일 메일 전송 테스트입니다.";
String mailContent = "<p>안녕하세요.</p><p>"+ " 첨부파일 메일 전송 테스트입니다.</p><p>감사합니다.</p>";
List<String> toAddressList = ListUtil.splitStringToArrayList(this.getParam("options.toaddress"), ",");
List<String> ccAddressList = ListUtil.splitStringToArrayList(this.getParam("options.ccaddress"), ",");
List<String> bccAddressList = ListUtil.splitStringToArrayList(this.getParam("options.bccaddress"), ",");
List<AtchFileDto> atchFileList = new ArrayList<>(Arrays.asList(new AtchFileDto(attachPath, attachName)));
mailService.sendMail(new MailDto(FROM_ADDRESS, toAddressList, ccAddressList, bccAddressList, mailSubject, mailContent, true, atchFileList));
}
catch (Exception e) {
e.printStackTrace();
}
}
}
- 필자의 경우, 메일 전송 시 함께 보낼 첨부파일을 미리 만든 후 첨부 파일 경로 및 이름을 추출해온 뒤 메일 전송을 진행했습니다.
- 이에 위와 같이 진행하였으며, 위처럼 메일 전송 시 결과는 아래와 같습니다.
참고 자료
728x90
반응형
'FRAMEWORK > Spring' 카테고리의 다른 글
[Spring] @Controller vs @RestController (0) | 2022.09.10 |
---|---|
[SpringBoot 2.5↑] 빌드 시 2가지 jar가 생성되는 현상 (executable jar & plain jar) (4) | 2021.12.13 |
[SpringBoot] SpringBoot를 이용한 AWS S3에 resizing 이미지 업로드하기(Marvin 활용) (1) | 2021.12.04 |
[SpringBoot] SpringBoot를 이용한 AWS S3에 여러 파일 업로드 및 삭제 구현하기 (2) | 2021.10.29 |
[Querydsl, pageable] slice를 이용한 무한 스크롤 (0) | 2021.10.29 |