示例#1
0
   void 
   TCPConnection::AsyncRead(const AnsiString &delimitor)
   {
      UpdateAutoLogoutTimer();

      std::function<void (const boost::system::error_code&, size_t)> AsyncReadCompletedFunction =
         std::bind(&TCPConnection::AsyncReadCompleted, shared_from_this(), 
         std::placeholders::_1,
         std::placeholders::_2);

      if (is_ssl_)
      {
         if (delimitor.GetLength() == 0)
            boost::asio::async_read(ssl_socket_, receive_buffer_, boost::asio::transfer_at_least(1), AsyncReadCompletedFunction);
         else
            boost::asio::async_read_until(ssl_socket_, receive_buffer_,  delimitor, AsyncReadCompletedFunction);
      }
      else
      {
         if (delimitor.GetLength() == 0)
         {
            boost::asio::async_read(socket_, receive_buffer_, boost::asio::transfer_at_least(1), AsyncReadCompletedFunction);
         }
         else
         {
            boost::asio::async_read_until(socket_, receive_buffer_, delimitor, AsyncReadCompletedFunction);
         }
      }

   }
示例#2
0
   void
   StringParser::Base64Decode(const String &sInput, String &sOutput)
   {

      if (sInput.GetLength() == 0)
      {
         sOutput.Empty();
         return;
      }

      AnsiString sInputStr = sInput;

      MimeCodeBase64 DeCoder;
      DeCoder.AddLineBreak(false);
      DeCoder.SetInput(sInputStr, sInputStr.GetLength(), false);
      
      AnsiString output;
      DeCoder.GetOutput(output);

      int length = output.GetLength();
      // Since we're going to store the result in
      // a normal StdString, we can't return null
      // characters.
      for (int i = 0; i < length; i++)
      {
         if (output[i] == 0)
            output[i] = '\t';
      }

      sOutput = output;
   }
   String 
   MessageUtilities::GetSendersIP(boost::shared_ptr<Message> pMessage)
   {
      const String fileName = PersistentMessage::GetFileName(pMessage);

      AnsiString sHeader = PersistentMessage::LoadHeader(fileName);

      MimeHeader oHeader;
      oHeader.Load(sHeader, sHeader.GetLength(), true);

      // Locate the first Received header
      MimeField *pReceivedHeader = oHeader.GetField("Received");
      if (pReceivedHeader == 0)
         return "127.0.0.1";

      // Now we should try to find the IP in the received header.
      String sReceivedValue = pReceivedHeader->GetValue();

      int iAddressStart = sReceivedValue.Find(_T("[")) +1;
      int iAddressEnd = sReceivedValue.Find(_T("]"), iAddressStart);
      int iAddressLen = iAddressEnd - iAddressStart;

      if (iAddressLen <= 0)
         return "127.0.0.1";

      String sIPAddress = sReceivedValue.Mid(iAddressStart, iAddressLen);

      if (!StringParser::IsValidIPAddress(sIPAddress))
         return "127.0.0.1";

      return sIPAddress;
   }
   AnsiString 
   Canonicalization::GetDKIMWithoutSignature_(AnsiString value)
   {
      // locate the b= tag
      int pos = value.Find("b=");
      if (pos < 0)
         return "";

      // Locate end of b-tag. We need to use the ;-separator
      // here. The signature may contain spaces and newlines
      // if it's folded (and canon-mode is set to simple).
      int end = value.Find(";", pos);

      int actualEnd = 0;
      if (end > pos)
         actualEnd = end;
      else
         actualEnd = value.GetLength();

      int len = actualEnd - pos;

      AnsiString before = value.Mid(0, pos+2);
      AnsiString after = value.Mid(actualEnd);

      AnsiString result = before + after;

      return result;
   }
示例#5
0
 bool 
 File::Write(const AnsiString &sWrite)
 {  
    AnsiString sTmp = sWrite;
    DWORD dwWritten = 0;
    return Write((const unsigned char*) sTmp.GetBuffer(), sTmp.GetLength(), dwWritten);
 }
示例#6
0
   String
      MimeHeader::GetUnicodeFieldValue(const AnsiString &pszFieldName, const AnsiString &sRawFieldValue)
   {
      AnsiString sWideStr;
      sWideStr = "";
      if (sRawFieldValue.IsEmpty())
      {
         if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeHeader::GetUnicodeFieldValue - sRawFieldValue.IsEmpty");
         return sWideStr;
      }


      // De-code the value to plain text.
      AnsiString sRetVal;
      FieldCodeBase* pCoder = MimeEnvironment::CreateFieldCoder(pszFieldName);
      pCoder->SetInput(sRawFieldValue, sRawFieldValue.GetLength(), false);
      pCoder->GetOutput(sRetVal);

      AnsiString sCharset = pCoder->GetCharset();

      delete pCoder;

      sWideStr = Charset::ToWideChar(sRetVal, sCharset);

      if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeHeader::GetUnicodeFieldValue - sWideStr: " + sWideStr);
      return sWideStr;
   }
   void
   SMTPClientConnection::ParseData(const AnsiString &Request)
   //---------------------------------------------------------------------------()
   // DESCRIPTION:
   // Parses a server SMTP cmmand.
   //---------------------------------------------------------------------------()
   {
      multi_line_response_buffer_ += Request;

      if (multi_line_response_buffer_.GetLength() > 10000)
      {
         UpdateAllRecipientsWithError_(500, "Unexpected response from server (too long).", false);
         return;
      }

      if (Request.GetLength() > 3 && (Request.GetAt(3) == '-'))
      {
         // Multi-line response. Wait for full buffer.
         multi_line_response_buffer_ += "\r\n";
         EnqueueRead();
         return;
      }

      bool postReceive = InternalParseData(multi_line_response_buffer_);

      multi_line_response_buffer_.Empty();

      if (postReceive)
         EnqueueRead();
   }
