Javamail 에서 첨부파일 붙이는 방법에 대해서
1. 한글 파일명 처리방안
파일이름이 길고, 파일이름에 한글이 포함된 파일을 첨부할 때, 다음과 같이 하면 Gmail 과 유사하게 된다.
Gmail 과 비교하면 1 줄의 길이가 조금 더 짧다.
File attach = new File("첨부파일첨부파일첨부파일첨부파일.pdf"); Multipart multipart = new MimeMultipart("mixed"); MimeBodyPart part = new MimeBodyPart(); part.attachFile(attach); String charset = java.nio.charset.StandardCharsets.UTF_8.name(); String base64EncodedFileName = MimeUtility.encodeText(attach.getName(), charset, "B"); base64EncodedFileName = base64EncodedFileName.replace("?= =?" + charset + "?B?", "?=\r\n\t=?" + charset + "?B?"); String contentType = request.getServletContext().getMimeType(attach.getName()) + ";\r\n"; contentType += "\t"; contentType += "name=\"" + base64EncodedFileName + "\""; part.setHeader("Content-Type", contentType); String contentDisposition = part.ATTACHMENT + ";\r\n"; contentDisposition += "\t"; contentDisposition += "filename=\"" + base64EncodedFileName + "\""; part.setHeader("Content-Disposition", contentDisposition); multipart.addBodyPart(part);
결과는 다음과 같다.
Content-Type: application/octet-stream; name="=?UTF-8?B?7LKo67aA7YyM7J287LKo67aA7YyM7J287LKo67aA?= =?UTF-8?B?7YyM7J287LKo67aA7YyM7J28LnBkZg==?="; Content-Disposition: attachment; filename="=?UTF-8?B?7LKo67aA7YyM7J287LKo67aA7YyM7J287LKo67aA?= =?UTF-8?B?7YyM7J287LKo67aA7YyM7J28LnBkZg==?="
Content-Type 과 Content-Disposition 헤더를 프로그램적으로 처리했는데, 그렇게 하지 않으면 legacy 에서 장애가 보고되거나, name, filename 항목에 이상한 값이 들어간다.
Javamail API 의 한글 문제는 legacy 호환성, 비표준 지원, 버그 중 하나로 보이는데, 명백한 버그는 Jakarta Mail API 에서 개선되기를 기대하고 있다.
2. 삽질의 기록
파일이름과 관련해서 프로그램적으로 아무것도 하지 않으면, Content-Type 의 name 항목은 "name*=UTF-8''" 과 같은 식이고, Content-Disposition 의 filename 항목은 filename*=UTF-8'' 과 같은 식인데, legacy 시스템에서 파일이름이 깨지는 사례가 보고된 적이 있다.
legacy 시스템에서 "UTF-8''" 를 처리하지 못할 수도 있고, 76 제한을 넘기기 때문에, 수신 쪽에서 이메일을 받을 때는 자동 줄바꿈이 된 상태일 수도 있다.
MimeBodyPart.setFileName(MimeUtility.encodeText(attach.getName())) 과 같이 하면, 다음과 같이 된다.
Content-Type: application/octet-stream; name*0="=?UTF-8?B?7LKo67aA7YyM7J287LKo67aA7YyM7J287LKo67aA?= =?UTF-8?B?7"; name*1="YyM7J287LKo67aA7YyM7J28LnBkZg==?="; Content-Disposition: attachment; filename*0="=?UTF-8?B?7LKo67aA7YyM7J287LKo67aA7YyM7J287LKo67aA?= =?UTF-8"; filename*1="?B?7YyM7J287LKo67aA7YyM7J28LnBkZg==?="
System.setProperty("mail.mime.encodefilename", "true");
인 경우
다음과 같이 된다.
Content-Type: application/octet-stream; name="=?UTF-8?B?7LKo67aA7YyM7J287LKo67aA7YyM7J287LKo67aA?= =?UTF-8?B?7YyM7J287LKo67aA7YyM7J28LnBkZg==?="; Content-Disposition: attachment; filename*0="=?UTF-8?B?7LKo67aA7YyM7J287LKo67aA7YyM7J287LKo67aA?= =?UTF-8"; filename*1="?B?7YyM7J287LKo67aA7YyM7J28LnBkZg==?="
name 은 정상이지만, filename 항목이 문제가 있다.
이건 버그라고 생각하고 있다.