이 글은 Gmail SMTP를 이용하여 다중 이미지 파일과 동영상 파일을 첨부하여 이메일을 보내는 Spring Boot 프로젝트 코드를 작성하는 내용을 다루며, 이전 포스팅 내용에서 일부 이어집니다.
main
├── java
│ │
│ ├── controller
│ │ ├── EmailSendController (class)
│ ├── service
│ │ ├── EmailService (interface)
│ │ ├── impl
│ │ │ ├── EmailServiceImpl (class)
│ └── MailAppplication
│
└── resources
└── applicion.properties
package com.example.egudanna.controller;
import com.example.egudanna.service.email.EmailService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/mail")
public class EmailSendController {
private EmailService emailService;
public EmailSendController(EmailService emailService) {
this.emailService = emailService;
}
@PostMapping("/send")
public String sendMail(@RequestParam(value = "file", name = "file") MultipartFile[] file,
@RequestParam("to") String to,
@RequestParam("cc") String[] cc,
@RequestParam("subject") String subject,
@RequestParam("body") String body) {
return emailService.sendMail(file, to, cc, subject, body);
}
}
@RestController
: @Controller + @ResponseBody가 합쳐진 것입니다. 따라서 값을 json의 형태로 반환합니다. @RequestMapping
: 접속할 url을 나타냅니다. url중에서 공통된 부분은 class밖으로 빼내어 간결하게 코드를 작성할 수 있습니다. @RequestParam
: 한 번에 하나의 파라미터의 값을 저장하기 위해 사용됩니다. (주의) 스프링 부트 3.2부터 스프링부트가 매개변수의 이름을 인식하지 못하는 문제가 발생하였고 이를 해결하기 위해서는 파라미터의 이름을 명시해주어야 합니다.
매개변수를 인식하지 못하는 어노테이션들 중에는 @RequestParam
도 들어있기 때문에 @RequestParam String to
가 아닌 @RequestParam("to") String to
로 작성해주어야 정상적으로 파라미터의 값을 읽어들여 오류가 발생하지 않게 됩니다.
file
: 이미지
to
: 메일을 받을 대상
cc
: 주 수신자(to
) 외의 참조 수신자들
cc
들에게 메일을 보내며 cc
들은 메일의 복사본을 받습니다. subject
: 메일의 제목
body
: 메일의 본문
위의 코드를 치면 sendMail
줄에 빨간줄이 생길텐데 Create method 'sendMail' in 'EmailService'
를 누르면 EmailService에 sendMail
이 정의됩니다.
package com.example.egudanna.service.email;
import org.springframework.web.multipart.MultipartFile;
public interface EmailService {
String sendMail(MultipartFile[] file, String to,String[] cc, String subject, String body);
}
EmailService는 interface이므로 '구현'이 아닌 '정의'가 됩니다.
interface인 EmailService를 상속받아 구현하는 클래스입니다.
package com.example.egudanna.service.email.impl;
import com.example.egudanna.service.email.EmailService;
import jakarta.mail.internet.MimeMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
@Service
public class EmailServiceImpl implements EmailService {
@Value("${spring.mail.username}")
private String fromEmail;
@Autowired
private JavaMailSender javaMailSender;
@Override
public String sendMail(MultipartFile[] file, String to, String[] cc, String subject, String body) {
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setFrom(fromEmail);
mimeMessageHelper.setTo(to);
mimeMessageHelper.setCc(cc);
mimeMessageHelper.setSubject(subject);
mimeMessageHelper.setText(body);
for (int i = 0; i < file.length; i++) {
mimeMessageHelper.addAttachment(
file[i].getOriginalFilename(),
new ByteArrayResource(file[i].getBytes()));
}
javaMailSender.send(mimeMessage);
return "mail send";
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
application.properties에서 smtp설정이 완료되었다는 전제하에 @Value()
로 메일 송신자값을 가져오겠습니다.
송신자는 항상 동일하므로 텍스트로 주기보다는 설정파일에 적혀있는 값을 가져오는 것이 훨씬 유연합니다.
@Value("${spring.mail.username}")
private String fromEmail;
EmailService interface에 선언되어있는 sendMail()을 구현합니다.
MimeMessage
: 받아온 이메일로 메시지 폼을 만들어 메시지를 반환하는 함수로 이메일의 제목, 본문, 수신자, 발신자 및 첨부 파일과 같은 다양한 속성을 지정할 수 있습니다.
addAttachment
: 이미지 파일 이름과 바이트를 저장하여 이미지 파일을 저장할 수 있습니다.
send
: 이메일의 제목, 본문, 수신자, 발신자, 첨부파일이 담긴 메시지를 반환합니다.
return "mail send";
: 메일이 정상적으로 보내졌다면 mail send
라는 문자열을 반환합니다.
Post로 New Request를 생성하고 "Body > form-data"에서 각각의 파라미터 이름을 적어줍니다.
이 때 file
파라미터의 타입은 File
로 지정해주어야 합니다.
순서대로 이미지파일 업로드, 수신자, 참조 수신자(메일의 복사본을 받을 사람), 메일 제목, 메일 본문의 값을 입력한 뒤 오른쪽 상단의 "Send" 버튼을 누르면
사진의 아래처럼 "mail send"라는 메시지가 나오게 되고 메일 전송에 성공하게 됩니다.
localhost:7000/mail/send url에서 port인 7000은 제가 application.properties파일에서 server.port=7000으로 따로 지정해준 것입니다.
위의 설정을 안 하셨다면 기본 포트인 8080으로 url를 작성해주세요.
to
에 적었던 메일에도
cc
에 적었던 메일에도 동일한 메일이 잘 전송된 것을 확인할 수 있습니다.
혹시라도 메일이 오지 않았다면 "스팸메일함"에 메일이 보관되어있지 않은지 확인해주세요.
영상 파일을 업로드하기 위해서는 최대 업로드 크기를 지정해주어야 합니다.
만약 이제껏 작성한 상태 그대로 영상을 업로드할 경우에는 아래와 같은 에러가 발생하게 됩니다.
Resolved [org.springframework.web.multipart.MaxUploadSizeExceededException: Maximum upload size exceeded]
최대 파일 업로드 사이즈를 초과했다고 알려주고 있습니다.
따라서 application.properties파일에 아래와 같이 맥시멈을 증가시켜줘야합니다.
spring.servlet.multipart.maxFileSize=10MB
spring.servlet.multipart.maxRequestSize=30MB
저는 최대를 10MB로 지정하였는데 더 필요하다면 늘려주시면 됩니다.
방식은 아까와 동일합니다.
단지 업로드하는 파일이 이미지에서 동영상으로 변경된 것 뿐입니다.
저는 1분 남짓하는 영상을 첨부하였습니다.
메일에도 동영상 파일이 첨부된 것을 확인할 수 있습니다!