示例#8
0
   /*
      Returns one of the following
      Neutral - Undecided
      Pass - Signature verified properly.
      TempFail - Failed to verify signature, potentially a local problem.
      PermFail - Failed to verify signature.

   */
   DKIM::Result
   DKIM::Verify(const String &fileName)
   {
      if (FileUtilities::FileSize(fileName) > MaxFileSize)
         return Neutral;
      
      AnsiString messageHeader = PersistentMessage::LoadHeader(fileName);
      MimeHeader mimeHeader;
      mimeHeader.Load(messageHeader.GetBuffer(), messageHeader.GetLength(), false);

      vector<pair<AnsiString, AnsiString> > signatureFields = GetSignatureFields(mimeHeader);

      if (signatureFields.size() == 0)
      {
         // No signatures in message.
         return Neutral;
      }

      Result result = Neutral;

      typedef pair<AnsiString, AnsiString> HeaderField;
      boost_foreach (HeaderField signatureField, signatureFields)
      {
         result = _VerifySignature(fileName, messageHeader, signatureField);
         if (result == Pass)
            return Pass;
      };
示例#9
0
   // helper.
   EVP_PKEY* 
   _GetPublicKey(const AnsiString &keyData)
   {
      // base64 decode the public key.
      AnsiString publicKeyData = Base64::Decode(keyData, keyData.GetLength());
      const unsigned char * publicKeyDataPointer = (const unsigned char*) publicKeyData.GetBuffer();

      EVP_PKEY *publicKey = d2i_PUBKEY(NULL, &publicKeyDataPointer, publicKeyData.GetLength());

      return publicKey;
   }
 AnsiString 
 SimpleCanonicalization::CanonicalizeBody(AnsiString value)
 {
    // remove all empty lines.
    while (value.EndsWith("\r\n"))
       value = value.Mid(0, value.GetLength()-2);
    
    value += "\r\n";
    
    return value;
 }
示例#11
0
   void
   Base64Tester::Test()
   {
      String s;

      AnsiString input = "Test";
      s = Base64::Encode(input.GetBuffer(), input.GetLength());
      if (s.Compare(_T("VGVzdA==")) != 0)
         throw;

      input = "Test test test test test test test!!!!";
      s = Base64::Encode(input, input.GetLength());
      if (s.Compare(_T("VGVzdCB0ZXN0IHRlc3QgdGVzdCB0ZXN0IHRlc3QgdGVzdCEhISE=")) != 0)
         throw;

      input = "hMailServer is a free e-mail server for Microsoft Windows. It's used by Internet service providers, companies, governments, schools and enthusiasts in all parts of the world. It supports the common e-mail protocols (IMAP, SMTP and POP3) and can easily be integrated with many existing web mail systems. It has flexible score-based spam protection and can attach to your virus scanner to scan all incoming and outgoing email.";
      s = Base64::Encode(input, input.GetLength());
      if (s.Compare(_T("aE1haWxTZXJ2ZXIgaXMgYSBmcmVlIGUtbWFpbCBzZXJ2ZXIgZm9yIE1pY3Jvc29mdCBXaW5kb3dzLiBJdCdzIHVzZWQgYnkgSW50ZXJuZXQgc2VydmljZSBwcm92aWRlcnMsIGNvbXBhbmllcywgZ292ZXJubWVudHMsIHNjaG9vbHMgYW5kIGVudGh1c2lhc3RzIGluIGFsbCBwYXJ0cyBvZiB0aGUgd29ybGQuIEl0IHN1cHBvcnRzIHRoZSBjb21tb24gZS1tYWlsIHByb3RvY29scyAoSU1BUCwgU01UUCBhbmQgUE9QMykgYW5kIGNhbiBlYXNpbHkgYmUgaW50ZWdyYXRlZCB3aXRoIG1hbnkgZXhpc3Rpbmcgd2ViIG1haWwgc3lzdGVtcy4gSXQgaGFzIGZsZXhpYmxlIHNjb3JlLWJhc2VkIHNwYW0gcHJvdGVjdGlvbiBhbmQgY2FuIGF0dGFjaCB0byB5b3VyIHZpcnVzIHNjYW5uZXIgdG8gc2NhbiBhbGwgaW5jb21pbmcgYW5kIG91dGdvaW5nIGVtYWlsLg==")) != 0)
         throw;

      input = "VGVzdA==";
      s = Base64::Decode(input, input.GetLength());
      if (s.Compare(_T("Test")) != 0)
         throw;

      input = "VGVzdCB0ZXN0IHRlc3QgdGVzdCB0ZXN0IHRlc3QgdGVzdCEhISE=";
      s = Base64::Decode(input, input.GetLength());
      if (s.Compare(_T("Test test test test test test test!!!!")) != 0)
         throw;

      input = "aE1haWxTZXJ2ZXIgaXMgYSBmcmVlIGUtbWFpbCBzZXJ2ZXIgZm9yIE1pY3Jvc29mdCBXaW5kb3dzLiBJdCdzIHVzZWQgYnkgSW50ZXJuZXQgc2VydmljZSBwcm92aWRlcnMsIGNvbXBhbmllcywgZ292ZXJubWVudHMsIHNjaG9vbHMgYW5kIGVudGh1c2lhc3RzIGluIGFsbCBwYXJ0cyBvZiB0aGUgd29ybGQuIEl0IHN1cHBvcnRzIHRoZSBjb21tb24gZS1tYWlsIHByb3RvY29scyAoSU1BUCwgU01UUCBhbmQgUE9QMykgYW5kIGNhbiBlYXNpbHkgYmUgaW50ZWdyYXRlZCB3aXRoIG1hbnkgZXhpc3Rpbmcgd2ViIG1haWwgc3lzdGVtcy4gSXQgaGFzIGZsZXhpYmxlIHNjb3JlLWJhc2VkIHNwYW0gcHJvdGVjdGlvbiBhbmQgY2FuIGF0dGFjaCB0byB5b3VyIHZpcnVzIHNjYW5uZXIgdG8gc2NhbiBhbGwgaW5jb21pbmcgYW5kIG91dGdvaW5nIGVtYWlsLg==";
      s = Base64::Decode(input, input.GetLength());
      if (s.Compare(_T("hMailServer is a free e-mail server for Microsoft Windows. It's used by Internet service providers, companies, governments, schools and enthusiasts in all parts of the world. It supports the common e-mail protocols (IMAP, SMTP and POP3) and can easily be integrated with many existing web mail systems. It has flexible score-based spam protection and can attach to your virus scanner to scan all incoming and outgoing email.")) != 0)
         throw;
   }
示例#12
0
AnsiString HashCreator::GenerateHash(const AnsiString &inputString, const AnsiString &salt)
{
    AnsiString saltString = salt;
    if (saltString.GetLength() == 0 && _hashType == SHA256)
    {
        AnsiString randomString = PasswordGenerator::Generate();
        saltString = _GetHash(randomString, hex);
        saltString = saltString.Mid(0, SALT_LENGTH);
    }

    AnsiString value = saltString + _GetHash(saltString + inputString, hex);
    return value;
}
示例#13
0
   boost::shared_ptr<MimeHeader> 
   MessageUtilities::_GetMessageHeader(boost::shared_ptr<Message> pMessage)
   {
      String fileName = PersistentMessage::GetFileName(pMessage);

      AnsiString sHeader = PersistentMessage::LoadHeader(fileName);
      boost::shared_ptr<MimeHeader> pHeader = boost::shared_ptr<MimeHeader>(new MimeHeader());
      
      boost::shared_ptr<MimeHeader> pMimeHeader = boost::shared_ptr<MimeHeader>(new MimeHeader);
      pHeader->Load(sHeader, sHeader.GetLength(), true);

      return pHeader;
   }
示例#14
0
   AnsiString
      MIMEUnicodeEncoder::EncodeValue(const AnsiString &sCharSet, const String &sUnicodeValue)
   {
      AnsiString sMBText = Charset::ToMultiByte(sUnicodeValue, sCharSet);

      FieldCodeBase pCoder;

      pCoder.SetCharset(sCharSet);
      pCoder.SetInput(sMBText, sMBText.GetLength(), true);

      AnsiString encodedValue;
      pCoder.GetOutput(encodedValue);
      return encodedValue;
   }
示例#15
0
   AnsiString 
   DKIM::_SignHash(AnsiString &privateKey, AnsiString &canonicalizedHeader, HashCreator::HashType hashType)
   {
      // Sign the hash.
      BIO *private_bio = BIO_new_mem_buf(privateKey.GetBuffer(), -1);
      if(private_bio == NULL) 
      {
         ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5309, "DKIM::_SignHash", "Unable to read the private key file into memory.");
         return "";
      }

      EVP_PKEY *private_key = PEM_read_bio_PrivateKey(private_bio, NULL, NULL, NULL);
      if(private_key == NULL) 
      {
         BIO_free(private_bio);
         ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5310, "DKIM::_SignHash", "Unable to parse the private key file.");
         return "";
      }
      BIO_free(private_bio);

      unsigned int siglen = EVP_PKEY_size(private_key);
      unsigned char *sig = (unsigned char*) OPENSSL_malloc(siglen);
      
      EVP_MD_CTX headerSigningContext;
      EVP_SignInit( &headerSigningContext, hashType == HashCreator::SHA256 ? EVP_sha256() : EVP_sha1());
      
      String result;

      if (EVP_SignUpdate( &headerSigningContext, canonicalizedHeader.GetBuffer(), canonicalizedHeader.GetLength() ) == 1)
      {
         if (EVP_SignFinal( &headerSigningContext, sig, &siglen, private_key) == 1)
         {
            result = Base64::Encode((const char*) sig, siglen);
         }
         else
         {
            ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5311, "DKIM::_SignHash", "Call to EVP_SignFinal failed.");
         }
      }
      else
      {
         ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5312, "DKIM::_SignHash", "Call to EVP_SignUpdate failed.");
      }

      EVP_PKEY_free(private_key);
      EVP_MD_CTX_cleanup( &headerSigningContext );
      OPENSSL_free(sig);

      return result;
   }
   void 
   POP3ClientConnection::PrependHeaders_()
   //---------------------------------------------------------------------------()
   // DESCRIPTION:
   // Adds headers to the beginning of the message.
   //---------------------------------------------------------------------------()
   {
      // Add a header with the name of the external account, so that
      // we can check where we downloaded it from later on.

      String sHeader;
      sHeader.Format(_T("X-hMailServer-ExternalAccount: %s\r\n"), account_->GetName().c_str());

      AnsiString sAnsiHeader = sHeader;

      transmission_buffer_->Append((BYTE*) sAnsiHeader.GetBuffer(), sAnsiHeader.GetLength());
   }
