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; }
/// 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); }
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; }
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; }
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; }
//---------------------------------------------------------------------------() // 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; }