Пример #1
0
   bool 
   SMTPDeliverer::_RunGlobalRules(shared_ptr<Message> pMessage, RuleResult &ruleResult)
   //---------------------------------------------------------------------------()
   // DESCRIPTION:
   // Performs global rules. We will do this on every retry of the message.
   //---------------------------------------------------------------------------()
   {
      shared_ptr<RuleApplier> pRuleApplier = shared_ptr<RuleApplier>(new RuleApplier);
      shared_ptr<Account> emptyAccount;
      pRuleApplier->ApplyRules(ObjectCache::Instance()->GetGlobalRules(), emptyAccount, pMessage, ruleResult);

      if (ruleResult.GetDeleteEmail())
      {
         String sDeleteRuleName = ruleResult.GetDeleteRuleName();

         String sMessage;
         sMessage.Format(_T("SMTPDeliverer - Message %I64d: ")
            _T("Message deleted. Action was taken by a global rule (%s). "),
            pMessage->GetID(), 
            sDeleteRuleName);

         LOG_APPLICATION(sMessage);

         PersistentMessage::DeleteObject(pMessage);
         return false;
      }

      return true;
   }
Пример #2
0
   /// Resolves IP addresses for the recipient servers. This will either be a MX 
   /// lookup, or a A lookup, if SMTP relaying is used.
   bool 
   ExternalDelivery::_ResolveRecipientServer(shared_ptr<ServerInfo> &serverInfo, vector<shared_ptr<MessageRecipient> > &vecRecipients, vector<String> &saMailServers)
   {
      DNSResolver resolver;

      // Resolve the specified hosts.
      bool dnsQueryOK = false;

      if (serverInfo->GetFixed())
      {
         String relayServer = serverInfo->GetHostName();

         LOG_APPLICATION("SMTPDeliverer - Message " + StringParser::IntToString(_originalMessage->GetID()) + ": Relaying to host " + relayServer + ".");      

         vector<String> mailServerHosts;
         if (relayServer.Find(_T("|")) > 0)
            mailServerHosts = StringParser::SplitString(relayServer, "|");
         else
            mailServerHosts.push_back(relayServer);

         boost_foreach(String host, mailServerHosts)
         {
            // The actual resolution of these host names to IP addresses,
            // are taken care of by TCPConnection::Connect.
            saMailServers.push_back(host);
         }
Пример #3
0
   bool 
   Events::FireOnDeliveryStart(std::shared_ptr<Message> pMessage)
   {
      if (!Configuration::Instance()->GetUseScriptServer())
         return true;

      std::shared_ptr<ScriptObjectContainer> pContainer = std::shared_ptr<ScriptObjectContainer>(new ScriptObjectContainer);
      std::shared_ptr<Result> pResult = std::shared_ptr<Result>(new Result);
      pContainer->AddObject("HMAILSERVER_MESSAGE", pMessage, ScriptObject::OTMessage);
      pContainer->AddObject("Result", pResult, ScriptObject::OTResult);
      String sEventCaller = "OnDeliveryStart(HMAILSERVER_MESSAGE)";
      ScriptServer::Instance()->FireEvent(ScriptServer::EventOnDeliveryStart, sEventCaller, pContainer);

      switch (pResult->GetValue())
      {
      case 1:
         {
            String sMessage;
            sMessage.Format(_T("SMTPDeliverer - Message %I64d: ")
               _T("Message deleted. Action was taken by script subscribing to OnDeliveryStart."),
               pMessage->GetID());

            LOG_APPLICATION(sMessage);

            PersistentMessage::DeleteObject(pMessage);             

            return false;
         }
      }

      return true;
   }
   void
   POP3ClientConnection::ParseStateCAPASent_(const String &sData)
   {
      if (!CommandIsSuccessfull_(sData) || !sData.Contains(_T("STLS")))
      {
         // STLS is not supported.
         if (GetConnectionSecurity() == CSSTARTTLSRequired)
         {
            String message = 
               Formatter::Format("The download of messages from external account {0} failed. The external aAccount is configured to use STARTTLS connection security, but the POP3 server does not support it.", account_->GetName());
            
            LOG_APPLICATION(message)
            QuitNow_();
            return;
         }
         else
         {
            SendUserName_();
            return;
         }
      }

      EnqueueWrite_("STLS");
      current_state_ = StateSTLSSent;
   }
Пример #5
0
   void
   SMTPDeliverer::DeliverMessage(shared_ptr<Message> pMessage)
   //---------------------------------------------------------------------------()
   // DESCRIPTION:
   // Submits the next message in the database. 
   //---------------------------------------------------------------------------()
   {
      LOG_DEBUG("Delivering message...");

      if (!pMessage)
      {
         ErrorManager::Instance()->ReportError(ErrorManager::Medium, 4217, "SMTPDeliverer::DeliverMessage()", "The message to deliver was not given.");
         return;
      }

      // Fetch the message ID before we delete the message and it's reset.
      __int64 messageID = pMessage->GetID();

      String sSendersIP;
      RuleResult globalRuleResult;
      if (!_PreprocessMessage(pMessage, sSendersIP, globalRuleResult))
      {
         // Message delivery was aborted during preprocessing.
         return;
      }

      vector<String> saErrorMessages;

      // Perform deliver to local recipients.
      LocalDelivery localDeliverer(sSendersIP, pMessage, globalRuleResult);
      bool messageReused = localDeliverer.Perform(saErrorMessages);

      bool messageRescheduled = false;
      if (pMessage->GetRecipients()->GetCount() > 0)
      {
         // Perform deliveries to external recipients.
         ExternalDelivery externalDeliverer(sSendersIP, pMessage, globalRuleResult);
         messageRescheduled = externalDeliverer.Perform(saErrorMessages);
      }

      // If an error has occurred, now is the time to send an error
      // message back to the author of the email message.
      if (saErrorMessages.size() > 0)
         _SubmitErrorLog(pMessage, saErrorMessages);

      // Unless the message has been re-used, or has been rescheduled for
      // later delivery, we should delete it now.
      bool deleteMessageNow = !messageReused && !messageRescheduled;
      if (deleteMessageNow)
      {
         // Check that we haven't reused this message before we delete it.
         if (pMessage->GetAccountID() > 0)
         {
            String errorMessage;
            errorMessage.Format(_T("Attempting to delete message %I64d even though it's been delivered to user account %I64d ."), messageID, pMessage->GetAccountID());
            ErrorManager::Instance()->ReportError(ErrorManager::High, 5208, "SMTPDeliverer::DeliverMessage", errorMessage);
            return;
         }

         PersistentMessage::DeleteObject(pMessage);   
      }

      String logText;
      logText.Format(_T("SMTPDeliverer - Message %I64d: Message delivery thread completed."), messageID);
      LOG_APPLICATION(logText);

      return;   
   }
Пример #6
0
   bool
   SMTPDeliverer::_HandleInfectedMessage(shared_ptr<Message> pMessage, const String &virusName)
   //---------------------------------------------------------------------------()
   // DESCRIPTION:
   // Called if a virus is found in an email message. Checks in the configuration
   // what we should do with infected messages and does just that.
   //---------------------------------------------------------------------------()
   {
      AntiVirusConfiguration &antiVirusConfig = Configuration::Instance()->GetAntiVirusConfiguration();

      if (antiVirusConfig.AVAction() == AntiVirusConfiguration::ActionDelete)
      {
         // The message should be deleted.

         // Should we notify the recipient?
         if (antiVirusConfig.AVNotifyReceiver())
         {
            // Notify every receiver of the email.
            vector<shared_ptr<MessageRecipient> > &vecRecipients = pMessage->GetRecipients()->GetVector();
            vector<shared_ptr<MessageRecipient> >::iterator iterRecipient = vecRecipients.begin();

            while (iterRecipient != vecRecipients.end())
            {
               SMTPVirusNotifier::CreateMessageDeletedNotification(pMessage, (*iterRecipient)->GetAddress());
               
               iterRecipient++;
            }
         }

         if (antiVirusConfig.AVNotifySender())
            SMTPVirusNotifier::CreateMessageDeletedNotification(pMessage, pMessage->GetFromAddress());

         String logMessage = Formatter::Format("SMTPDeliverer - Message {0}: Message deleted (contained virus {1}).", 
            pMessage->GetID(), virusName);

         LOG_APPLICATION(logMessage);

         PersistentMessage::DeleteObject(pMessage);
         
         return false; // do not continue delivery

      }
      else if (antiVirusConfig.AVAction() == AntiVirusConfiguration::ActionStripAttachments)
      {
         shared_ptr<MessageAttachmentStripper> pStripper = shared_ptr<MessageAttachmentStripper>(new MessageAttachmentStripper());

         pStripper->Strip(pMessage);

         String logMessage = Formatter::Format("SMTPDeliverer - Message {0}: Message attachments stripped (contained virus {1}).", 
            pMessage->GetID(), virusName);

         LOG_APPLICATION(logMessage);

         return true; // continue delivery
      }

      // Weird configuration?
      assert(0);
      
      return false;
   }
Пример #7
0
   //---------------------------------------------------------------------------()
   // DESCRIPTION:
   // Performs preprocessing of the message. Checks that the file exists, runs
   // global rules, virus scanning and mirroring.
   //
   // Returns true if delivery should continue. False if it should be aborted.
   //---------------------------------------------------------------------------()
   bool
   SMTPDeliverer::_PreprocessMessage(shared_ptr<Message> pMessage, String &sendersIP, RuleResult &globalRuleResult)
   {
      // Before we do anything else, check that the message file exists. If the file
      // does not exist, there is nothing to deliver. So if the file does not exist,
      // delete pMessage from the database and report in the application log.
      const String messageFileName = PersistentMessage::GetFileName(pMessage);
      if (!FileUtilities::Exists(messageFileName))
      {
         ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5006, "SMTPDeliverer::DeliverMessage()", "Message " + StringParser::IntToString(pMessage->GetID()) + " could not be delivered since the data file does not exist.");
         PersistentMessage::DeleteObject(pMessage);

         return false;
      }

      if (pMessage->GetRecipients()->GetCount() == 0)
      {
         // No remaining recipients.
         ErrorManager::Instance()->ReportError(ErrorManager::Medium, 5007, "SMTPDeliverer::DeliverMessage()", "Message " + StringParser::IntToString(pMessage->GetID()) + " could not be delivered. No remaining recipients. File: " + messageFileName);

         PersistentMessage::DeleteObject(pMessage);
         return false;
      }

      if (AWStats::GetEnabled())
      {
         sendersIP = MessageUtilities::GetSendersIP(pMessage);
      }

      // Create recipient list.
      String sRecipientList = pMessage->GetRecipients()->GetCommaSeperatedRecipientList();

      String sMessage = Formatter::Format("SMTPDeliverer - Message {0}: Delivering message from {1} to {2}. File: {3}",
                                                pMessage->GetID(), pMessage->GetFromAddress(), sRecipientList, messageFileName);

      LOG_APPLICATION(sMessage);

      // Run the first event in the delivery chain
      if (!Events::FireOnDeliveryStart(pMessage))
      {
         _LogAwstatsMessageRejected(sendersIP, pMessage, "Delivery cancelled by OnDeliveryStart-event");
         return false;
      }

      if (pMessage->GetRecipients()->GetCount() == 0)
      {
         vector<String> saErrorMessages;
         _SubmitErrorLog(pMessage, saErrorMessages);
         PersistentMessage::DeleteObject(pMessage);
         return false;
      }

      // Run virus protection.
      if (!_RunVirusProtection(pMessage))
      {
         _LogAwstatsMessageRejected(sendersIP, pMessage, "Message delivery cancelled during virus scanning");
         return false;
      }

      // Apply rules on this message.
      if (!_RunGlobalRules(pMessage, globalRuleResult))
      {
         _LogAwstatsMessageRejected(sendersIP, pMessage, "Message delivery cancelled during global rules");
         return false;
      }

      // Run the OnDeliverMessage-event
      if (!Events::FireOnDeliverMessage(pMessage))
      {
         _LogAwstatsMessageRejected(sendersIP, pMessage, "Message delivery cancelled during OnDeliverMessage-event");
         return false;
      }

      // Run mirroring
      if (pMessage->GetNoOfRetries() == 0)
      {
         MirrorMessage mirrorer(pMessage);
         mirrorer.Send();
      }

      return true;

   }