示例#17
0
   // store the body part to un-encoded string buffer
   void MimeBody::Store(AnsiString &output, bool bIncludeHeader) const
   {
      // store header fields
      int nSize = 0;

      if (bIncludeHeader)
         MimeHeader::Store(output);

      // Copy the data to the output buffer. 
      output.append(m_pbText);

      if (m_listBodies.empty())
         return;

      // store child body parts
      string strBoundary = GetBoundary();
      if (strBoundary.empty())
         return;					// boundary not be set

      int nBoundSize = (int)strBoundary.size() + 6;

// Bill48105 - These iOutputSize are temp fix for [ ambiguous error
	  int iOutputSizeLess2 = output.size() - 2;
	  int iOutputSizeLess1 = output.size() - 1;
      for (BodyList::const_iterator it=m_listBodies.begin(); it!=m_listBodies.end(); it++)
      {
         // If the initial body ends with \r\n, remove them. We add new ones below.
         if (m_listBodies.begin() == it && output.size() >= 2 && 
            output[iOutputSizeLess2] == '\r' && output[iOutputSizeLess1] == '\n')
         {
            output = output.Mid(0, output.GetLength() - 2);
         }

         AnsiString boundaryLine = Formatter::Format(_T("\r\n--{0}\r\n"), String(strBoundary));
         output.append(boundaryLine);

         shared_ptr<MimeBody> pBP = *it;
         ASSERT(pBP != NULL);	

         pBP->Store(output);
      }

      AnsiString endBoundaryLine = Formatter::Format(_T("\r\n--{0}--\r\n"), String(strBoundary));
      output.append(endBoundaryLine);
   }
