*/
public long appendMessage(final InputStream msgIn, Date internalDate,
final MailboxSession mailboxSession,final boolean isRecent, final Flags flagsToBeSet)
throws MailboxException {
File file = null;
SharedFileInputStream tmpMsgIn = null;
try {
// Create a temporary file and copy the message to it. We will work with the file as
// source for the InputStream
file = File.createTempFile("imap", ".msg");
FileOutputStream out = new FileOutputStream(file);
byte[] buf = new byte[1024];
int i = 0;
while ((i = msgIn.read(buf)) != -1) {
out.write(buf, 0, i);
}
out.flush();
out.close();
tmpMsgIn = new SharedFileInputStream(file);
final int size = tmpMsgIn.available();
final int bodyStartOctet = bodyStartOctet(tmpMsgIn);
// Disable line length... This should be handled by the smtp server component and not the parser itself
// https://issues.apache.org/jira/browse/IMAP-122
MimeEntityConfig config = new MimeEntityConfig();
config.setMaximalBodyDescriptor(true);
config.setMaxLineLen(-1);
final ConfigurableMimeTokenStream parser = new ConfigurableMimeTokenStream(config);
parser.setRecursionMode(MimeTokenStream.M_NO_RECURSE);
parser.parse(tmpMsgIn.newStream(0, -1));
final List<Header> headers = new ArrayList<Header>();
int lineNumber = 0;
int next = parser.next();
while (next != MimeTokenStream.T_BODY
&& next != MimeTokenStream.T_END_OF_STREAM
&& next != MimeTokenStream.T_START_MULTIPART) {
if (next == MimeTokenStream.T_FIELD) {
String fieldValue = parser.getField().getBody();
if (fieldValue.endsWith("\r\f")) {
fieldValue = fieldValue.substring(0,fieldValue.length() - 2);
}
if (fieldValue.startsWith(" ")) {
fieldValue = fieldValue.substring(1);
}
final Header header
= createHeader(++lineNumber, parser.getField().getName(),
fieldValue);
headers.add(header);
}
next = parser.next();
}
final MaximalBodyDescriptor descriptor = (MaximalBodyDescriptor) parser.getBodyDescriptor();
final PropertyBuilder propertyBuilder = new PropertyBuilder();
final String mediaType;
final String mediaTypeFromHeader = descriptor.getMediaType();
final String subType;
if (mediaTypeFromHeader == null) {
mediaType = "text";
subType = "plain";
} else {
mediaType = mediaTypeFromHeader;
subType = descriptor.getSubType();
}
propertyBuilder.setMediaType(mediaType);
propertyBuilder.setSubType(subType);
propertyBuilder.setContentID(descriptor.getContentId());
propertyBuilder.setContentDescription(descriptor.getContentDescription());
propertyBuilder.setContentLocation(descriptor.getContentLocation());
propertyBuilder.setContentMD5(descriptor.getContentMD5Raw());
propertyBuilder.setContentTransferEncoding(descriptor.getTransferEncoding());
propertyBuilder.setContentLanguage(descriptor.getContentLanguage());
propertyBuilder.setContentDispositionType(descriptor.getContentDispositionType());
propertyBuilder.setContentDispositionParameters(descriptor.getContentDispositionParameters());
propertyBuilder.setContentTypeParameters(descriptor.getContentTypeParameters());
// Add missing types
final String codeset = descriptor.getCharset();
if (codeset == null) {
if ("TEXT".equalsIgnoreCase(mediaType)) {
propertyBuilder.setCharset("us-ascii");
}
} else {
propertyBuilder.setCharset(codeset);
}
final String boundary = descriptor.getBoundary();
if (boundary != null) {
propertyBuilder.setBoundary(boundary);
}
if ("text".equalsIgnoreCase(mediaType)) {
final CountingInputStream bodyStream = new CountingInputStream(parser.getInputStream());
bodyStream.readAll();
long lines = bodyStream.getLineCount();
next = parser.next();
if (next == MimeTokenStream.T_EPILOGUE) {
final CountingInputStream epilogueStream = new CountingInputStream(parser.getInputStream());
epilogueStream.readAll();
lines+=epilogueStream.getLineCount();
}
propertyBuilder.setTextualLineCount(lines);
}
final Flags flags;
if (flagsToBeSet == null) {
flags = new Flags();
} else {
flags = flagsToBeSet;
// Check if we need to trim the flags
trimFlags(flags, mailboxSession);
}
if (isRecent) {
flags.add(Flags.Flag.RECENT);
}
if (internalDate == null) {
internalDate = new Date();
}
long nextUid = uidProvider.nextUid(mailboxSession, getMailboxEntity());
final Message<Id> message = createMessage(nextUid, internalDate, size, bodyStartOctet, tmpMsgIn.newStream(0, -1), flags, headers, propertyBuilder);
long uid = appendMessageToStore(message, mailboxSession);
Map<Long, MessageMetaData> uids = new HashMap<Long, MessageMetaData>();
uids.put(uid, new SimpleMessageMetaData(uid, flags, size, internalDate));
dispatcher.added(mailboxSession, uids, new StoreMailboxPath<Id>(getMailboxEntity()));
return uid;
} catch (IOException e) {
throw new MailboxException("Unable to parse message", e);
} catch (MimeException e) {
throw new MailboxException("Unable to parse message", e);
} catch (MailboxException e) {
throw new MailboxException("Unable to parse message", e);
} finally {
if (tmpMsgIn != null) {
try {
tmpMsgIn.close();
} catch (IOException e) {
// ignore on close
}
}
// delete the temporary file if one was specified