이슈
유지보수하는 어플리케이션에서 메일서버 API를 사용하고 있었는데 어느날부터 메일 제목이 깨져서 발송되는 문제가 발생했다. 이리저리 삽질 끝에 문제를 해결했는데 도움이 될까 남겨본다.
분석 발송된 메일의 제목을 확인해보니 아래와 같이 나왔다 1 =?UTF-8?B?7TAGM6Iqk5Yq2OSDHsydvOyeheuLuhC4=
SMTP의 subject format은 다음과 같다
1 =?[charset]?[인코딩타입]?[인코딩된 제목]?=
왜 디코딩이 안됐을까… 하고 한참 보다가 뒤에 물음표 빠진것 발견 ^^
2. eml Test 왜 빠진걸까? 일단 eml 파일을 만들어 테스트 해봤다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 public static void main (String[] args) { ImMessage message = null ; try { Properties props = new Properties(); Session session = Session.getDefaultInstance(props); message = new ImMessage( session ); message.setCharset("utf-8" ); message.setFrom("" , "timpac61@gmail.com" , "utf-8" ); message.setSubjectEncode("테스트 메일입니다." , "utf-8" ); message.setPriority(3 ); message.setHtml("테스트" ); message.setRecipientsEx(javax.mail.Message.RecipientType.TO, "조영덕" , "utf-8" ); message.makeMimeFile("E:\\test.eml" ); }catch (Exception ex){ ex.printStackTrace(); } }
만들어진 eml 파일의 결과는 아래와 같다
1 2 3 4 5 6 7 From: <timpac61@gmail.com> Subject: =?UTF-8?B?7YWM7Iqk7Yq4IOuplOydvOyeheuLiOuLpC4= ?= Mime-Version: 1.0 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 X-Priority: 3
Subject의 값이 ?(물음표) 앞에서 개행된 것을 확인할 수 있다. 아하~ 그래서 디코딩을 못했구만.. 근데 어디서 바뀐거지? ㅡ.ㅡ
3. BASE64 Encoding Test 메일 API lib에서 subject를 만들어주는 부분을 찾아서 테스트 코드로 만들었다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 public void subjectEncodingTest () { String subject = "테스트 메일입니다." ; try { byte [] result = Base64.encodeBase64(subject.getBytes("UTF-8" ), true ); String sTemp = new String(result); System.out.println("base64 encoding: " + sTemp); String sRet = "" ; String[] arrResult = sTemp.split("\r\n" ); for (int i = 0 ; i < arrResult.length; ++i) if (i != 0 ) sRet = sRet + "\r\n\t=?UTF-8?B?" + arrResult[i] + "?=" ; else sRet = sRet + "=?UTF-8?B?" + arrResult[i] + "?=" ; System.out.println("subject format : " + sRet); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } }
대충 제목을 BASE64로 인코딩한후 SMTP foramt에 맞게 만들어주는 코드다. 결과는 아래와 같이 나왔다
1 2 3 4 base64 encoding: 7YWM7Iqk7Yq4IOuplOydvOyeheuLiOuLpC4= subject format: =?UTF-8?B?7YWM7Iqk7Yq4IOuplOydvOyeheuLiOuLpC4= ?=
역시나 물음표 앞이 개행됨 sTemp.split(“\r\n”); 구문 때문에 여기서 문제가 있을거 같다고 예상했으나… 아니였고 apache.commons.codec.Base64 클래스에서 인코딩 변환 중 개행문자가 붙어나왔다 Why?? 우리의 아파치가 그럴 리 없어~ (무한신뢰)
4. Check Library 라이브러리 버전이나 충돌이 의심되어 클래스 로드를 확인해봤다
1 2 3 4 public void test () { String path = org.apache.commons.codec.binary.Base64.class.getProtectionDomain().getCodeSource().getLocation().getPath(); System.out.println("Base64:" + path); }
확인결과 ~~~~~~~ 두둥~! 아파치 Commons.codec.jar 가 아닌 다른 jar 파일을 로드하고 있는걸 확인했다. 결제관련 라이브러리에 포함된 Base64 클래스였다.
잡았다 요놈~
해결 해당 결제 라이브러리 패키지에서 apache.commons.codec을 삭제하고 리패키징한 후 배포하니 깔끔하게 해결되었다. ^^