示例#18
0
   void 
   TCPConnection::EnqueueWrite(const AnsiString &sData)
   {
      AnsiString sTemp = sData;
      char *pBuf = sTemp.GetBuffer();

         std::shared_ptr<ByteBuffer> pBuffer = std::shared_ptr<ByteBuffer>(new ByteBuffer());
      pBuffer->Add((BYTE*) pBuf, sData.GetLength());

#ifdef _DEBUG
      String sDebugOutput;
         sDebugOutput.Format(_T("SENT: %s"), String(sTemp).c_str());
      OutputDebugString(sDebugOutput);
#endif

      EnqueueWrite(pBuffer);

   }
示例#19
0
   std::vector<AnsiString>
   StringParser::SplitString(const AnsiString &sInput, const AnsiString &sSeperators)
   {
      std::vector<AnsiString> vecResult;
      int iBeginning = 0;
      int iEnd = sInput.Find(sSeperators);

      if (iEnd == -1)
      {
         // The separator was not found in the string. 
         // We should put the entire string in the result.
         if (!sInput.IsEmpty())
            vecResult.push_back(sInput);

      }

      int iSeperatorLen = sSeperators.GetLength();

      while (iEnd >= 0)
      {
         int iSubStrLength = iEnd - iBeginning;

         String sSubString;
         sSubString = sInput.Mid(iBeginning, iSubStrLength);

         vecResult.push_back(sSubString);

         // Skip to the position where the next substring
         // can start
         iBeginning = iEnd + iSeperatorLen;
         iEnd = sInput.Find(sSeperators, iBeginning);   
      }

      if (iBeginning > 0)
      {
         String sSubString = sInput.Mid(iBeginning);
         if (!sSubString.IsEmpty())
            vecResult.push_back(sSubString);
      }

      return vecResult;


   }
