void
   POP3ClientConnection::ParseData(const AnsiString &sRequest)
   {
      command_buffer_.append(sRequest);
      command_buffer_.append("\r\n");

      bool is_awaiting_multiline_response  = current_state_ == StateCAPASent ||
                                             current_state_ == StateUIDLRequestSent;

      if (is_awaiting_multiline_response)
      {
         bool multiline_response_completed = sRequest == "." ||
                                             !CommandIsSuccessfull_(command_buffer_);

         if (!multiline_response_completed)
         {
            EnqueueRead();
            return;
         }
      }

      bool postReceive = InternalParseData(command_buffer_);

      // The ASCII buffer has been parsed, so we
      // may clear it now.
      command_buffer_.Empty();

      if (postReceive)
         EnqueueRead();
   }
   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();
   }
 void
 POP3ClientConnection::OnHandshakeCompleted()
 {
    if (GetConnectionSecurity() == CSSSL)
       EnqueueRead();
    else if (GetConnectionSecurity() == CSSTARTTLSOptional ||
             GetConnectionSecurity() == CSSTARTTLSRequired)
    {
       SendUserName_();
       EnqueueRead();
    }
 }
 void
 SMTPClientConnection::OnHandshakeCompleted()
 {
    if (GetConnectionSecurity() == CSSSL)
       EnqueueRead();
    else if (GetConnectionSecurity() == CSSTARTTLSRequired ||
             GetConnectionSecurity() == CSSTARTTLSOptional)
    {
       ProtocolStateHELOEHLO_("");
       EnqueueRead();
    }
 }
   void
   SpamAssassinClient::ParseData(std::shared_ptr<ByteBuffer> pBuf)
   {
      if (!result_)
      {
         String logMessage;
         logMessage.Format(_T("Parsing response from SpamAssassin. Session %d"), GetSessionID());
         LOG_DEBUG(logMessage);

         result_ = std::shared_ptr<File>(new File);
         result_->Open(FileUtilities::GetTempFileName(), File::OTAppend);

         spam_dsize_ = ParseFirstBuffer_(pBuf);
      }

      // Append output to the file
      result_->Write(pBuf);

      total_result_bytes_written_ += pBuf->GetSize();

      if (total_result_bytes_written_ < spam_dsize_)
         EnqueueRead();
      else
         FinishTesting_();
   }
 void
 POP3ClientConnection::OnConnected()
 {
    if (GetConnectionSecurity() == CSNone || 
        GetConnectionSecurity() == CSSTARTTLSOptional ||
        GetConnectionSecurity() == CSSTARTTLSRequired)
       EnqueueRead();
 }
   void
   POP3ClientConnection::ParseData(std::shared_ptr<ByteBuffer> pBuf)
   {
      // Append message buffer with the binary data we've received.
      if (!transmission_buffer_)
      {
         if (!ParseFirstBinary_(pBuf))
         {
            EnqueueRead("");
            return;
         }

         String fileName = PersistentMessage::GetFileName(current_message_);

         // Create a binary buffer for this message. 
         transmission_buffer_ = std::shared_ptr<TransparentTransmissionBuffer>(new TransparentTransmissionBuffer(false));
         if (!transmission_buffer_->Initialize(fileName))
         {
            // We have probably failed to create the file...
            LOG_DEBUG("POP3 External Account: Error creating binary buffer or file.");
            QuitNow_();
            return;
         }

         PrependHeaders_();
      }

      transmission_buffer_->Append(pBuf->GetBuffer(), pBuf->GetSize());
      transmission_buffer_->Flush();

      // Clear the binary buffer.
      pBuf->Empty();

      if (!transmission_buffer_->GetTransmissionEnded())
      {
         EnqueueRead("");
         return;
      }

      // Since this may be a time-consuming task, do it asynchronously
      std::shared_ptr<AsynchronousTask<TCPConnection> > finalizationTask = 
         std::shared_ptr<AsynchronousTask<TCPConnection> >(new AsynchronousTask<TCPConnection>
         (std::bind(&POP3ClientConnection::HandlePOP3FinalizationTaskCompleted_, this), shared_from_this()));

      Application::Instance()->GetAsyncWorkQueue()->AddTask(finalizationTask);
   }
 void
 SMTPClientConnection::OnConnected()
 {
    if (GetConnectionSecurity() == CSNone || 
        GetConnectionSecurity() == CSSTARTTLSRequired ||
        GetConnectionSecurity() == CSSTARTTLSOptional)
    {
       EnqueueRead();
    }
 }
   void
   POP3ClientConnection::HandlePOP3FinalizationTaskCompleted_()
   {
      // The entire message has now been downloaded from the
      // remote POP3 server. Save it in the database and deliver
      // it to the account.
      String fileName = PersistentMessage::GetFileName(current_message_);
      current_message_->SetSize(FileUtilities::FileSize(fileName));

      if (current_message_->GetSize() == 0)
      {
         // Error handling.
         LOG_DEBUG("POP3 External Account: Message is 0 bytes.");
         QuitNow_();
         return;
      }

      ParseMessageHeaders_();

      if (DoSpamProtection_())
      {
         // should we scan this message for virus later on?
         current_message_->SetFlagVirusScan(account_->GetUseAntiVirus());

         FireOnExternalAccountDownload_(current_message_, (*cur_message_).second);

         // the message was not classified as spam which we should delete.
         SaveMessage_();

         // Notify the SMTP deliverer that there is a new message.
         Application::Instance()->SubmitPendingEmail();
      }

      MarkCurrentMessageAsRead_();

      // Switch to ASCII since we're going to request a new message.
      SetReceiveBinary(false);

      // Move on to the next message to download
      cur_message_++;

      RequestNextMessage_();
   
      EnqueueRead("");
   }
   bool
   SpamAssassinClient::SendFileContents_(const String &sFilename)
   {
      String logMessage;
      logMessage.Format(_T("Sending message to SpamAssassin. Session %d, File: %s"), GetSessionID(), sFilename.c_str());
      LOG_DEBUG(logMessage);

      File oFile;
      
      try
      {
         oFile.Open(sFilename, File::OTReadOnly);
      }
      catch (...)
      {
         String sErrorMsg;
         sErrorMsg.Format(_T("Could not send file %s via socket since the file could not be opened."), sFilename.c_str());

         ErrorManager::Instance()->ReportError(ErrorManager::High, 5019, "SMTPClientConnection::SendFileContents_", sErrorMsg);
         return false;
      }

      const int maxIterations = 100000;
      for (int i = 0; i < maxIterations; i++)
      {
         std::shared_ptr<ByteBuffer> pBuf = oFile.ReadChunk(20000);

         if (pBuf->GetSize() == 0)
            break;

         BYTE *pSendBuffer = (BYTE*) pBuf->GetBuffer();
         size_t iSendBufferSize = pBuf->GetSize();

         EnqueueWrite(pBuf);
      }

      EnqueueShutdownSend();

      // Request the response...
      EnqueueRead("");
      
      return true;
   }
   void 
   SMTPClientConnection::ReadAndSend_()
   {
      // Continue sending the file..
      int bufferSize = GetBufferSize();
      std::shared_ptr<ByteBuffer> pBuffer = current_file_.ReadChunk(bufferSize);

      while (pBuffer->GetSize() > 0)
      {
         transmission_buffer_.Append(pBuffer->GetBuffer(), pBuffer->GetSize());

         if (transmission_buffer_.Flush())
         {
            // Data was sent. We'll wait with sending more data until
            // the current data has been sent.
            return; 
         }

         pBuffer = current_file_.ReadChunk(bufferSize);
      }

      // We're done sending!
      current_file_.Close();

      // No more data to send. Make sure all buffered data is flushed.
      transmission_buffer_.Flush(true);

      // We're ready to receive the Message accepted-response.
      // No \r\n on end because EnqueueWrite adds
      EnqueueWrite_("\r\n.");

      EnqueueRead();

      // State change moved to AFTER crlf.crlf to help with race condition
      current_state_ = DATASENT;
   }
Example #12
0
 void 
 TCPConnection::EnqueueRead()
 {
    EnqueueRead(GetCommandSeparator());
 }