AWS SES로 이메일 발송 시 파일첨부 기능 추가하기
얼마 전에 AWS SES + Spring Boot를 이용해서 이메일 발송하는 예제를 작성했었는데요.
이번에는 파일을 첨부하여 발송하는 기능까지 알아보겠습니다.
이미 AWS SES 공식 문서 맨 하단에 Java로 작성된 예제코드가 작성돼있는데요. 핵심 부분만 잠시 살펴보겠습니다.
AWS SES 공식문서 예제코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | public static void main(String[] args) throws AddressException, MessagingException, IOException { Session session = Session.getDefaultInstance(new Properties()); // Create a new MimeMessage object. MimeMessage message = new MimeMessage(session); // Add subject, from and to lines. message.setSubject(SUBJECT, "UTF-8"); message.setFrom(new InternetAddress(SENDER)); message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(RECIPIENT)); // Create a multipart/alternative child container. MimeMultipart msg_body = new MimeMultipart("alternative"); // Create a wrapper for the HTML and text parts. MimeBodyPart wrap = new MimeBodyPart(); // Define the text part. MimeBodyPart textPart = new MimeBodyPart(); textPart.setContent(BODY_TEXT, "text/plain; charset=UTF-8"); // Define the HTML part. MimeBodyPart htmlPart = new MimeBodyPart(); htmlPart.setContent(BODY_HTML,"text/html; charset=UTF-8"); // Add the text and HTML parts to the child container. msg_body.addBodyPart(textPart); msg_body.addBodyPart(htmlPart); // Add the child container to the wrapper object. wrap.setContent(msg_body); // Create a multipart/mixed parent container. MimeMultipart msg = new MimeMultipart("mixed"); // Add the parent container to the message. message.setContent(msg); // Add the multipart/alternative part to the message. msg.addBodyPart(wrap); // Define the attachment MimeBodyPart att = new MimeBodyPart(); DataSource fds = new FileDataSource(ATTACHMENT); att.setDataHandler(new DataHandler(fds)); att.setFileName(fds.getName()); // Add the attachment to the message. msg.addBodyPart(att); // Try to send the email. try { System.out.println("Attempting to send an email through Amazon SES " +"using the AWS SDK for Java..."); // Instantiate an Amazon SES client, which will make the service // call with the supplied AWS credentials. AmazonSimpleEmailService client = AmazonSimpleEmailServiceClientBuilder.standard() // Replace US_WEST_2 with the AWS Region you're using for // Amazon SES. .withRegion(Regions.US_WEST_2).build(); // Print the raw email content on the console PrintStream out = System.out; message.writeTo(out); // Send the email. ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); message.writeTo(outputStream); RawMessage rawMessage = new RawMessage(ByteBuffer.wrap(outputStream.toByteArray())); SendRawEmailRequest rawEmailRequest = new SendRawEmailRequest(rawMessage) .withConfigurationSetName(CONFIGURATION_SET); client.sendRawEmail(rawEmailRequest); System.out.println("Email sent!"); // Display an error if something goes wrong. } catch (Exception ex) { System.out.println("Email Failed"); System.err.println("Error message: " + ex.getMessage()); ex.printStackTrace(); } } } | cs |
예제코드이지만 코드가 너무 길고 가독성이 좋지 못한데요. Spring Mail 라이브러리에서는 이러한 코드를 더욱 쉽게 사용할 수 있게 제공하는데 좀 더 자세히 알아보겠습니다.
예제코드
1 2 3 4 | dependencies { implementation 'org.springframework.boot:spring-boot-starter-mail' implementation 'com.amazonaws:aws-java-sdk-ses:1.12.408' } | cs |
spring-boot-starter-mail, aws ses 두 라이브러리를 추가해줍니다.
AWS SES 공식 문서에서 제공된 예제코드는 MimeBodyPort, MimeMultiPart, FileDataSource 클래스들을 직접 다 작성했어야 했는데 org.springframework.mail.javamail.MimeMessageHelper 클래스를 사용하면 위 작업들을 더욱 깔끔하게 작성할 수 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | @SpringBootApplication public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Bean public AmazonSimpleEmailService amazonSimpleEmailService() { return AmazonSimpleEmailServiceClientBuilder.standard() .withRegion(Regions.AP_NORTHEAST_2) .withCredentials(DefaultAWSCredentialsProviderChain.getInstance()) .build(); } @Bean public ApplicationRunner applicationRunner(AmazonSimpleEmailService amazonSimpleEmailService) { return args -> { try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { Session session = Session.getDefaultInstance(new Properties()); MimeMessage message = new MimeMessage(session); MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true, StandardCharsets.UTF_8.name()); mimeMessageHelper.setFrom("발신자 이메일 주소"); mimeMessageHelper.setTo("수신자 이메일 주소"); mimeMessageHelper.setSubject("Hello, World!"); mimeMessageHelper.setText("<h1>Hello, World!</h1>", true); mimeMessageHelper.addAttachment("maple.png", new ClassPathResource("maple.png")); message.writeTo(outputStream); RawMessage rawMessage = new RawMessage(ByteBuffer.wrap(outputStream.toByteArray())); SendRawEmailRequest rawEmailRequest = new SendRawEmailRequest(rawMessage); amazonSimpleEmailService.sendRawEmail(rawEmailRequest); } }; } } | cs |
AWS SES 공식 문서에서 제공된 예제코드와 비교했을 때 확실히 코드 라인이 짧아졌고 가독성도 좋아졌습니다.
이 코드에 대해 간단히 몇 개만 설명드리겠습니다.
MimeMessageHelper 클래스에는 여러 생성자가 있는데 위 사진에 대해 간단히 설명하겠습니다.
첫 번째 인자엔 MimeMessage 인스턴스를 전달하시면 됩니다.
두 번째 인자엔 해당 발송에 Multipart 전송 여부를 나타냅니다. Multipart 전송이면 true를 전달하시면 됩니다.
세 번째 인자엔 인코딩을 지정해서 전달하시면 됩니다.
setText 메서드는 이메일 발송 시 본문에 들어갈 데이터를 세팅해주는 부분입니다.
첫 번째 인자엔 메세지 본문 내용을 전달하시면 됩니다.
두 번째 인자엔 메세지 본문 내용이 HTML 형식이면 true를 전달하시면 됩니다. (기본값은 false입니다.)
Multipart 전송일 경우 위 메서드를 사용하시면 됩니다.
첫 번째 인자엔 파일명을 전달하시면 됩니다.
두 번째 인자엔 InputStreamSource 구현 클래스를 전달하시면 됩니다.
InputStreamSource는 인터페이스고 spring.core.io 패키지에서 제공하는 InputStream의 최상위 인터페이스입니다.
Resource 인터페이스와 MultipartFile 인터페이스가 이 인터페이스를 상속하고 있습니다.
만일 사용자가 서버에 파일을 전송할 경우 서버에서는 MultipartFile 타입으로 받을 수 있는데요.
받은 데이터를 그대로 addAttachment 메서드에 전달하시면 됩니다.
메일발송
메세지 본문과 첨부파일이 정상적으로 발송되었습니다.