*/
public long appendMessage(final InputStream msgIn, Date internalDate, final MailboxSession mailboxSession, final boolean isRecent, final Flags flagsToBeSet) throws MailboxException {
File file = null;
TeeInputStream tmpMsgIn = null;
BodyOffsetInputStream bIn = null;
FileOutputStream out = null;
SharedFileInputStream contentIn = null;
if (!isWriteable(mailboxSession)) {
throw new ReadOnlyException(new StoreMailboxPath<Id>(getMailboxEntity()), mailboxSession.getPathDelimiter());
}
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");
out = new FileOutputStream(file);
tmpMsgIn = new TeeInputStream(msgIn, out);
bIn = new BodyOffsetInputStream(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
MimeConfig config = new MimeConfig();
config.setMaxLineLen(-1);
config.setMaxHeaderLen(-1);
final MimeTokenStream parser = new MimeTokenStream(config, new DefaultBodyDescriptorBuilder());
parser.setRecursionMode(RecursionMode.M_NO_RECURSE);
parser.parse(bIn);
final HeaderImpl header = new HeaderImpl();
EntityState next = parser.next();
while (next != EntityState.T_BODY && next != EntityState.T_END_OF_STREAM && next != EntityState.T_START_MULTIPART) {
if (next == EntityState.T_FIELD) {
header.addField(parser.getField());
}
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();
bodyStream.close();
next = parser.next();
if (next == EntityState.T_EPILOGUE) {
final CountingInputStream epilogueStream = new CountingInputStream(parser.getInputStream());
epilogueStream.readAll();
lines += epilogueStream.getLineCount();
epilogueStream.close();
}
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();
}
byte[] discard = new byte[4096];
while (tmpMsgIn.read(discard) != -1) {
// consume the rest of the stream so everything get copied to
// the file now
// via the TeeInputStream
}
int bodyStartOctet = (int) bIn.getBodyStartOffset();
if (bodyStartOctet == -1) {
bodyStartOctet = 0;
}
contentIn = new SharedFileInputStream(file);
final int size = (int) file.length();