/* This little program demonstrates the parsing of IPAddress strings */ int main(int argc, char ** argv) { CompleteSetupSystem css; PrintExampleDescription(); while(1) { printf("Please enter a string representing an IPv4 or IPv6 numeric host-address: "); fflush(stdout); char buf[1024]; (void) fgets(buf, sizeof(buf), stdin); String s = buf; s = s.Trim(); // get rid of newline ugliness IPAddress ip; if (ip.SetFromString(s) == B_NO_ERROR) { printf("I parsed the string [%s] as IPAddress %s\n", s(), ip.ToString()()); printf(" ip.IsValid() returned %i\n", ip.IsValid()); printf(" ip.IsIPv4() returned %i\n", ip.IsIPv4()); printf(" ip.IsMulticast() returned %i\n", ip.IsMulticast()); printf(" ip.IsStandardLoopbackAddress() returned %i\n", ip.IsStandardLoopbackDeviceAddress()); printf("\n"); } else printf("Error, couldn't parse [%s] as an IPAddress!\n", s()); } return 0; }
bool BLCheck::ClientExistsInDNSBL(const IPAddress &sClientIP, const String &sDNSBLHost, const String &sExpectedResult) { String sReverted = GetRevertedIP(sClientIP.ToString()); if (sReverted.GetLength() == 0) return false; String sCheckHost = sReverted + "." + sDNSBLHost; std::vector<String> foundAddresses; DNSResolver resolver; resolver.GetARecords(sCheckHost, foundAddresses); bool isBlocked = false; // It's possible to specify that one or many intervals are blocked, // using syntax such as 127.0.0.1-5|127.0.0.10-3 const std::set<String> blockedAddresses = ExpandAddresses(sExpectedResult); // // The server may return a list of addresses. // for(const String foundAddress : foundAddresses) { // Go through all list of blocked addresses and see if host is in it. for(const String &blockedAddress : blockedAddresses) { // We not only support ranges, we support wildcards as well. isBlocked = StringParser::WildcardMatch(blockedAddress, foundAddress); if (isBlocked) { // We have a match. No need to continue now. break; } } if (isBlocked) { // We have a match. No need to continue. break; } } // If a message is rejected, it's good to mention in the log which DNSBL // caused the rejection... // http://www.hmailserver.com/forum/viewtopic.php?f=10&t=16221 // String foundAddressesJoined = StringParser::JoinVector(foundAddresses, ", "); if (foundAddressesJoined.IsEmpty()) foundAddressesJoined = "(none)"; String logMessage = Formatter::Format("DNS lookup: {0}, {1} addresses found: {2}, Match: {3}", sCheckHost, foundAddresses.size(), foundAddressesJoined, isBlocked); LOG_SMTP(0,"TCP",logMessage); return isBlocked; }
bool IPAddress::WithinRange(const IPAddress &lower, const IPAddress &upper) const { #ifdef _DEBUG String lower1 = lower.ToString(); String lower2 = upper.ToString(); String thisIP = ToString(); #endif if (GetAddress1() < lower.GetAddress1() || GetAddress1() > upper.GetAddress1()) return false; // If it's an IPv4 address, we don't need to compare the second part. if (_address.is_v4()) return true; if (GetAddress2() < lower.GetAddress2() || GetAddress2() > upper.GetAddress2()) return false; return true; }
String TCPConnection::SafeGetIPAddress() { try { IPAddress address = socket_.remote_endpoint().address(); return address.ToString(); } catch (...) { return ""; } }
bool TCPServer::FireOnAcceptEvent(const IPAddress &remoteAddress, int port) { // Fire an event... if (!Configuration::Instance()->GetUseScriptServer()) return true; shared_ptr<ClientInfo> pCliInfo = shared_ptr<ClientInfo>(new ClientInfo); pCliInfo->SetIPAddress(remoteAddress.ToString()); pCliInfo->SetPort(port); shared_ptr<ScriptObjectContainer> pContainer = shared_ptr<ScriptObjectContainer>(new ScriptObjectContainer); shared_ptr<Result> pResult = shared_ptr<Result>(new Result); pContainer->AddObject("Result", pResult, ScriptObject::OTResult); pContainer->AddObject("HMAILSERVER_CLIENT", pCliInfo, ScriptObject::OTClient); String sEventCaller; String sScriptLanguage = Configuration::Instance()->GetScriptLanguage(); if (sScriptLanguage == _T("VBScript")) sEventCaller.Format(_T("OnClientConnect(HMAILSERVER_CLIENT)")); else if (sScriptLanguage == _T("JScript")) sEventCaller.Format(_T("OnClientConnect(HMAILSERVER_CLIENT);")); ScriptServer::Instance()->FireEvent(ScriptServer::EventOnClientConnect, sEventCaller, pContainer); switch (pResult->GetValue()) { case 1: { // Disconnect the socket immediately. return false; } } return true; }
//////////////////////////////////////////////////////////// /// Send an array of bytes //////////////////////////////////////////////////////////// Socket::Status SocketUDP::Send(const char* Data, std::size_t Size, const IPAddress& Address, unsigned short Port) { // Make sure the socket is valid if (!IsValid()) Create(); // Check parameters if (Data && Size) { // Build the target address sockaddr_in Target; Target.sin_family = AF_INET; Target.sin_port = htons(Port); Target.sin_addr.s_addr = inet_addr(Address.ToString().c_str()); memset(Target.sin_zero, 0, sizeof(Target.sin_zero)); // Loop until every byte has been sent int Sent = 0; int SizeToSend = static_cast<int>(Size); for (int Length = 0; Length < SizeToSend; Length += Sent) { // Send a chunk of data Sent = (int)sendto(mySocket, Data + Length, SizeToSend - Length, 0, reinterpret_cast<sockaddr*>(&Target), sizeof(Target)); // Check errors if (Sent <= 0) return SocketHelper::GetErrorStatus(); } return Socket::Done; } else { // Error... std::cerr << "Cannot send data over the network (invalid parameters)" << std::endl; return Socket::Error; } }
//////////////////////////////////////////////////////////// /// Connect to another computer on a specified port //////////////////////////////////////////////////////////// bool SocketTCP::Connect(unsigned short Port, const IPAddress& HostAddress) { // Make sure our socket is valid if (!IsValid()) Create(); // Build the host address sockaddr_in SockAddr; memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero)); SockAddr.sin_addr.s_addr = inet_addr(HostAddress.ToString().c_str()); SockAddr.sin_family = AF_INET; SockAddr.sin_port = htons(Port); // Connect if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1) { // Error... std::cerr << "Failed to connect socket to host " << HostAddress << std::endl; return false; } return true; }
//////////////////////////////////////////////////////////// /// Connect to another computer on a specified port //////////////////////////////////////////////////////////// Socket::Status SocketTCP::Connect(unsigned short Port, const IPAddress& HostAddress, float Timeout) { // Make sure our socket is valid if (!IsValid()) Create(); // Build the host address sockaddr_in SockAddr; memset(SockAddr.sin_zero, 0, sizeof(SockAddr.sin_zero)); SockAddr.sin_addr.s_addr = inet_addr(HostAddress.ToString().c_str()); SockAddr.sin_family = AF_INET; SockAddr.sin_port = htons(Port); if (Timeout <= 0) { // ----- We're not using a timeout : just try to connect ----- if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) == -1) { // Failed to connect return SocketHelper::GetErrorStatus(); } // Connection succeeded return Socket::Done; } else { // ----- We're using a timeout : we'll need a few tricks to make it work ----- // Save the previous blocking state bool IsBlocking = myIsBlocking; // Switch to non-blocking to enable our connection timeout if (IsBlocking) SetBlocking(false); // Try to connect to host if (connect(mySocket, reinterpret_cast<sockaddr*>(&SockAddr), sizeof(SockAddr)) >= 0) { // We got instantly connected! (it may no happen a lot...) return Socket::Done; } // Get the error status Socket::Status Status = SocketHelper::GetErrorStatus(); // If we were in non-blocking mode, return immediatly if (!IsBlocking) return Status; // Otherwise, wait until something happens to our socket (success, timeout or error) if (Status == Socket::NotReady) { // Setup the selector fd_set Selector; FD_ZERO(&Selector); FD_SET(mySocket, &Selector); // Setup the timeout timeval Time; Time.tv_sec = static_cast<long>(Timeout); Time.tv_usec = (static_cast<long>(Timeout * 1000) % 1000) * 1000; // Wait for something to write on our socket (would mean the connection has been accepted) if (select(static_cast<int>(mySocket + 1), NULL, &Selector, NULL, &Time) > 0) { // Connection succeeded Status = Socket::Done; } else { // Failed to connect before timeout is over Status = SocketHelper::GetErrorStatus(); } } // Switch back to blocking mode SetBlocking(true); return Status; } }
bool TCPConnection::Connect(const AnsiString &remote_ip_address, long remotePort, const IPAddress &localAddress) { #if _DEBUG if (!StringParser::IsValidIPAddress(remote_ip_address)) { ErrorManager::Instance()->ReportError(ErrorManager::High, 5506, "TCPConnection::Connect", Formatter::Format("Attempting to connect to {0} - Not a valid IP address.", remote_ip_address)); } #endif remote_port_ = remotePort; remote_ip_address_ = remote_ip_address; is_client_ = true; LOG_TCPIP(Formatter::Format("Connecting to {0}:{1}...", remote_ip_address_, remotePort)); if (!localAddress.IsAny()) { boost::system::error_code error_code; if (localAddress.GetType() == IPAddress::IPV4) socket_.open(boost::asio::ip::tcp::v4(), error_code); else if (localAddress.GetType() == IPAddress::IPV6) socket_.open(boost::asio::ip::tcp::v6(), error_code); if (error_code) { String errorMessage = Formatter::Format("Failed to open local socket on IP address {0}", localAddress.ToString()); OnCouldNotConnect(errorMessage); ReportError(ErrorManager::Medium, 5520, "TCPConnection::Connect", errorMessage, error_code); return false; } socket_.bind(boost::asio::ip::tcp::endpoint(localAddress.GetAddress(), 0), error_code); if (error_code) { String errorMessage = Formatter::Format("Failed to bind to IP address {0}.", localAddress.ToString()); ReportError(ErrorManager::Medium, 4330, "TCPConnection::Connect", errorMessage, error_code); OnCouldNotConnect(errorMessage); boost::system::error_code ignored_error_code; socket_.close(ignored_error_code); return false; } } // Start an asynchronous resolve to translate the server and service names // into a list of endpoints. StartAsyncConnect_(remote_ip_address, remotePort); return true; }
bool TestConnect::PerformTest(const String &localAddressStr, const String &server, int port, String &result) { boost::asio::io_service io_service; IPAddress localAddress; if (!localAddressStr.IsEmpty()) { if (!localAddress.TryParse(localAddressStr, false)) { result.append(Formatter::Format("ERROR: Unable to parse address {0}.\r\n", localAddressStr)); return false; } else result.append(Formatter::Format("Local address is {0}.\r\n", localAddress.ToString())); } result.append(Formatter::Format("Trying to connect to host {0}...\r\n", server)); // Get a list of endpoints corresponding to the server name. tcp::resolver resolver(io_service); tcp::resolver::query query(AnsiString(server), AnsiString(StringParser::IntToString(port)), tcp::resolver::query::numeric_service); boost::system::error_code errorResolve = boost::asio::error::host_not_found; tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, errorResolve); tcp::resolver::iterator end; if (errorResolve || endpoint_iterator == end) { // Host was not found. String formattedString; formattedString.Format(_T("ERROR: The host name %s could not be resolved.\r\n"), server); result.append(formattedString); return false; } // Try each endpoint until we successfully establish a connection. tcp::socket socket(io_service); boost::system::error_code error = boost::asio::error::host_not_found; while (error && endpoint_iterator != end) { boost::asio::ip::address adr = (*endpoint_iterator).endpoint().address(); String ipAddressString = adr.to_string(); String formattedString; formattedString.Format(_T("Trying to connect to TCP/IP address %s on port %d.\r\n"), ipAddressString, port); result.append(formattedString); socket.close(); IPAddress emptyAddr; bool any = emptyAddr.IsAny(); if (!localAddress.IsAny()) { socket.open(boost::asio::ip::tcp::v4()); boost::system::error_code tempError; socket.bind(boost::asio::ip::tcp::endpoint(localAddress.GetAddress(), 0), tempError); if (tempError) { result.append(Formatter::Format("ERROR: Unable to bind to address {0}.\r\n", localAddress.ToString())); socket.close(); return false; } } socket.connect(*endpoint_iterator++, error); } if (error) { // We were unable to connect. result.append(_T("ERROR: It was not possible to connect.\r\n")); return false; } // Read the response status line. boost::asio::streambuf response; boost::asio::read_until(socket, response, "\r\n"); std::string s; std::istream is(&response); std::getline(is, s, '\r'); result.append(Formatter::Format("Received: {0}.\r\n", String(s))); // Close the socket again. socket.close(); result.append(_T("Connected successfully.\r\n")); return true; }
void TCPServer::HandleAccept(shared_ptr<TCPConnection> pConnection, const boost::system::error_code& error) { if (error.value() == 995) { String sMessage; sMessage.Format(_T("TCP - AcceptEx failed. Error code: %d, Message: %s"), error.value(), String(error.message())); LOG_DEBUG(sMessage); /* 995: The I/O operation has been aborted because of either a thread exit or an application request This happens when the servers are stopped. We shouldn't post any new accepts or do anything else in this situation. */ return; } // Post another AcceptEx. We should always have outstanding unless the // server is stopping, which we are taking care of above. StartAccept(); if (!error) { boost::asio::ip::tcp::endpoint localEndpoint = pConnection->GetSocket().local_endpoint(); boost::asio::ip::tcp::endpoint remoteEndpoint = pConnection->GetSocket().remote_endpoint(); IPAddress localAddress (localEndpoint.address()); IPAddress remoteAddress (remoteEndpoint.address()); String sMessage = Formatter::Format("TCP - {0} connected to {1}:{2}.", remoteAddress.ToString(), localAddress.ToString(), port_); LOG_TCPIP(sMessage); shared_ptr<SecurityRange> securityRange = PersistentSecurityRange::ReadMatchingIP(remoteAddress); if (!securityRange) { LOG_TCPIP("TCP - Connection dropped - No matching IP range."); return; } bool allow = SessionManager::Instance()->GetAllow(sessionType_, securityRange); if (!allow) { // Session creation failed. May not be matching IP range, or enough connections have been created. String message; message.Format(_T("Client connection from %s was not accepted. Blocked either by IP range or by connection limit."), String(remoteAddress.ToString())); LOG_DEBUG(message); // Give option to hold connection for anti-pounding & hopefully minimize DoS // NOTE: We really need max connections per IP as well int iBlockedIPHoldSeconds = IniFileSettings::Instance()->GetBlockedIPHoldSeconds(); if (iBlockedIPHoldSeconds > 0) { Sleep(iBlockedIPHoldSeconds * 1000); message.Format(_T("Held connection from %s for %i seconds before dropping."), String(remoteAddress.ToString()), iBlockedIPHoldSeconds); LOG_DEBUG(message); } return; } if (!FireOnAcceptEvent(remoteAddress, localEndpoint.port())) return; pConnection->SetSecurityRange(securityRange); pConnection->Start(); } else { if (error.value() == 10009 || error.value() == 995) { // Not really errors.. return; } // The outstanding accept-ex failed. This may or may not be an error. Default to being positive. String sMessage; sMessage.Format(_T("TCP - AcceptEx failed. Error code: %d, Message: %s"), error.value(), String(error.message())); LOG_TCPIP(sMessage); } }
void CGUL::Network::HTTPRequest::ConnectSSL(const IPAddress& ip, int port) { host = ip.ToString(); sock->ConnectSSL(ip, port); }
void MessageUtilitiesTester::Test() { std::list<String> headerLines; headerLines.push_back("from host.edu (host.edu [1.2.3.4]) by mail.host.edu (8.8.5) id 004A21; Tue, Mar 18 1997 14:36:17 -0800 (PST)\r\n"); headerLines.push_back("from someone.google (someone.google [1.1.1.1]) by mail.host.edu (8.8.5) id 004A21; Tue, Mar 18 1997 14:36:17 -0800 (PST)\r\n"); String hostName; IPAddress address; bool result = MessageUtilities::RetrieveOriginatingAddress(headerLines, hostName, address); if (result == false) throw; if (hostName != _T("host.edu")) throw; if (address.ToString() != "1.2.3.4") throw; if (address.IsAny()) throw; // If the message headerLines.clear(); headerLines.push_back("by 10.103.12.12 with SMTP id p12cs158601mui; Mon, 14 Dec 2009 08:53:48 -0800 (PST)"); headerLines.push_back("by 10.224.63.1 with SMTP id z1mr3063080qah.314.1260809627613; Mon, 14 Dec 2009 08:53:47 -0800 (PST)"); headerLines.push_back("from e113.en25.com (e113.en25.com [209.167.231.113]) by mx.google.com with ESMTP id 9si6782547iwn.6.2009.12.14.08.53.46; Mon, 14 Dec 2009 08:53:47 -0800 (PST)"); result = MessageUtilities::RetrieveOriginatingAddress(headerLines, hostName, address); if (result == false) throw; if (hostName != _T("e113.en25.com")) throw; if (address.ToString() != "209.167.231.113") throw; if (address.IsAny()) throw; // We are unable to parse this because the IP address isn't within brackets ([]). headerLines.clear(); headerLines.push_back("(qmail 25533 invoked from network); 19 Jan 2010 20:06:21 +0100"); headerLines.push_back("from ded943.maximumasp.com (HELO mail.hmailserver.com) (216.128.26.134)"); result = MessageUtilities::RetrieveOriginatingAddress(headerLines, hostName, address); if (result == true) throw; if (hostName != _T("")) throw; if (address.ToString() != "0.0.0.0") throw; if (!address.IsAny()) throw; }
bool TestConnect::PerformTest(ConnectionSecurity connection_security, const String &localAddressStr, const String &server, int port, String &result) { std::shared_ptr<IOService> io_service_wrapper = Application::Instance()->GetIOService(); IPAddress localAddress; if (!localAddressStr.IsEmpty()) { if (!localAddress.TryParse(localAddressStr, false)) { result.append(Formatter::Format("ERROR: Unable to parse address {0}.\r\n", localAddressStr)); return false; } else result.append(Formatter::Format("Local address is {0}.\r\n", localAddress.ToString())); } result.append(Formatter::Format("Trying to connect to host {0}...\r\n", server)); // Get a list of endpoints corresponding to the server name. tcp::resolver resolver(io_service_wrapper->GetIOService()); tcp::resolver::query query(AnsiString(server), AnsiString(StringParser::IntToString(port)), tcp::resolver::query::numeric_service); boost::system::error_code errorResolve = boost::asio::error::host_not_found; tcp::resolver::iterator endpoint_iterator = resolver.resolve(query, errorResolve); tcp::resolver::iterator end; if (errorResolve || endpoint_iterator == end) { // Host was not found. String formattedString; formattedString.Format(_T("ERROR: The host name %s could not be resolved.\r\n"), server.c_str()); result.append(formattedString); return false; } String last_error_message; // Try each endpoint until we successfully establish a connection. boost::system::error_code error = boost::asio::error::host_not_found; while (error && endpoint_iterator != end) { boost::asio::ip::address adr = (*endpoint_iterator).endpoint().address(); String ipAddressString = adr.to_string(); String formattedString; formattedString.Format(_T("Trying to connect to TCP/IP address %s on port %d.\r\n"), ipAddressString.c_str(), port); result.append(formattedString); std::shared_ptr<Event> disconnectEvent = std::shared_ptr<Event>(new Event()); std::shared_ptr<TestConnectionResult> connection_result = std::make_shared<TestConnectionResult>(); std::shared_ptr<TestConnection> connection = std::make_shared<TestConnection>(connection_security, io_service_wrapper->GetIOService(), io_service_wrapper->GetClientContext(), disconnectEvent, server, connection_result); if (connection->Connect(ipAddressString, port, localAddress)) { connection.reset(); disconnectEvent->Wait(); if (connection_result->GetConnectedSuccesfully()) { result.append(_T("Connected successfully.\r\n")); if (connection_security == CSSSL) { if (connection_result->GetHandshakeCompletedSuccesfully()) { result.append(_T("SSL/TLS handshake completed successfully.\r\n")); return true; } else { result.append(_T("ERROR: Handshake failed.\r\n")); return false; } } else { return true; } } else { result.append(Formatter::Format("ERROR: It was not possible to connect. Error: {0}.\r\n", connection_result->GetErrorMessage())); } } endpoint_iterator++; } // We were unable to connect. result.append(_T("ERROR: Failed to connect to all servers.\r\n")); return false; }
/** @brief Connects to a server on a given ip and port. * @param ip The IP address to connect to. * @param port The port number. */ void Jatta::Network::SocketTCP::Connect(const IPAddress& ip, unsigned short port) { // Check that the IP is valid if (!ip.IsValid()) { throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::ADDRESS_INVALID); } // Create a hints variable used to determine the connection configuration. struct addrinfo hints; memset(&hints, 0, sizeof(addrinfo)); // Check if the IP is an IPv4 or IPv6. if (ip.GetType() == IPAddressType::IPV4) { // Use IPv4. hints.ai_family = AF_INET; } else { // Use IPv6. hints.ai_family = AF_INET6; } // We're setting up a TCP/IP connection, which is a STREAM socket. hints.ai_socktype = SOCK_STREAM; // Convert the port into a string. char portString[6]; # ifdef MSVC sprintf_s(portString, "%d", port); # else sprintf(portString, "%d", port); # endif // Get the address info using the hints. addrinfo* result; if (getaddrinfo(ip.ToString().GetCString(), portString, &hints, &result) != 0) { throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::NO_NETWORK_INTERFACE); } // Create the socket. Because our hints are so strict, we don't have to worry about looping // through the linked list. We should be able to trust that the first result is what we want. sock = socket(result->ai_family, result->ai_socktype, result->ai_protocol); if (sock == INVALID_SOCKET) { freeaddrinfo(result); throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::FAILED_CREATE_SOCKET); } // Make the connection. if (::connect(sock, result->ai_addr, result->ai_addrlen) == SOCKET_ERROR) { freeaddrinfo(result); Close(); throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::FAILED_CONNECT_CALL); } // Make a non-blocking socket. if (!MakeNonBlocking()) { freeaddrinfo(result); Close(); throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::FAILED_NONBLOCKING); } // Turn off the Nagle Algorithm to increase speed. if (!MakeNoDelay()) { freeaddrinfo(result); Close(); throw NetworkException(NetworkExceptionCode::FAILED_CONNECT, NetworkExceptionReason::FAILED_NO_DELAY); } // Free up the address info linked list. freeaddrinfo(result); }
bool SpamProtection::PerformGreyListing(std::shared_ptr<Message> message, const std::set<std::shared_ptr<SpamTestResult> > &spamTestResults, const String &toAddress, const IPAddress &ipaddress) { if (!Configuration::Instance()->GetAntiSpamConfiguration().GetUseGreyListing()) { // The sender is either local, or grey listing is not enabled. We should // not do grey list checks in these cases. return true; } // Check if we should use grey listing for the recipient domain. String sRecipientDomain = StringParser::ExtractDomain(toAddress); std::shared_ptr<const Domain> pDomain = CacheContainer::Instance()->GetDomain(sRecipientDomain); if (pDomain && !pDomain->GetASUseGreyListing()) { // Grey listing not enabled in domain. Skip it. return true; } // Check if the SPF test has succeeded. If so, maybe we should not do if (Configuration::Instance()->GetAntiSpamConfiguration().GetBypassGreyListingOnSPFSuccess()) { for(std::shared_ptr<SpamTestResult> testResult : spamTestResults) { if (testResult->GetTestName() == SpamTestSPF::GetTestName()) { if (testResult->GetResult() == SpamTestResult::Pass) { // We should not run grey listing since the SPF test has passed LOG_DEBUG("SPF passed, skipping greylisting."); return true; } } } } // Check if the mail is coming from the domain A record or MX record. If so, bypass grey listing. if (Configuration::Instance()->GetAntiSpamConfiguration().GetBypassGreyListingOnMailFromMX()) { String senderDomain = StringParser::ExtractDomain(message->GetFromAddress()); if (senderDomain.GetLength() > 0) { std::vector<String> found_ip_addresses; DNSResolver resolver; resolver.GetARecords(senderDomain, found_ip_addresses); std::vector<HostNameAndIpAddress> host_name_with_addresses; resolver.GetEmailServers(senderDomain, host_name_with_addresses); for(HostNameAndIpAddress host_and_ip : host_name_with_addresses) found_ip_addresses.push_back(host_and_ip.GetIpAddress()); String actualFromAddress = ipaddress.ToString(); for(String found_ip_address : found_ip_addresses) { if (found_ip_address.CompareNoCase(actualFromAddress) == 0) { // The message is coming from either an A record or a MX record. Skip greylisting. LOG_DEBUG("Mail coming from A or MX record. Skipping grey listing."); return true; } } } } // Grey listing is enabled, and there's no reason to skip it. Go ahead! if (!GreyListingAllowSend(message->GetFromAddress(), toAddress, ipaddress)) return false; return true; }