📄 mimemessageutil.java
字号:
/**************************************************************** * Licensed to the Apache Software Foundation (ASF) under one * * or more contributor license agreements. See the NOTICE file * * distributed with this work for additional information * * regarding copyright ownership. The ASF licenses this file * * to you under the Apache License, Version 2.0 (the * * "License"); you may not use this file except in compliance * * with the License. You may obtain a copy of the License at * * * * http://www.apache.org/licenses/LICENSE-2.0 * * * * Unless required by applicable law or agreed to in writing, * * software distributed under the License is distributed on an * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * ****************************************************************/package org.apache.james.core;import org.apache.james.util.InternetPrintWriter;import org.apache.james.util.io.IOUtil;import javax.activation.UnsupportedDataTypeException;import javax.mail.MessagingException;import javax.mail.internet.MimeMessage;import javax.mail.internet.MimeUtility;import java.io.BufferedWriter;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.OutputStreamWriter;import java.io.PrintWriter;import java.util.Enumeration;/** * Utility class to provide optimized write methods for the various MimeMessage * implementations. */public class MimeMessageUtil { /** * Convenience method to take any MimeMessage and write the headers and body to two * different output streams */ public static void writeTo(MimeMessage message, OutputStream headerOs, OutputStream bodyOs) throws IOException, MessagingException { writeTo(message, headerOs, bodyOs, null); } /** * Convenience method to take any MimeMessage and write the headers and body to two * different output streams, with an ignore list */ public static void writeTo(MimeMessage message, OutputStream headerOs, OutputStream bodyOs, String[] ignoreList) throws IOException, MessagingException { MimeMessage testMessage = message; if (message instanceof MimeMessageCopyOnWriteProxy) { MimeMessageCopyOnWriteProxy wr = (MimeMessageCopyOnWriteProxy) message; testMessage = wr.getWrappedMessage(); } if (testMessage instanceof MimeMessageWrapper) { MimeMessageWrapper wrapper = (MimeMessageWrapper)testMessage; if (!wrapper.isModified()) { wrapper.writeTo(headerOs, bodyOs, ignoreList); return; } } writeToInternal(message, headerOs, bodyOs, ignoreList); } /** * @param message * @param headerOs * @param bodyOs * @param ignoreList * @throws MessagingException * @throws IOException * @throws UnsupportedDataTypeException */ public static void writeToInternal(MimeMessage message, OutputStream headerOs, OutputStream bodyOs, String[] ignoreList) throws MessagingException, IOException, UnsupportedDataTypeException { if(message.getMessageID() == null) { message.saveChanges(); } writeHeadersTo(message, headerOs, ignoreList); // Write the body to the output stream writeMessageBodyTo(message, bodyOs); } public static void writeMessageBodyTo(MimeMessage message, OutputStream bodyOs) throws IOException, UnsupportedDataTypeException, MessagingException { OutputStream bos; InputStream bis; try { // Get the message as a stream. This will encode // objects as necessary, and we have some input from // decoding an re-encoding the stream. I'd prefer the // raw stream, but see bos = MimeUtility.encode(bodyOs, message.getEncoding()); bis = message.getInputStream(); } catch(UnsupportedDataTypeException udte) { /* If we get an UnsupportedDataTypeException try using * the raw input stream as a "best attempt" at rendering * a message. * * WARNING: JavaMail v1.3 getRawInputStream() returns * INVALID (unchanged) content for a changed message. * getInputStream() works properly, but in this case * has failed due to a missing DataHandler. * * MimeMessage.getRawInputStream() may throw a "no * content" MessagingException. In JavaMail v1.3, when * you initially create a message using MimeMessage * APIs, there is no raw content available. * getInputStream() works, but getRawInputStream() * throws an exception. If we catch that exception, * throw the UDTE. It should mean that someone has * locally constructed a message part for which JavaMail * doesn't have a DataHandler. */ try { bis = message.getRawInputStream(); bos = bodyOs; } catch(javax.mail.MessagingException _) { throw udte; } } catch(javax.mail.MessagingException me) { /* This could be another kind of MessagingException * thrown by MimeMessage.getInputStream(), such as a * javax.mail.internet.ParseException. * * The ParseException is precisely one of the reasons * why the getRawInputStream() method exists, so that we * can continue to stream the content, even if we cannot * handle it. Again, if we get an exception, we throw * the one that caused us to call getRawInputStream(). */ try { bis = message.getRawInputStream(); bos = bodyOs; } catch(javax.mail.MessagingException _) { throw me; } } try { copyStream(bis, bos); } finally { IOUtil.shutdownStream(bis); } } /** * Convenience method to copy streams */ public static void copyStream(InputStream in, OutputStream out) throws IOException { // TODO: This is really a bad way to do this sort of thing. A shared buffer to // allow simultaneous read/writes would be a substantial improvement byte[] block = new byte[1024]; int read = 0; while ((read = in.read(block)) > -1) { out.write(block, 0, read); } out.flush(); } /** * Write the message headers to the given outputstream * * @param message * @param headerOs * @param ignoreList * @throws MessagingException */ private static void writeHeadersTo(MimeMessage message, OutputStream headerOs, String[] ignoreList) throws MessagingException { //Write the headers (minus ignored ones) Enumeration headers = message.getNonMatchingHeaderLines(ignoreList); writeHeadersTo(headers, headerOs); } /** * Write the message headers to the given outputstream * * @param message * @param headerOs * @param ignoreList * @throws MessagingException */ public static void writeHeadersTo(Enumeration headers, OutputStream headerOs) throws MessagingException { PrintWriter hos = new InternetPrintWriter(new BufferedWriter(new OutputStreamWriter(headerOs), 512), true); while (headers.hasMoreElements()) { hos.println((String)headers.nextElement()); } // Print header/data separator hos.println(); hos.flush(); } /** * @param message * @param ignoreList * @return * @throws MessagingException */ public static InputStream getHeadersInputStream(MimeMessage message, String[] ignoreList) throws MessagingException { ByteArrayOutputStream bo = new ByteArrayOutputStream(); writeHeadersTo(message,bo,ignoreList); return new ByteArrayInputStream(bo.toByteArray()); } /** * Slow method to calculate the exact size of a message! */ private static final class SizeCalculatorOutputStream extends OutputStream { long size = 0; public void write(int arg0) throws IOException { size++; } public long getSize() { return size; } public void write(byte[] arg0, int arg1, int arg2) throws IOException { size += arg2; } public void write(byte[] arg0) throws IOException { size += arg0.length; } } /** * @return size of full message including headers * * @throws MessagingException if a problem occours while computing the message size */ public static long getMessageSize(MimeMessage message) throws MessagingException { //If we have a MimeMessageWrapper, then we can ask it for just the // message size and skip calculating it long size = -1; if (message instanceof MimeMessageWrapper) { MimeMessageWrapper wrapper = (MimeMessageWrapper) message; size = wrapper.getMessageSize(); } else if (message instanceof MimeMessageCopyOnWriteProxy) { MimeMessageCopyOnWriteProxy wrapper = (MimeMessageCopyOnWriteProxy) message; size = wrapper.getMessageSize(); } if (size == -1) { size = calculateMessageSize(message); } return size; } /** * @param message * @return the calculated size * @throws MessagingException */ public static long calculateMessageSize(MimeMessage message) throws MessagingException { long size; //SK: Should probably eventually store this as a locally // maintained value (so we don't have to load and reparse // messages each time). size = message.getSize(); if (size != -1) { Enumeration e = message.getAllHeaderLines(); if (e.hasMoreElements()) { size += 2; } while (e.hasMoreElements()) { // add 2 bytes for the CRLF size += ((String) e.nextElement()).length()+2; } } if (size == -1) { SizeCalculatorOutputStream out = new SizeCalculatorOutputStream(); try { message.writeTo(out); } catch (IOException e) { // should never happen as SizeCalculator does not actually throw IOExceptions. throw new MessagingException("IOException wrapped by getMessageSize",e); } size = out.getSize(); } return size; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -