[SpringBoot] Gmail SMTP로 Image, Video File을 첨부하여 메일을 송신해보자

Haeun Noh·2024년 5월 27일
0

Spring & SpringBoot3

목록 보기
5/5
post-thumbnail

0527

이 글은 Gmail SMTP를 이용하여 다중 이미지 파일과 동영상 파일을 첨부하여 이메일을 보내는 Spring Boot 프로젝트 코드를 작성하는 내용을 다루며, 이전 포스팅 내용에서 일부 이어집니다.


🗂️ 폴더 구조

  • IDE: IntelliJ 유료버전 (gradle)
  • Java version: 17
main
	├── java
	│   │   
	│   ├── controller
	│   │   ├── EmailSendController (class)
	│   ├── service
	│   │   ├── EmailService (interface)
	│   │   ├── impl
	│   │   │   ├── EmailServiceImpl (class)
    │   └── MailAppplication 
	│
	└── resources
	    └── applicion.properties

👀 EmailSendController

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 : 메일의 본문


👀 EmailService

위의 코드를 치면 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이므로 '구현'이 아닌 '정의'가 됩니다.


👀 EmailServiceImpl

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;

👩‍💻 sendMail Overriding하기

EmailService interface에 선언되어있는 sendMail()을 구현합니다.

  • MimeMessage : 받아온 이메일로 메시지 폼을 만들어 메시지를 반환하는 함수로 이메일의 제목, 본문, 수신자, 발신자 및 첨부 파일과 같은 다양한 속성을 지정할 수 있습니다.

  • addAttachment : 이미지 파일 이름과 바이트를 저장하여 이미지 파일을 저장할 수 있습니다.

  • send : 이메일의 제목, 본문, 수신자, 발신자, 첨부파일이 담긴 메시지를 반환합니다.

  • return "mail send"; : 메일이 정상적으로 보내졌다면 mail send라는 문자열을 반환합니다.


📤 Postman으로 이미지 파일이 첨부된 메일 전송해보기


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로 지정하였는데 더 필요하다면 늘려주시면 됩니다.


📤 Postman에서 메일로 영상 송신하기

방식은 아까와 동일합니다.
단지 업로드하는 파일이 이미지에서 동영상으로 변경된 것 뿐입니다.


저는 1분 남짓하는 영상을 첨부하였습니다.


메일에도 동영상 파일이 첨부된 것을 확인할 수 있습니다!


profile
기록의 힘을 믿는 개발자, 노하은입니다!

0개의 댓글