示例#20
0
   AnsiString
      MimeHeader::GetUTF8FieldValue(const AnsiString &pszFieldName, const AnsiString &sRawFieldValue)
   {
      AnsiString sAnsiStr;
      if (sRawFieldValue.IsEmpty())
         return sAnsiStr;


      // De-code the value to plain text.
      AnsiString sRetVal;
      FieldCodeBase* pCoder = MimeEnvironment::CreateFieldCoder(pszFieldName);
      pCoder->SetInput(sRawFieldValue, sRawFieldValue.GetLength(), false);
      pCoder->GetOutput(sRetVal);

      delete pCoder;

      sAnsiStr = Charset::ToUTF8(sRetVal);
      return sAnsiStr;
   }
   AnsiString 
   RelaxedCanonicalization::CanonicalizeHeaderValue(AnsiString value)
   {
      /*
      Unfold all header field continuation lines as described in
      [RFC2822]; in particular, lines with terminators embedded in
      continued header field values (that is, CRLF sequences followed by
      WSP) MUST be interpreted without the CRLF.  Implementations MUST
      NOT remove the CRLF at the end of the header field value.
      */

      value.Replace("\r\n ", " ");
      value.Replace("\r\n\t", " ");

      /*
      Convert all sequences of one or more WSP characters to a single SP
      character.  WSP characters here include those before and after a
      line folding boundary.
      */

      value.Replace("\t ", " ");
      value.Replace(" \t", " ");
      
      while (value.Find("  ") >= 0)
         value.Replace("  ", " ");

      /*
      Delete all WSP characters at the end of each unfolded header field value.
      */

      while (value.EndsWith(" ") || value.EndsWith("\t"))
         value = value.Mid(0, value.GetLength() -1);

      /* Delete any WSP characters remaining before and after the colon
      separating the header field name from the header field value.  The
      colon separator MUST be retained.
      */
      value.Trim();


      return value;
   }
示例#22
0
   void
   StringParser::Base64Encode(const String &sInput, String &sOutput)
   {
      if (sInput.GetLength() == 0)
      {
         sOutput.Empty();
         return;
      }
         
      AnsiString sInputStr = sInput;
      
      MimeCodeBase64 Coder;
      Coder.SetInput(sInputStr, sInputStr.GetLength(), true);
      Coder.AddLineBreak(false);
      
      AnsiString output;
      Coder.GetOutput(output);

      sOutput = output;
   }
示例#23
0
   // initialize the content with text
   int MimeBody::SetUnicodeText(const String &sText)
   {
      // Retrieve the current charset for this field.
      std::string strCharset = GetCharset();

      if (strCharset.size() == 0)
      {
         return SetRawText(sText);
      }

      AnsiString sMBText = Charset::ToMultiByte(sText, strCharset);
      AnsiString sEncodedValue;
      MimeCodeBase* pCoder = MimeEnvironment::CreateCoder("quoted-printable");
      pCoder->SetInput(sMBText, sMBText.GetLength(), true);
      pCoder->GetOutput(sEncodedValue);
      delete pCoder;   

      SetTransferEncoding("quoted-printable");

      return SetRawText(sEncodedValue);
   }   
   void 
   POP3ClientConnection::ParseMessageHeaders_()
   {
      assert(current_message_);

      String fileName = PersistentMessage::GetFileName(current_message_);

      AnsiString sHeader = PersistentMessage::LoadHeader(fileName);
      std::shared_ptr<MimeHeader> pHeader = std::shared_ptr<MimeHeader>(new MimeHeader);
      pHeader->Load(sHeader, sHeader.GetLength());

      {
         // Parse out the sender of the message. 
         String sFrom = pHeader->GetRawFieldValue("From");

         if (!sFrom.IsEmpty())
         {
            AddresslistParser oAddressParser;

            String sFullName, sUser, sDomain;
            oAddressParser.ExtractParts(sFrom, sFullName, sUser, sDomain);

            if (!sUser.IsEmpty() && !sDomain.IsEmpty())
            {
               sFrom = sUser + "@" + sDomain;
               if (StringParser::IsValidEmailAddress(sFrom))
                  current_message_->SetFromAddress(sFrom);
            }
         }
      }      

      // bool bPreprocessRecipientList = true;
      CreateRecipentList_(pHeader);

      // Remove non-existent accounts.
      RemoveInvalidRecipients_();

      RetrieveReceivedDate_(pHeader);
   }
示例#25
0
   void 
      MimeHeader::SetUnicodeFieldValue(const AnsiString &sFieldName, const String & sFieldValue, const AnsiString & sCharset)
   {
      // Retrieve the current charset for this field.
      MimeField* pfd = GetField(sFieldName);

      if (sFieldValue.GetLength() == 0)
      {
         SetRawFieldValue(sFieldName, "", "");
         return;
      }

      AnsiString sCharsetToUse = sCharset;

      // If client hasn't specified character set, assume it's the existing one.
      if (pfd && pfd->GetCharset() && sCharsetToUse.IsEmpty())
         sCharsetToUse = pfd->GetCharset();

      // If there's no existing charset, assume it's the same as for the email.
      if (sCharsetToUse.IsEmpty())
         sCharsetToUse = GetCharset();

      if (sCharsetToUse.IsEmpty())
         sCharsetToUse = "utf-8";

      AnsiString sMBText = Charset::ToMultiByte(sFieldValue, sCharsetToUse);

      // Encode the value
      FieldCodeBase* pCoder = MimeEnvironment::CreateFieldCoder(sFieldName);
      pCoder->SetInput(sMBText, sMBText.GetLength(), true);
      pCoder->SetCharset(sCharsetToUse.c_str());

      AnsiString sEncodedValue;
      pCoder->GetOutput(sEncodedValue);

      delete pCoder;   

      SetRawFieldValue(sFieldName, sEncodedValue, sCharsetToUse);
   }
