Index: core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/AbstractGeneralMailbox.java
===================================================================
--- core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/AbstractGeneralMailbox.java	(revision 567160)
+++ core-library/src/main/java/org/apache/james/mailboxmanager/mailbox/AbstractGeneralMailbox.java	(working copy)
@@ -19,11 +19,15 @@
 
 package org.apache.james.mailboxmanager.mailbox;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.Iterator;
 
+import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
 import org.apache.james.mailboxmanager.MailboxManagerException;
@@ -31,41 +35,60 @@
 import org.apache.james.mailboxmanager.impl.GeneralMessageSetImpl;
 import org.apache.james.mailboxmanager.util.AbstractLogFactoryAware;
 
-public abstract class AbstractGeneralMailbox extends AbstractLogFactoryAware implements GeneralMailbox {
-    
-    public Collection list() throws MailboxManagerException {
-        MessageResult[] messageResult=getMessages(GeneralMessageSetImpl.all(), MessageResult.KEY);
-        Collection result=new ArrayList(messageResult.length);
-        for (int i = 0; i < messageResult.length; i++) {
-            result.add(messageResult[i].getKey());
-        }
-        return result;
-    }
+import com.sun.mail.util.CRLFOutputStream;
 
-    public void remove(String key) throws MailboxManagerException {
-        remove(GeneralMessageSetImpl.oneKey(key));
-    }
+public abstract class AbstractGeneralMailbox extends AbstractLogFactoryAware
+		implements GeneralMailbox {
 
-    public MimeMessage retrieve(String key) throws MailboxManagerException {
-        MessageResult[] result = getMessages(GeneralMessageSetImpl.oneKey(key),
-                MessageResult.MIME_MESSAGE);
-        if (result != null && result.length == 1) {
-            return result[0].getMimeMessage();
-        } else {
-            return null;
-        }
-    }
+	public Collection list() throws MailboxManagerException {
+		MessageResult[] messageResult = getMessages(
+				GeneralMessageSetImpl.all(), MessageResult.KEY);
+		Collection result = new ArrayList(messageResult.length);
+		for (int i = 0; i < messageResult.length; i++) {
+			result.add(messageResult[i].getKey());
+		}
+		return result;
+	}
 
-    public String store(MimeMessage message) throws MailboxManagerException {
-        MessageResult result=appendMessage(message, new Date(), MessageResult.KEY);
-        return result.getKey();
-    }
+	public void remove(String key) throws MailboxManagerException {
+		remove(GeneralMessageSetImpl.oneKey(key));
+	}
 
-    public String update(String key, MimeMessage message) throws MailboxManagerException {
-        MessageResult result=updateMessage(GeneralMessageSetImpl.oneKey(key),message, MessageResult.KEY);
-        return result.getKey();
-    }
-    
-    
+	public MimeMessage retrieve(String key) throws MailboxManagerException {
+		MessageResult[] result = getMessages(GeneralMessageSetImpl.oneKey(key),
+				MessageResult.MIME_MESSAGE);
+		if (result != null && result.length == 1) {
+			return result[0].getMimeMessage();
+		} else {
+			return null;
+		}
+	}
 
+	public String store(MimeMessage message) throws MailboxManagerException {
+		MessageResult result = appendMessage(message, new Date(),
+				MessageResult.KEY);
+		return result.getKey();
+	}
+
+	public String update(String key, MimeMessage message)
+			throws MailboxManagerException {
+		MessageResult result = updateMessage(GeneralMessageSetImpl.oneKey(key),
+				message, MessageResult.KEY);
+		return result.getKey();
+	}
+
+	protected static byte[] getByteBuffer(MimeMessage message) throws IOException, MessagingException {
+		InputStream is = message.getInputStream();
+
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		CRLFOutputStream crlf = new CRLFOutputStream(baos);
+		byte[] buf = new byte[4096];
+		int read;
+		while ((read = is.read(buf)) > 0) {
+			crlf.write(buf, 0, read);
+		}
+		is.close();
+		return baos.toByteArray();
+
+	}
 }
Index: core-library/src/main/java/org/apache/james/mailboxmanager/MessageResult.java
===================================================================
--- core-library/src/main/java/org/apache/james/mailboxmanager/MessageResult.java	(revision 567160)
+++ core-library/src/main/java/org/apache/james/mailboxmanager/MessageResult.java	(working copy)
@@ -20,10 +20,13 @@
 package org.apache.james.mailboxmanager;
 
 import java.util.Date;
+import java.util.Enumeration;
 
 import javax.mail.Flags;
+import javax.mail.MessagingException;
 import javax.mail.internet.MimeMessage;
 
+import org.apache.james.imapserver.ProtocolException;
 import org.apache.mailet.Mail;
 
 /**
@@ -88,13 +91,17 @@
     public static final int INTERNAL_DATE = 0x40;
 
     public static final int FLAGS = 0x80;
+    
+    public static final int HEADERS = 0x100;
 
-    int getIncludedResults();
+    public static final int ENVELOPE = 0x200;
 
-    boolean contains(int result);
+    //int getIncludedResults();
 
-    MimeMessage getMimeMessage();
+    //boolean contains(int result);
 
+    MimeMessage getMimeMessage() throws MailboxManagerException;
+
     long getUid();
 
     long getUidValidity();
@@ -125,10 +132,71 @@
      */
     Flags getFlags();
 
-    Mail getMail();
+    //Mail getMail();
 
     String getKey();
     
     int getSize();
 
+
+    /**
+     * return all header lines as an enumeration. In a non optimized version this should be equivalent to
+     *  getMimeMessage().getAllHeaderLines()
+     * 
+     * @return
+     * @throws MessagingException 
+     */
+    Enumeration getAllHeaderLines() throws MessagingException;
+
+    /**
+     * return all header lines as an enumeration. In a non optimized version this should be equivalent to
+     *  getMimeMessage().getNonMatchingHeaderLines(headers)
+     * 
+     * @return
+     * @throws MessagingException 
+     */
+    Enumeration getNonMatchingHeaderLines(String[] headers) throws MessagingException;
+
+    /**
+     * return the matching header lines as an enumeration. In a non optimized version this should be equivalent to
+     *  getMimeMessage().getMatchingHeaderLines(headers)
+     * 
+     * @return
+     * @throws MessagingException 
+     */
+    Enumeration getMatchingHeaderLines(String[] headers) throws MessagingException;
+    
+    /**
+     * Provides the Envelope structure information for this message. This is a parsed representation of the rfc-822 envelope information. This is not to be confused with the SMTP envelope!
+     *
+     * @return String satisfying envelope syntax in rfc 2060.
+     * @throws MessagingException 
+     */
+    String getEnvelope() throws MessagingException;
+
+    /**
+     * Provides the Body Structure information for this message. This is a parsed representtion of the MIME structure of the message.
+     *
+     * @return String satisfying body syntax in rfc 2060.
+     * @throws MessagingException 
+     */
+    public String getBodyStructure( boolean includeExtensions ) throws MessagingException;
+
+    /**
+     * returns the length of the MIME message as a byte array, when the content is supposed to contains just CRLF line endings.
+     * @return
+     * @throws MessagingException 
+     * @throws ProtocolException 
+     */
+    public int getMimeMessageSizeAsByteArray() throws ProtocolException, MessagingException;
+    
+    
+    /**
+     * appends the MIME message to this buffer, with correct CRLF line endings.
+     * @param buffer
+     * @throws MessagingException 
+     * @throws ProtocolException 
+     */
+    public void writeMimeMessage(StringBuffer buffer) throws ProtocolException, MessagingException;
+    
 }
