shared_ptr<MimeBody> 
   MessageData::FindPartNoRecurse(shared_ptr<MimeBody> parent, const AnsiString &sType) const
   {
      shared_ptr<MimeBody> pPart = parent->FindFirstPart();

      while (pPart)
      {
         AnsiString sContentType = pPart->GetCleanContentType();
         sContentType.MakeLower();

         if (sContentType.CompareNoCase(sType) == 0)
         {
            // Create a new part in the end of the message. We have already
            // looked for a part with the proper type without success. This
            // is probably a new attachment.
            return pPart;
         }

         pPart = parent->FindNextPart();
      }
      
      shared_ptr<MimeBody> empty;
      return empty;
   }
   shared_ptr<MimeBody> 
   MessageData::CreatePart(const String &sContentType)
   {
      // Step 1: Extract all parts.
      // Step 2: Delete everything
      // Step 3: Create the new type.
      // Step 4: Insert the new type and all others.

      // Create a new part by rebuilding the message more or less from scratch.
      AnsiString sMainBodyType = m_pMimeMail->GetCleanContentType();
      AnsiString sMainBodyCharset = m_pMimeMail->GetCharset();
      sMainBodyType.MakeLower();
      
      shared_ptr<MimeBody> textPart = FindPartNoRecurse(m_pMimeMail, "text/plain");
      shared_ptr<MimeBody> htmlPart = FindPartNoRecurse(m_pMimeMail, "text/html");

      shared_ptr<MimeBody> retValue;

      shared_ptr<MimeBody> alternativeNode = FindPartNoRecurse(m_pMimeMail, "multipart/alternative");
      if (alternativeNode)
      {
         if (!textPart) 
         {
            textPart = FindPartNoRecurse(alternativeNode, "text/plain");
            if (textPart)
               alternativeNode->ErasePart(textPart);
         }

         if (!htmlPart)
         {
            htmlPart = FindPartNoRecurse(alternativeNode, "text/html");

            if (htmlPart)
               alternativeNode->ErasePart(htmlPart);
         }

         m_pMimeMail->ErasePart(alternativeNode);
      }

      if (!textPart && !htmlPart)
      {
         // We don't have any text or HMTL part. Copy the main content
         // of the message to a new part, if the main content isn't empty.
         if (sMainBodyType == "" || sMainBodyType == "text/plain")
         {
            if (m_pMimeMail->GetRawText().size() > 0)
            {
               textPart = shared_ptr<MimeBody>(new MimeBody);
               textPart->SetRawText(m_pMimeMail->GetRawText());
               textPart->SetContentType("text/plain", "");
               
               if (!sMainBodyCharset.IsEmpty())
                  textPart->SetCharset(sMainBodyCharset);

               AnsiString originalTransferEncoding = m_pMimeMail->GetTransferEncoding();
               if (!originalTransferEncoding.IsEmpty())
                  textPart->SetTransferEncoding(originalTransferEncoding);
            }
         }
         else if (sMainBodyType == "text/html")
         {
            if (m_pMimeMail->GetRawText().size() > 0)
            {
               htmlPart = shared_ptr<MimeBody>(new MimeBody);
               htmlPart->SetRawText(m_pMimeMail->GetRawText());
               htmlPart->SetContentType("text/html", "");
               
               if (!sMainBodyCharset.IsEmpty())
                  htmlPart->SetCharset(sMainBodyCharset);

               AnsiString originalTransferEncoding = m_pMimeMail->GetTransferEncoding();
               if (!originalTransferEncoding.IsEmpty())
                  htmlPart->SetTransferEncoding(originalTransferEncoding);
            }
         }
      }

      // Locate the other parts which are not text or html.
      //
      // When we get here, any alternative, text or html parts
      // should have been removed from the message already.
      //
      shared_ptr<MimeBody> part = m_pMimeMail->FindFirstPart();
      set<shared_ptr<MimeBody> > setAttachments;
      while (part)
      {
         AnsiString subContentType = part->GetCleanContentType();
         if (!IsTextType(subContentType) && !IsHTMLType(subContentType))
            setAttachments.insert(part);

         part = m_pMimeMail->FindNextPart();
      }

      // Remove all parts so that we can rebuild it again.
      m_pMimeMail->DeleteAll();

      // Create the brand new part...
      if (sContentType.CompareNoCase(_T("text/plain")) == 0)
      {
         assert (textPart == 0);

         if (setAttachments.size() == 0 && !htmlPart)
         {
            // Reuse the main part. There's no need to add a new one.
            textPart = m_pMimeMail;
            textPart->SetContentType("text/plain", "");
         }
         else
         {
            textPart = shared_ptr<MimeBody>(new MimeBody);
            textPart->SetContentType("text/plain", "");

            AnsiString transferEncoding = m_pMimeMail->GetTransferEncoding();
            if (!transferEncoding.IsEmpty())
               textPart->SetTransferEncoding(transferEncoding);

            if (!sMainBodyCharset.IsEmpty())
               textPart->SetCharset(sMainBodyCharset);

         }

         retValue = textPart;
      }
      else if (sContentType.CompareNoCase(_T("text/html")) == 0)
      {
         assert (htmlPart == 0);

         if (setAttachments.size() == 0 && !textPart)
         {
            // Reuse the main part. There's no need to add a new one.

            htmlPart = m_pMimeMail;
            htmlPart->SetContentType("text/html", "");
         }
         else
         {
            htmlPart = shared_ptr<MimeBody>(new MimeBody);
            htmlPart->SetContentType("text/html", "");

            AnsiString transferEncoding = m_pMimeMail->GetTransferEncoding();
            if (!transferEncoding.IsEmpty())
               htmlPart->SetTransferEncoding(transferEncoding);

            if (!sMainBodyCharset.IsEmpty())
               htmlPart->SetCharset(sMainBodyCharset);
         }

         retValue = htmlPart;
         
      }
      else
      {
         // create a new item. treat as an attachment.
         retValue = shared_ptr<MimeBody>(new MimeBody);
         setAttachments.insert(retValue);
      }

      AnsiString mainBodyType;
      if (setAttachments.size() > 0)
         mainBodyType = "multipart/mixed";
      else if (textPart && htmlPart)
         mainBodyType = "multipart/alternative";
      else if (htmlPart)
         mainBodyType = "text/html";
      else
         mainBodyType = "text/plain";

      if (textPart && htmlPart)
      {
         if (mainBodyType == "multipart/mixed")
         {
            shared_ptr<MimeBody> alternativePart = shared_ptr<MimeBody>(new MimeBody);
            alternativePart->SetContentType("multipart/alternative", "");
            alternativePart->SetRawText("This is a multi-part message.\r\n\r\n");

            alternativePart->AddPart(textPart);
            alternativePart->AddPart(htmlPart);
            alternativePart->SetBoundary(NULL);

            m_pMimeMail->AddPart(alternativePart);
         }
         else
         {
            if (m_pMimeMail != textPart)
               m_pMimeMail->AddPart(textPart);

            if (m_pMimeMail != htmlPart)
               m_pMimeMail->AddPart(htmlPart);
         }
         
      }
      else if (textPart)
      {
         if (mainBodyType == "multipart/mixed")
         {
            if (m_pMimeMail != textPart)
               m_pMimeMail->AddPart(textPart);
         }
      }
      else if (htmlPart)
      {
         if (mainBodyType == "multipart/mixed")
         {
            if (m_pMimeMail != htmlPart)
               m_pMimeMail->AddPart(htmlPart);
         }
      }

      boost_foreach(shared_ptr<MimeBody> pAttachment, setAttachments)
      {
         m_pMimeMail->AddPart(pAttachment);
      }