示例#26
0
   String
      MimeBody::GetUnicodeText()
   {
      String sWideStr;
      AnsiString sRawText = GetRawText();

if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sRawText: " + sRawText)
else
if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sRawText");

      if (sRawText.IsEmpty())
      {
if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sRawText.IsEmpty!");
         return sRawText;
       }

      std::string strCharset = GetCharset();
      if (strCharset.size() == 0)
      {
if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText strCharset.size=0!");
         return sRawText;
      }

      // De-code the value to plain text.
      AnsiString sRetVal;
      MimeCodeBase* pCoder = MimeEnvironment::CreateCoder(GetTransferEncoding());
      pCoder->SetInput(sRawText, sRawText.GetLength(), false);
      pCoder->GetOutput(sRetVal);
      delete pCoder;

      sWideStr = Charset::ToWideChar(sRetVal, strCharset);
if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sWideStr: " + sWideStr)
else
if (IniFileSettings::Instance()->GetLogLevel() > 99) LOG_DEBUG("MimeBody::GetUnicodeText sWideStr");

      return sWideStr;
   }
   String
   IMAPCommandSEARCH::GetHeaderValue_(const String &fileName, std::shared_ptr<Message> pMessage, const String &sHeaderField)
   {
      if (message_data_)
      {
         message_data_ = std::shared_ptr<MessageData>(new MessageData());
         message_data_->LoadFromMessage(fileName, pMessage);

         return message_data_->GetFieldValue(sHeaderField);
      }
      
      if (!mime_header_)
      {
         // Load header
         AnsiString sHeader = PersistentMessage::LoadHeader(fileName);

         mime_header_ = std::shared_ptr<MimeHeader>(new MimeHeader);
         mime_header_->Load(sHeader, sHeader.GetLength(), true);
      }

      AnsiString sHeaderFieldStr = sHeaderField;
      return mime_header_->GetUnicodeFieldValue(sHeaderFieldStr);

   }