Index: core-library/src/main/java/org/apache/james/mailboxmanager/impl/MessageResultImpl.java
===================================================================
--- core-library/src/main/java/org/apache/james/mailboxmanager/impl/MessageResultImpl.java	(revision 567160)
+++ core-library/src/main/java/org/apache/james/mailboxmanager/impl/MessageResultImpl.java	(working copy)
@@ -19,17 +19,27 @@
 
 package org.apache.james.mailboxmanager.impl;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.util.Date;
+import java.util.Enumeration;
 
 import javax.mail.Flags;
+import javax.mail.MessagingException;
 import javax.mail.Flags.Flag;
 import javax.mail.internet.MimeMessage;
 
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.imapserver.store.SimpleMessageAttributes;
+import org.apache.james.mailboxmanager.MailboxManagerException;
 import org.apache.james.mailboxmanager.MessageResult;
 import org.apache.mailet.Mail;
 
+import com.sun.mail.util.CRLFOutputStream;
+
 public class MessageResultImpl implements MessageResult {
     
+	private SimpleMessageAttributes msgAttributes;
     private MimeMessage mimeMessage;
     private long uid;
     private int msn;
@@ -37,7 +47,7 @@
     private int size;
     private Date internalDate;
     private String key;
-    
+    protected byte[] mimeMessageCache;
 
     public MessageResultImpl(long uid) {
         this.uid=uid;
@@ -51,7 +61,7 @@
         this.flags=flags;
     }
 
-    public MessageResultImpl(MessageResult origMr) {
+    public MessageResultImpl(MessageResult origMr) throws MailboxManagerException {
         this.uid=origMr.getUid();
         this.flags=origMr.getFlags();
         this.mimeMessage=origMr.getMimeMessage();
@@ -67,7 +77,7 @@
         return false;
     }
 
-    public MimeMessage getMimeMessage() {
+    public MimeMessage getMimeMessage() throws MailboxManagerException {
         return mimeMessage;
     }
 
@@ -184,4 +194,59 @@
         this.key=key;
     }
 
+    public Enumeration getAllHeaderLines() throws MessagingException {
+    	return mimeMessage.getAllHeaderLines();
+    }
+    
+    public Enumeration getMatchingHeaderLines(String[] names) throws MessagingException {
+    	return mimeMessage.getMatchingHeaderLines(names);
+    }
+    
+    public Enumeration getNonMatchingHeaderLines(String[] headers) throws MessagingException {
+    	return mimeMessage.getNonMatchingHeaderLines(headers);
+    }
+    
+    protected SimpleMessageAttributes getMsgAttributes() throws MessagingException {
+    	if (msgAttributes==null) {
+    		msgAttributes = new SimpleMessageAttributes(mimeMessage);
+    	}
+		return msgAttributes;
+	}
+    
+    // @Override
+    public String getEnvelope() throws MessagingException {
+    	return getMsgAttributes().getEnvelope();
+    }
+    
+    // @Override
+    public String getBodyStructure(boolean includeExtensions) throws MessagingException {
+    	return getMsgAttributes().getBodyStructure(includeExtensions);
+    }
+
+    byte[] getMimeMessageCache() throws ProtocolException, MessagingException {
+    	if (mimeMessageCache==null) {
+    		ByteArrayOutputStream bout = new ByteArrayOutputStream();
+			try {
+				mimeMessage.writeTo(new CRLFOutputStream(bout));
+				mimeMessageCache = bout.toByteArray();
+			} catch (IOException e) {
+				throw new ProtocolException("Error reading message source", e);
+			}
+    	}
+		return mimeMessageCache;
+	}
+    
+	public int getMimeMessageSizeAsByteArray() throws ProtocolException, MessagingException {
+		return getMimeMessageCache().length;
+	}
+
+	public void writeMimeMessage(StringBuffer response) throws ProtocolException, MessagingException {
+		byte[] buf = getMimeMessageCache();
+		for (int i=0;i<buf.length;i++) {
+			response.append((char) buf[i]);
+		}
+	}
+    
+	
+	
 }
Index: core-library/src/main/java/org/apache/james/mailboxmanager/impl/MessageResultWithHeaders.java
===================================================================
--- core-library/src/main/java/org/apache/james/mailboxmanager/impl/MessageResultWithHeaders.java	(revision 0)
+++ core-library/src/main/java/org/apache/james/mailboxmanager/impl/MessageResultWithHeaders.java	(revision 0)
@@ -0,0 +1,158 @@
+package org.apache.james.mailboxmanager.impl;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import javax.mail.Flags;
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+import javax.mail.util.SharedByteArrayInputStream;
+
+import org.apache.commons.collections.iterators.IteratorEnumeration;
+import org.apache.james.imapserver.ProtocolException;
+import org.apache.james.mailboxmanager.MailboxManagerException;
+import org.apache.james.mailboxmanager.MessageResult;
+
+/**
+ * This MessageResult implementation allows to store the message headers outside of the MIME message, 
+ * and explicitly manage it. The back end only have to fill with the addHeader method, the frontend will get all
+ * the necessary information.
+ * 
+ * @author zsombor
+ *
+ */
+public class MessageResultWithHeaders extends MessageResultImpl {
+
+	Map headerMap = new HashMap();
+
+	String envelope;
+	String bodyStructure;
+	String bodyStructureWithExtensions;
+	List headerLines = new ArrayList();
+	byte[] mimeMessageBody;
+	int headerListLength = 2; // this is for the separation between the header and the body
+	
+	
+	public MessageResultWithHeaders() {
+		super();
+	}
+
+	public MessageResultWithHeaders(long uid, Flags flags) {
+		super(uid, flags);
+	}
+
+	public MessageResultWithHeaders(long uid) {
+		super(uid);
+	}
+
+	public MessageResultWithHeaders(MessageResult origMr) throws MailboxManagerException {
+		super(origMr);
+	}
+
+	public void setEnvelope(String envelope) {
+		this.envelope = envelope;
+	}
+	
+	public void setBodyStructure(String bodyStructure) {
+		this.bodyStructure = bodyStructure;
+	}
+	
+	public void setBodyStructureWithExtensions(
+			String bodyStructureWithExtensions) {
+		this.bodyStructureWithExtensions = bodyStructureWithExtensions;
+	}
+	
+	public void addHeader(String name, String value) {
+		String line = name.trim()+": "+value;
+		headerMap.put(name, line);
+		headerLines.add(line);
+		// hmm ... I should think more about the lots of char-byte conversion in the process.
+		headerListLength += line.length() + 2;
+	}
+	
+	// @Override
+	public Enumeration getAllHeaderLines() throws MessagingException {
+		return new IteratorEnumeration(headerMap.values().iterator());
+	}
+	
+	// @Override
+	public Enumeration getMatchingHeaderLines(String[] names)
+			throws MessagingException {
+		// i hate to use vectors, but the Vector has a built in Enumeration
+		Vector result = new Vector();
+		for (int i=0;i<names.length;i++) {
+			Object line = headerMap.get(names[i]);
+			if (line!=null) {
+				result.add(line);
+			}
+		}
+		return result.elements();
+	}
+
+	//@Override
+	public Enumeration getNonMatchingHeaderLines(String[] headers)
+			throws MessagingException {
+		Set keys = new HashSet(headerMap.keySet());
+		for (int i=0;i<headers.length;i++) {
+			keys.remove(headers[i]);
+		}
+		Vector result = new Vector();
+		for (Iterator iter = keys.iterator(); iter.hasNext(); ) {
+			String key = (String) iter.next();
+			result.add(headerMap.get(key));
+		}
+		return result.elements();
+	}
+	
+	//@Override
+	public String getEnvelope() throws MessagingException {
+		return envelope;
+	}
+	
+	// @Override
+	public String getBodyStructure(boolean includeExtensions)
+			throws MessagingException {
+		return includeExtensions ? bodyStructureWithExtensions : bodyStructure;
+	}
+	
+	public void setMimeMessageBody(byte[] mimeMessageBody) {
+		this.mimeMessageBody = mimeMessageBody;
+	}
+	
+	public int getMimeMessageSizeAsByteArray() throws ProtocolException,
+			MessagingException {
+		return mimeMessageBody.length + headerListLength;
+	}
+	
+	public void writeMimeMessage(StringBuffer response)
+			throws ProtocolException, MessagingException {
+		for (int i=0;i<headerLines.size();i++) {
+			response.append((String)headerLines.get(i)).append("\r\n"); 
+		}
+		response.append("\r\n");
+		for (int i=0;i<mimeMessageBody.length;i++) {
+			response.append((char) mimeMessageBody[i]);
+		}
+	}
+	
+	public MimeMessage getMimeMessage() throws MailboxManagerException {
+		if (super.getMimeMessage()==null) {
+			SharedByteArrayInputStream sharedInput = new SharedByteArrayInputStream(mimeMessageBody);
+			try {
+				MimeMessage message = new MimeMessage(null, sharedInput);
+				setMimeMessage(message);
+				return message;
+			} catch (MessagingException e) {
+				throw new MailboxManagerException("error during parsing mail:"+this,e);
+			}
+		}
+		return super.getMimeMessage();
+	}
+}
Index: imapserver-function/src/main/java/org/apache/james/imapserver/commands/FetchCommand.java
===================================================================
--- imapserver-function/src/main/java/org/apache/james/imapserver/commands/FetchCommand.java	(revision 567160)
+++ imapserver-function/src/main/java/org/apache/james/imapserver/commands/FetchCommand.java	(working copy)
@@ -86,9 +86,8 @@
         }
 
         // TODO only fetch needed results
