/*
* Copyright (C) 2012 Works Applications Co., Ltd.
* http://www.worksap.co.jp/
*
* Licensed under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
*/
package jp.co.worksap.message.parser;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import javax.mail.BodyPart;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.internet.MimeBodyPart;
import jp.co.worksap.message.decoder.HeaderDecoder;
import jp.co.worksap.message.util.StringValidator;
import jp.co.worksap.message.wrapper.CharsetGuesser;
import com.google.common.base.Strings;
public class AttachedFileParser {
private static final String breakLine = "\r\n";
private static final String NO_FILE_NAME = "no file name";
private final Message message;
public AttachedFileParser(Message message) {
this.message = message;
}
public String decodeFileName(BodyPart body) throws MessagingException {
StringBuilder fileHeader = new StringBuilder();
if (!(body instanceof MimeBodyPart)) {
return "";
}
Enumeration<?> enums = ((MimeBodyPart) body)
.getNonMatchingHeaderLines(null);
while (enums.hasMoreElements()) {
Object o = enums.nextElement();
if (!(o instanceof String)) {
continue;
}
String temp = ((String) o).toLowerCase();
if (temp.contains("multipart/")) {
Object content = null;
try {
content = body.getContent();
} catch (IOException e) {
throw new MessagingException(
"Can not get the mail content", e);
}
if (content instanceof BodyPart) {
try {
return decodeFileName((BodyPart) body.getContent());
} catch (IOException e) {
throw new MessagingException(
"Can not decode the file name", e);
}
}
} else if (temp.contains("message/")) {
try {
if (Strings.isNullOrEmpty(body.getFileName())) {
return NO_FILE_NAME;
}
} catch (MessagingException e) {
throw e;
}
}
fileHeader.append(o);
fileHeader.append(breakLine);
}
HeaderDecoder decoder = new HeaderDecoder();
String fileName = decoder.decodeFileName(fileHeader.toString());
return fileName;
}
public void fixFileName(Multipart mp) throws MessagingException,
IOException {
for (int i = 0; i < mp.getCount(); i++) {
BodyPart body = mp.getBodyPart(i);
Object bodyContent = getBodyContent(body);
if (body.getContent() instanceof Multipart) {
fixFileName((Multipart) bodyContent);
}
String fileName = decodeFileName(body);
if (fileName == null || fileName.equals("")) {
continue;
}
if (!StringValidator.isValid(fileName)) {
CharsetGuesser guesser = new CharsetGuesser();
String charset = guesser.guessCharset(message.getAllHeaders(),
new ByteArrayInputStream(fileName.getBytes()));
if (!charset.isEmpty()) {
try {
fileName = new String(fileName.getBytes(), charset);
} catch (UnsupportedEncodingException e) {
}
}
}
try {
body.setFileName(fileName);
} catch (MessagingException e) {
// retry to set file name.
// the file name rarely have one-side quotation; "hoge.txt , so
// check it.
if (!fileName.startsWith("\"")) {
fileName = "\"" + fileName;
}
if (!fileName.endsWith("\"")) {
fileName += "\"";
}
body.setHeader("Content-Disposition", "attachment; filename="
+ fileName);
}
mp.removeBodyPart(i);
mp.addBodyPart(body, i);
}
}
private Object getBodyContent(BodyPart p) throws IOException,
MessagingException {
try {
return p.getContent();
} catch (IOException e) {
if (e.getMessage().equals("Unknown encoding: 8-bit")) {
p.setHeader("Content-Transfer-Encoding", "7bit");
return p.getContent();
}
throw e;
}
}
}