Microsoft 社는 2022년 6월 15일 Internet Explorer 11의 지원을 종료했습니다.

Java 와 인코딩(webmua의 eml ~ mbox 파일 처리를 중심으로)

제목

Java 와 인코딩(webmua의 mbox 파일 처리를 중심으로)

1. mbox 파일은 iso-8859-1 로 읽어야 한다.

encoding 을 알지 못하는 파일을 String으로 읽었다가 다시 byte array 를 거쳐 InputStream으로 변경하여 MimeMessage 에 전달할 때는 iso-8859-1 로 읽은 것을 전달해야 한다.

MimeMessage 에서의 처리는 MailParserProcessorImpl.java 파일을 참조한다.

eml ~ mbox 파일내의 한글은 대부분 ms949 혹은 utf-8 로 encoding 이 사용된다. eml 파일은 1개의 encoding 만 사용될 가능성이 높지만, mbox 나 Thunderbird mbox 는 1개의 파일 내에 여러 개의 encoding이 사용될 가능성이 높다.

최근에는 utf-8 이 일반적이지만, ms949 가 빈번하던 시절도 있었다. 이론적으로 다른 한글 인코딩이 사용될 수도 있을 것이고, 드물지만 utf-8 이나 ms949 호환도 아닌 encoding 이 발견되는 경우도 있다.

2. 어떻게 iso-8859-1 로 읽어야 하나?

Java 는 encoding 을 지정하는 방법이 숨겨져 있는 것처럼 보이지만, 이는 널리 사용되는 메소드들이 시스템의 기본값을 사용하기 때문이다.

전체 소스는 MailMigrationProcessorImpl.java 파일을 참조한다.

2.1. 시스템 기본값

시스템의 기본값을 확인하기 위해서는 다음과 같이 한다.

System.getProperty("file.encoding");

이 값은 Java 프로그램을 실행시킬 때 "-Dfile.encoding=iso-8859-1" 와 같은 명령행 파라미터을 추가해서 지정할 수 있고, 이것이 누락된 경우 Java 프로그램 실행 당시의 locale 을 사용한다.

Linux/Unix 계열에서 locale 을 확인하기 위한 명령어는 다음과 같다.

locale

영향을 미치는 것은 LANG 이라는 항목이고, LANG=C 는 file.encoding=iso-8859-1 이다.

Graha ~ 그 응용프로그램과 같이 WAS 에서 구동되는 프로그램은 시스템 기본값을 변경하지 않고, 프로그램내에서 처리하는 것이 원칙이다.

2.3. eml 파일

eml 파일은 다음과 같이 특별한 처리가 없어도 된다.

FileInputStream fis = new FileInputStream(file);
MimeMessage mime = new MimeMessage(null, fis);
fis.close();

2.4. mbox 나 Thunderbird mbox 파일

mbox 나 Thunderbird mbox 파일은 여러 개의 이메일로 구성되기 때문에, 이메일을 1개씩 읽어 처리해야 한다.

이메일은 "From - " 으로 시작(Thunderbird mbox) 하거나 "From " 으로 시작(mbox) 하므로, readLine 메소드를 지원하는 BufferedReader 로 처리해야 한다.

BufferedReader 는 charset 을 파라미터로 받는 생성자가 없지만, 생성자의 파라미터인 Reader 를 구현한 InputStreamReader 가 charset 을 파라미터로 받는 생성자를 지원한다.

실제 코드는 예외처리와 다른 처리를 위해 복잡하겠지만, 요약하면 다음과 같다.

InputStreamReader isr = new InputStreamReader(is, StandardCharsets.ISO_8859_1);
BufferedReader in = new BufferedReader(isr);
String line = null;
while ((line = in.readLine()) != null) {
}
in.close();
isr.close();

이걸로 끝은 아니다.

MimeMessage 에 공급할 InputStream 으로 만들기 위해, String 으로 읽은 것을 다시 byte array 로 변경해야 하는데, 다음과 같이 charset을 지정해야 한다.

byte[] buffer = line.getBytes(StandardCharsets.ISO_8859_1);

2.5. zip 파일에서 파일이름

zip 파일에서는 파일이름을 iso-8859-1 로 가져와야 하는데, 다음과 같이 ZipInputStream 의 생성자에 charset 을 공급한다.

FileInputStream fis = new FileInputStream(fileName);
ZipInputStream zis = new ZipInputStream(fis, StandardCharsets.ISO_8859_1);
while((ZipEntry entry = zis.getNextEntry()) != null) {
String fileName = entry.getName();
}

그렇지 않으면 예외가 발생할 가능성이 높아진다.

제목

첨부파일