示例#28
0
   void
   SMTPClientConnection::InternalParseData(const AnsiString  &Request)
   {
      LOG_DEBUG("SMTPClientConnection::_ParseASCII()");

      String sData = "RECEIVED: " + Request;
      LOG_SMTP_CLIENT(GetSessionID(), GetIPAddress().ToString(), sData);

      // Below 3 lines is fix of the problem that occurs when the remote server answers
      // with 2 line in his welcome message.
      String sMinus = "-";
      if ((Request.GetLength() > 3) && (Request.GetAt(3) == sMinus.GetAt(0)))
      {
         LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 1");
         return;
      }

      int lFirstSpace = Request.Find(" ");
   
      AnsiString sFirstWordTemp;
      if (lFirstSpace < 0)
         sFirstWordTemp = Request;
      else
         sFirstWordTemp = Request.Mid(0, lFirstSpace);
      sFirstWordTemp.MakeUpper();
      int iCode = atoi(sFirstWordTemp);

      // We should not update all recipient's if we've just sent a
      // RCPT TO. We should only update the specific one we've just
      // sent to.
      // 
      // Also, we should not update state if we've just sent QUIT to
      // the server. At the time we send QUIT, the message has already
      // been either accepted for delivery and rejected. Any error after
      // this isn't relvat.
      if (m_CurrentState != RCPTTOSENT && m_CurrentState != QUITSENT)
      {
         if (IsPermanentNegative(iCode))
         {
            _UpdateAllRecipientsWithError(iCode, Request, false);
            _SendQUIT();
            return;
         }
         else if (IsTransientNegative(iCode))
         {
            _UpdateAllRecipientsWithError(iCode, Request, false);
            _SendQUIT();
            return;
         }
      }
   
      switch (m_CurrentState)
      {
      case SENDUSERNAME:
         _ProtocolSendUsername();
         break;
      case SENDPASSWORD:
         _ProtocolSendPassword();
         break;
      case PASSWORDCHECK:
         if (!_ProtocolPassswordCheck(iCode, Request))
         {
            // Authentication failed. We have just sent
            // a quit command.
            return;
         }

         break;
      }
      
      if (m_CurrentState == HELO)
      {
         if (iCode == 220)
         {
			   String sComputerName = Utilities::ComputerName(); 
      
            if (m_bUseSMTPAuth)
            {
               _SendData("EHLO " + sComputerName);
               _SetState(EHLOSENT);
            }
            else
            {
               _SendData("HELO " + sComputerName);
               _SetState(HELOSENT);
            }
        
            LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 2");

            return ;
         }
         else
         {
            LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 3");
            _UpdateAllRecipientsWithError(iCode, Request, false);
            _SendQUIT();
            return;
         }
      }

      if (m_CurrentState == EHLOSENT)
      {
         // Ask the server to initiate login process.
         _SendData("AUTH LOGIN");
         _SetState(SENDUSERNAME);
         return ;
      }

      if (m_CurrentState == HELOSENT)
      {
         if (IsPositiveCompletion(iCode))
         {
            // --- Server accepted HELO. Go to HEADER/MAILFROM state.
            _SetState(MAILFROM);
         }
	      else
         {
            _UpdateAllRecipientsWithError(iCode, Request, false);
         }
      }
   

      if (m_CurrentState == MAILFROM)
      {
         String sFrom = m_pDeliveryMessage->GetFromAddress();
         String sData = "MAIL FROM:<" + sFrom + ">";
         _SendData(sData);
         m_CurrentState = MAILFROMSENT;
         LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 4");
         return;
      }

      if (m_CurrentState == MAILFROMSENT)
      {
         if (IsPositiveCompletion(iCode))
         {
            // --- Server accepted mail from. Go to header/rcpt to state.
            m_CurrentState = RCPTTO;
         }
         else
         {
            LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 5");
            _UpdateAllRecipientsWithError(iCode, Request, false);
         }

      }

      if (m_CurrentState == RCPTTO)
      {
         LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 6");

         shared_ptr<MessageRecipient> pRecipient = _GetNextRecipient();
         if (!pRecipient) 
         {
            _SendQUIT();
            return;
         }
         
         String sRecipient = pRecipient->GetAddress();
         String sData = "RCPT TO:<" + sRecipient + ">";
         _SendData(sData);
         m_CurrentState = RCPTTOSENT;

         return;

      }

      if (m_CurrentState == RCPTTOSENT)
      {
         if (m_iCurRecipient < m_vecRecipients.size())
         {
            if (IsPositiveCompletion(iCode))
            {
               _actualRecipients.insert(m_vecRecipients[m_iCurRecipient]);
            }
            else
            {
               _UpdateRecipientWithError(iCode, Request, m_vecRecipients[m_iCurRecipient], false);
            }
         }

         shared_ptr<MessageRecipient> pRecipient = _GetNextRecipient();
         if (pRecipient)
         {
            // Send next recipient.
            _SendData("RCPT TO:<" + pRecipient->GetAddress() + ">");
            m_CurrentState = RCPTTOSENT;
         }
         else
         {
            if (_actualRecipients.size() == 0)
            {
               _SendQUIT();
               return;
            }
            
            m_CurrentState = DATAQUESTION;
         }
      }

      if (m_CurrentState == DATAQUESTION)
      {
         _SendData("DATA");
         m_CurrentState = DATA;
         LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 7");
         return;
      }

      if (m_CurrentState == DATA)
      {
         if (IsPositiveIntermediate(iCode))
         {
            // Send the data!
            const String fileName = PersistentMessage::GetFileName(m_pDeliveryMessage);
            LOG_DEBUG("SMTPClientConnection::~_BEFORE SendFile");
            _StartSendFile(fileName);
            LOG_DEBUG("SMTPClientConnection::~_AFTER SendFile");
            return;
         }
      }

      if (m_CurrentState == DATASENT)
      {
            LOG_DEBUG("SMTPClientConnection::~_BEFORE SendQUIT");
         _SendQUIT();
            LOG_DEBUG("SMTPClientConnection::~_AFTER SendQUIT");

         if (IsPositiveCompletion(iCode))
         {
            _UpdateSuccessfulRecipients();
            LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 9");
            return;
         }
         else
         {
            _UpdateAllRecipientsWithError(iCode, Request, false);
            LOG_DEBUG("SMTPClientConnection::~_ParseASCII() - 10");
         }

         return;
      }

      if (m_CurrentState == QUITSENT)
      {     
         // We just received a reply on our QUIT. Time to disconnect.
         m_bPendingDisconnect = true;
         PostDisconnect();
      }
   }