-        int resultToFetch = MessageResult.FLAGS | MessageResult.MIME_MESSAGE
-                | MessageResult.INTERNAL_DATE | MessageResult.MSN
-                | MessageResult.SIZE;
+        int resultToFetch = fetch.getNeededMessageResult();
+        
         ImapMailboxSession mailbox = session.getSelected().getMailbox();
         for (int i = 0; i < idSet.length; i++) {
             GeneralMessageSet messageSet=GeneralMessageSetImpl.range(idSet[i].getLowVal(),idSet[i].getHighVal(),useUids);
@@ -151,25 +150,23 @@
                 response.append(result.getSize());
             }
 
-            SimpleMessageAttributes attrs = new SimpleMessageAttributes(result
-                    .getMimeMessage(), getLogger());
-
+    
             // ENVELOPE response
             if (fetch.envelope) {
                 response.append(" ENVELOPE ");
-                response.append(attrs.getEnvelope());
+                response.append(result.getEnvelope());
             }
 
             // BODY response
             if (fetch.body) {
                 response.append(" BODY ");
-                response.append(attrs.getBodyStructure(false));
+                response.append(result.getBodyStructure(false));
             }
 
             // BODYSTRUCTURE response
             if (fetch.bodyStructure) {
                 response.append(" BODYSTRUCTURE ");
-                response.append(attrs.getBodyStructure(true));
+                response.append(result.getBodyStructure(true));
             }
 
             // UID response
