void MessageAttachmentStripper::_WriteToDisk(shared_ptr<Message> pMessage, MimeBody &oMainMessage, shared_ptr<MimeBody> pBody) { if (!pBody) return; AnsiString sHeader; vector<MimeField> oFieldList = oMainMessage.Fields(); vector<MimeField>::iterator iterField = oFieldList.begin(); while (iterField != oFieldList.end()) { MimeField oField = (*iterField); AnsiString sName = oField.GetName(); if (sName.CompareNoCase("subject") == 0) { String sTextVirusFound = Configuration::Instance()->GetServerMessages()->GetMessage("VIRUS_FOUND"); sHeader += sName; sHeader += ": " + sTextVirusFound +": "; sHeader += oField.GetValue(); sHeader += "\r\n"; } else if (sName.CompareNoCase("content-type") != 0) { sHeader += sName; sHeader += ": "; sHeader += oField.GetValue(); sHeader += "\r\n"; } iterField++; } String sBody = pBody->GetRawText(); String sNotification = Configuration::Instance()->GetServerMessages()->GetMessage("VIRUS_ATTACHMENT_REMOVED"); sBody = sNotification + sBody; String sData = sHeader; sData += "\r\n"; sData += sBody + "\r\n"; pMessage->SetSize(sData.GetLength()); String fileName = PersistentMessage::GetFileName(pMessage); FileUtilities::WriteToFile(fileName, sData, false); }
bool MessageUtilities::RetrieveOriginatingAddress(boost::shared_ptr<Message> pMessage, String &hostName, IPAddress &address) //---------------------------------------------------------------------------() // DESCRIPTION: // Tries to determine the IP address / host this email originally comes from. //---------------------------------------------------------------------------() { hostName = ""; address = IPAddress(); // Extract Received headers from the message. boost::shared_ptr<MimeHeader> pHeader = _GetMessageHeader(pMessage); std::list<String> receivedHeaders; AnsiString sHeaderName = "Received"; vector<MimeField> &lstFields = pHeader->Fields(); vector<MimeField>::iterator iter = lstFields.begin(); vector<MimeField>::iterator iterEnd = lstFields.end(); for (; iter != iterEnd; iter++) { MimeField& fd = *iter; if (sHeaderName.CompareNoCase(fd.GetName()) == 0) { receivedHeaders.push_back(fd.GetValue()); } } return RetrieveOriginatingAddress(receivedHeaders, hostName, address); }
void POP3ClientConnection::ProcessReceivedHeaders_(std::shared_ptr<MimeHeader> pHeader) //---------------------------------------------------------------------------() // DESCRIPTION: // Goes throguh all the "Received" headers of the email. Tries to parse the // addresses and deliver the message to the recipients specified in them. //---------------------------------------------------------------------------() { AnsiString sHeaderName = "Received"; std::vector<MimeField> &lstFields = pHeader->Fields(); std::vector<MimeField>::iterator iter = lstFields.begin(); std::vector<MimeField>::iterator iterEnd = lstFields.end(); RecipientParser recipientParser; for (; iter != iterEnd; iter++) { MimeField& fd = *iter; if (sHeaderName.CompareNoCase(fd.GetName()) == 0) { String sValue = fd.GetValue(); String sRecipient = Utilities::GetRecipientFromReceivedHeader(sValue); if (!sRecipient.IsEmpty()) { bool recipientOK = false; recipientParser.CreateMessageRecipientList(sRecipient, current_message_->GetRecipients(), recipientOK); } } } }
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; }
// get the value of a parameter bool MimeField::GetParameter(const char* pszAttr, AnsiString& strValue) const { strValue = ""; bool encodedParameter = false; vector<AnsiString> parameters = StringParser::SplitString(AnsiString(m_strValue), ";"); for (unsigned int i = 1; i < parameters.size(); i++) { AnsiString value = parameters[i]; value.TrimLeft(); // Locate end of parameter name. int nameEndPos = 0; for (nameEndPos = 0; nameEndPos < value.GetLength(); nameEndPos++) { char c = value[nameEndPos]; if (c == ' ' || c == '*' || c == '=') break; } // If we haven't found any value for this parameter, bail out. if (nameEndPos == 0 && strValue.IsEmpty()) return false; AnsiString parameterName = value.Mid(0, nameEndPos); if (parameterName.CompareNoCase(pszAttr) != 0) continue; // Locate start of parameter value. int valuePos = 0; for (valuePos = nameEndPos; valuePos < value.GetLength(); valuePos++) { char c = value[valuePos]; if (c == '=') break; } // We want the char before = NOT char after param name // to detect encoding per RFC 2231 4.1 // http://www.hmailserver.com/forum/viewtopic.php?f=10&t=21417 char characterBeforeEquals = value[valuePos - 1]; if (characterBeforeEquals == '*') encodedParameter = true; // Skip past the equal sign. valuePos++; // Locate the start of the actual value. May be enclosed with quotes. // // For instance, this is perfectly valid // Content-Type: text/plain; charset = "iso-8859-1" // for (; valuePos < value.GetLength(); valuePos++) { char c = value[valuePos]; if (c == ' ' || c == '"') continue; else break; } // Locate the end of the value. The value may contain // pretty much any character, including space. int valueEndPos = valuePos; for (; valueEndPos < value.GetLength(); valueEndPos++) { char c = value[valueEndPos]; if (c == ';' || c == '"') break; else continue; } int valueLength = valueEndPos - valuePos; value = value.Mid(valuePos, valueLength); // If the value is // Content-Type: text/plain; charset = "iso-8859-1" // it needs to be trimmed. value.TrimRight(); strValue.append(value); } if (strValue.IsEmpty()) return false; /* (2) MIME headers, like the RFC 822 headers they often appear in, are limited to 7bit US-ASCII, and the encoded-word mechanisms of RFC 2047 are not available to parameter values. This makes it impossible to have parameter values in character sets other than US-ASCII without specifying some sort of private per-parameter encoding. http://tools.ietf.org/html/draft-freed-pvcsc-03 Examples: Input: ISO-8859-1''%E9%2E%70%6E%67 Output: =?ISO-8859-1?Q?=E9=2Epng?= */ if (encodedParameter) { MimeParameterRFC2184Decoder decoder; strValue.assign(decoder.Decode(strValue)); } strValue.TrimLeft(); return true; }
AnsiString SimpleCanonicalization::CanonicalizeHeader(AnsiString header, const std::pair<AnsiString, AnsiString> &signatureField, const std::vector<AnsiString> &fieldsToInclude, AnsiString &fieldList) { // first build a formatted list of header lines. std::vector<AnsiString> formattedHeaderLines; AnsiString result; std::vector<AnsiString> headerLines = StringParser::SplitString(header, "\r\n"); AnsiString foldedLines; for (size_t i = headerLines.size(); i > 0; i--) { AnsiString line = headerLines[i-1]; if (line.StartsWith(" ") || line.StartsWith("\t")) { // line is folded. append to next. foldedLines = line + "\r\n" + foldedLines; } else { // we have a line! int colonPos = line.Find(":"); if (colonPos < 0) { assert(0); // broken header. continue; } AnsiString entireHeaderField = line + "\r\n" + foldedLines; formattedHeaderLines.push_back(entireHeaderField); foldedLines = ""; } } for(AnsiString fieldToInclude : fieldsToInclude) { fieldToInclude.Trim(); // locate the header line. auto iter = formattedHeaderLines.begin(); auto iterEnd = formattedHeaderLines.end(); for (; iter != iterEnd; iter++) { AnsiString headerLine = (*iter); int colonPos = headerLine.Find(":"); AnsiString headerName = headerLine.Mid(0, colonPos); if (headerName.CompareNoCase(fieldToInclude) == 0) { result += headerLine; if (!fieldList.IsEmpty()) fieldList += ":"; fieldList += headerName; formattedHeaderLines.erase(iter); break; } } } if (!signatureField.first.IsEmpty()) { // Don't pick the value from the actual header, use the header we're verifying instead // If there are more than one DKIM-signature fields in the header, this will be important. AnsiString headerName = signatureField.first; AnsiString headerLine = headerName + ": " + GetDKIMWithoutSignature_(signatureField.second); if (headerLine.EndsWith("\r\n")) headerLine = headerLine.Mid(0, headerLine.GetLength()-2); result += headerLine; } return result; }