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);
   }
Пример #2
0
   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);
            }

         }
      }
   }
Пример #4
0
   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;
   }
Пример #5
0
   // 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;
   }