@@ -190,9 +187,8 @@
                 // Various mechanisms for returning message body.
                 String sectionSpecifier = fetchElement.getParameters();
 
-                MimeMessage mimeMessage = result.getMimeMessage();
                 try {
-                    handleBodyFetch(mimeMessage, sectionSpecifier, response);
+                    handleBodyFetch(result, sectionSpecifier, response);
                 } catch (MessagingException e) {
                     throw new MailboxException(e.getMessage(), e);
                 }
@@ -212,14 +208,15 @@
     }
 
 
-    private void handleBodyFetch( MimeMessage mimeMessage,
+    private void handleBodyFetch( MessageResult result, 
                                   String sectionSpecifier,
                                   StringBuffer response )
             throws ProtocolException, MessagingException
     {
+
         if ( sectionSpecifier.length() == 0 ) {
             // TODO - need to use an InputStream from the response here.
-            ByteArrayOutputStream bout = new ByteArrayOutputStream();
+            /*ByteArrayOutputStream bout = new ByteArrayOutputStream();
             try {
                 mimeMessage.writeTo(new CRLFOutputStream(bout));
             }
@@ -228,21 +225,30 @@
             }
             byte[] bytes = bout.toByteArray();
             addLiteral( bytes, response );
+            */
+        	
+            response.append('{' );
+            response.append( result.getMimeMessageSizeAsByteArray() ); // TODO JD addLiteral: why was it  bytes.length +1 here?
+            response.append( '}' );
+            response.append( "\r\n" );
+
+            result.writeMimeMessage(response);
+        	
             // TODO JD maybe we've to add CRLF here
             
         }
         else if ( sectionSpecifier.equalsIgnoreCase( "HEADER" ) ) {
-            Enumeration e = mimeMessage.getAllHeaderLines();
+            Enumeration e = result.getAllHeaderLines();
             addHeaders( e, response );
         }
         else if ( sectionSpecifier.startsWith( "HEADER.FIELDS.NOT " ) ) {
             String[] excludeNames = extractHeaderList( sectionSpecifier, "HEADER.FIELDS.NOT ".length() );
-            Enumeration e = mimeMessage.getNonMatchingHeaderLines( excludeNames );
+            Enumeration e = result.getNonMatchingHeaderLines( excludeNames );
             addHeaders( e, response );
         }
         else if ( sectionSpecifier.startsWith( "HEADER.FIELDS " ) ) {
             String[] includeNames = extractHeaderList( sectionSpecifier, "HEADER.FIELDS ".length() );
-            Enumeration e = mimeMessage.getMatchingHeaderLines( includeNames );
+            Enumeration e = result.getMatchingHeaderLines( includeNames );
             addHeaders( e, response );
         }
         else if ( sectionSpecifier.equalsIgnoreCase( "MIME" ) ) {
@@ -257,6 +263,7 @@
             ByteArrayOutputStream bodyOut = new ByteArrayOutputStream();
             try {
                 // TODO James Trunk : Is this okay?
+                MimeMessage mimeMessage = result.getMimeMessage();
                 MimeMessageWrapper mmw=new MimeMessageWrapper(mimeMessage);
                 
                 mmw.writeTo(headerOut, bodyOut );
@@ -436,11 +443,11 @@
                     } else if ("UID".equalsIgnoreCase(name)) {
                         fetch.uid = true;
                     } else if ("RFC822".equalsIgnoreCase(name)) {
-                        fetch.add(new BodyFetchElement("RFC822", ""), false);
+                        fetch.add(new BodyFetchElement("RFC822", "", null), false);
                     } else if ("RFC822.HEADER".equalsIgnoreCase(name)) {
-                        fetch.add(new BodyFetchElement("RFC822.HEADER", "HEADER"), true);
+                        fetch.add(new BodyFetchElement("RFC822.HEADER", "HEADER", null), true);
                     } else if ("RFC822.TEXT".equalsIgnoreCase(name)) {
-                        fetch.add(new BodyFetchElement("RFC822.TEXT", "TEXT"), false);
+                        fetch.add(new BodyFetchElement("RFC822.TEXT", "TEXT", null), false);
                     } else {
                         throw new ProtocolException( "Invalid fetch attribute: " + name );
                     }
@@ -452,10 +459,19 @@
                     String parameter = readWord(command, "]");
 
                     consumeChar( command, ']');
+                    
+                    char partialStart = command.nextChar();
+                    String partial = null;
+                    if (partialStart=='<') {
+                    	consumeChar(command, '<');
+                    	partial = readWord(command, ">");
+                    	consumeChar(command, '>');
+                    }
+                    
                     if ( "BODY".equalsIgnoreCase( name ) ) {
-                        fetch.add(new BodyFetchElement("BODY[" + parameter + "]", parameter), false);
+                        fetch.add(new BodyFetchElement("BODY[" + parameter + "]", parameter, partial), false);
                     } else if ( "BODY.PEEK".equalsIgnoreCase( name ) ) {
-                        fetch.add(new BodyFetchElement("BODY[" + parameter + "]", parameter), true);
+                        fetch.add(new BodyFetchElement("BODY[" + parameter + "]", parameter, partial), true);
                     } else {
                         throw new ProtocolException( "Invalid fetch attibute: " + name + "[]" );
                     }
@@ -510,6 +526,9 @@
         
         private Set bodyElements = new HashSet();
         
+        boolean headerFetchElement = false;
+        boolean mailFetchElement = false;
+        
         public Collection getBodyElements() {
             return bodyElements;
         }
@@ -523,19 +542,55 @@
             if (!peek) {
                 setSeen = true;
             }
+            // we only need the headers, if the following element added:
+            String sectionIdentifier = element.sectionIdentifier.toUpperCase();
+			if ("HEADERS".equals(sectionIdentifier) || sectionIdentifier.startsWith("HEADER.FIELDS.NOT ") || sectionIdentifier.startsWith("HEADER.FIELDS ")) {
+            	headerFetchElement = true;
+            } else {
+            	// unfortunately we need to fetch the whole mail
+            	mailFetchElement = true;
+            }
             bodyElements.add(element);
         }
+        
+        public int getNeededMessageResult() {
+        	int result = MessageResult.MSN;
+        	if (flags || setSeen) {
+        		result |= MessageResult.FLAGS;
+        	}
+        	if (internalDate) {
+        		result |= MessageResult.INTERNAL_DATE;
+        	}
+        	if (size) {
+        		result |= MessageResult.SIZE;
+        	}
+        	if (uid) {
+        		result |= MessageResult.UID;
+        	}
+        	if (mailFetchElement) {
+        		result |= MessageResult.MIME_MESSAGE;
+        	}
+        	if (body || bodyStructure || envelope) {
+        		result |= MessageResult.ENVELOPE;
+        	}
+        	if (headerFetchElement || mailFetchElement) {
+        		result |= MessageResult.HEADERS;
+        	}
+        	return result;
+        }
     }
 
     private class BodyFetchElement
     {
         private String name;
         private String sectionIdentifier;
+        private String partial;
 
-        public BodyFetchElement( String name, String sectionIdentifier)
+        public BodyFetchElement( String name, String sectionIdentifier, String partial)
         {
             this.name = name;
             this.sectionIdentifier = sectionIdentifier;
+            this.partial = partial;
         }
 
         public String getParameters()
@@ -546,6 +601,10 @@
         public String getResponseName() {
             return this.name;
         }
+        
+        public String getPartial() {
+			return partial;
+		}
     }
 
 }