示例#29
0
   void 
   IMAPSort::CacheHeaderFields_(std::shared_ptr<IMAPConnection> pConnection,
                                const std::vector<std::pair<int, std::shared_ptr<Message> > > &vecMessages, 
                                const std::map<__int64, String > &databaseMetaData, 
                                SortField &sortField,
                                std::map<__int64, String> &mapHeaderFields)
   {
      mapHeaderFields.clear();

      String sHeaderField;

      switch (sortField)
      {
      case From:
         sHeaderField = "From";
         break;
      case Subject:
         sHeaderField = "Subject";
         break;
      case To:
         sHeaderField = "To";
         break;
      case CC:
         sHeaderField = "CC";
         break;
      case Date:
         sHeaderField = "Date";
         break;      
      }

      // Cache the header field for all messages.
      bool bTrimLeadingSpecialCharacters = (sortField == From || sortField == To || sortField == CC);

      std::vector<std::pair<int, std::shared_ptr<Message> > >::const_iterator iter = vecMessages.begin();
      std::vector<std::pair<int, std::shared_ptr<Message> > >::const_iterator iterEnd = vecMessages.end();

      for (; iter != iterEnd; iter++)
      {
         // Fetch message.
         const std::shared_ptr<Message> p1 = (*iter).second;

         String sFieldValue = "";

         // Read message and parse out the value from the header.
         std::map<__int64, String >::const_iterator dbMetaIter = databaseMetaData.find(p1->GetID());
         
         if (dbMetaIter == databaseMetaData.end())
         {
            String fileName = PersistentMessage::GetFileName(pConnection->GetAccount(), p1);

            AnsiString sHeader = PersistentMessage::LoadHeader(fileName);

            MimeHeader oHeader;oHeader.Load(sHeader, sHeader.GetLength());
            sFieldValue = oHeader.GetUnicodeFieldValue(sHeaderField);

            if (sortField == Date)
            {
               DateTime dt = Time::GetDateTimeFromMimeHeader(sFieldValue);
               sFieldValue = Time::GetTimeStampFromDateTime(dt);
            }
         }
         else
         {
            sFieldValue = (*dbMetaIter).second;
         }

         if (sortField == Date && sFieldValue.IsEmpty())
         {
             /*
              * RFC 5256 "2.2. Sent Date" chapter. If the sent date cannot be determined (a Date: header is missing or cannot be parsed), 
              * the INTERNALDATE for that message is used as the sent date.
              */
            sFieldValue = p1->GetCreateTime();
         }

         // Convert the string to upper case. The sorting should be
         // case insensitive. Otherwise b will come before A.
         sFieldValue.ToUpper();

         // Remove leading ". If we sort on From, "Test" should come in 
         // same position as Test. (quotes / no quotes)
         if (bTrimLeadingSpecialCharacters)
         {
            sFieldValue.TrimLeft(_T("\""));
            sFieldValue.TrimLeft(_T("<"));
         }

         // Cache the header
         mapHeaderFields[p1->GetID()] = sFieldValue;
      }
   }
   void 
   SMTPVacationMessageCreator::CreateVacationMessage(shared_ptr<const Account> recipientAccount, 
                                        const String &sToAddress, 
                                        const String &sVacationSubject, 
                                        const String &sVacationMessage,
                                        const shared_ptr<Message> pOriginalMessage)
   {
      
      
      
      
      if (!_CanSendVacationMessage(recipientAccount->GetAddress(), sToAddress))
         return; // We have already notified this user.
      
      LOG_DEBUG("Creating out-of-office message.");      

      String sModifiedSubject = sVacationSubject;
      String sModifiedBody = sVacationMessage;

      const String originalFileName = PersistentMessage::GetFileName(recipientAccount, pOriginalMessage);

      if (sModifiedSubject.Find(_T("%")) >= 0 || sModifiedBody.Find(_T("%")) >= 0)
      {
         // Replace macros in the string.
         MimeHeader header;
         AnsiString sHeader = PersistentMessage::LoadHeader(originalFileName);
         header.Load(sHeader, sHeader.GetLength(), true);

         String sOldSubject;
         if (header.GetField("Subject"))
            sOldSubject = header.GetField("Subject")->GetValue();

         sModifiedSubject.ReplaceNoCase(_T("%SUBJECT%"), sOldSubject);
         sModifiedBody.ReplaceNoCase(_T("%SUBJECT%"), sOldSubject);
      }

      if (sModifiedSubject.GetLength() == 0)
      {
         // Parse out the subject in the original
         // message, so that we can Re: that..
         MimeHeader header;

         AnsiString sHeader = PersistentMessage::LoadHeader(originalFileName);
         header.Load(sHeader, sHeader.GetLength(), true);

         String sOldSubject;
         if (header.GetField("Subject"))
            sOldSubject = header.GetField("Subject")->GetValue();

         sModifiedSubject = "Re: " + sOldSubject;
      }


      // Send a copy of this email.
      shared_ptr<Message> pMsg = shared_ptr<Message>(new Message());

      pMsg->SetState(Message::Delivering);
      pMsg->SetFromAddress(recipientAccount->GetAddress());

      const String newFileName = PersistentMessage::GetFileName(pMsg);

      shared_ptr<MessageData> pNewMsgData = shared_ptr<MessageData>(new MessageData());
      pNewMsgData->LoadFromMessage(newFileName, pMsg);
      
      // Required headers
      pNewMsgData->SetReturnPath(recipientAccount->GetAddress());
      pNewMsgData->GenerateMessageID();
      pNewMsgData->SetSentTime(Time::GetCurrentMimeDate());
      pNewMsgData->SetFieldValue("Content-Type", "text/plain; charset=\"utf-8\"");

      // Optional headers
      pNewMsgData->SetFrom(recipientAccount->GetAddress());
      pNewMsgData->SetTo(sToAddress);
      pNewMsgData->SetSubject(sModifiedSubject);
      pNewMsgData->SetBody(sModifiedBody);
	  pNewMsgData->SetAutoReplied();
      pNewMsgData->IncreaseRuleLoopCount();
      
      // Write message data
      pNewMsgData->Write(newFileName);

      // Add recipients.
      bool recipientOK = false;
      RecipientParser recipientParser;
      recipientParser.CreateMessageRecipientList(sToAddress, pMsg->GetRecipients(), recipientOK);

      // Save message
      if (pMsg->GetRecipients()->GetCount() > 0)
         PersistentMessage::SaveObject(pMsg);

      // Tell app to submit mail
      Application::Instance()->SubmitPendingEmail();  
   }