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); }