class MailDelivrer {

    @VisibleForTesting
    ExecutionResult handleSenderFailedException(Mail mail, SendFailedException sfe) {
        logSendFailedException(sfe);
        EnhancedMessagingException enhancedMessagingException = new EnhancedMessagingException(sfe);
        List<MailAddress> invalidAddresses = AddressesArrayToMailAddressListConverter.getAddressesAsMailAddress(sfe.getInvalidAddresses());
        List<MailAddress> validUnsentAddresses = AddressesArrayToMailAddressListConverter.getAddressesAsMailAddress(sfe.getValidUnsentAddresses());
        if (configuration.isDebug()) {
            LOGGER.debug("Mail {} has initially recipients: {}", mail.getName(), mail.getRecipients());
            if (!invalidAddresses.isEmpty()) {
                LOGGER.debug("Invalid recipients: {}", invalidAddresses);
            }
            if (!validUnsentAddresses.isEmpty()) {
                LOGGER.debug("Unsent recipients: {}", validUnsentAddresses);
            }
        }
        if (!validUnsentAddresses.isEmpty()) {
            if (!invalidAddresses.isEmpty()) {
                mail.setRecipients(invalidAddresses);
                bouncer.bounce(mail, sfe);
            }
            mail.setRecipients(validUnsentAddresses);
            if (enhancedMessagingException.hasReturnCode()) {
                boolean isPermanent = enhancedMessagingException.isServerError();
                return logAndReturn(mail, ExecutionResult.onFailure(isPermanent, sfe));
            } else {
                return logAndReturn(mail, ExecutionResult.temporaryFailure(sfe));
            }
        }
        if (!invalidAddresses.isEmpty()) {
            mail.setRecipients(invalidAddresses);
            return logAndReturn(mail, ExecutionResult.permanentFailure(sfe));
        }

        if (enhancedMessagingException.hasReturnCode() || enhancedMessagingException.hasNestedReturnCode()) {
            if (enhancedMessagingException.isServerError()) {
                return ExecutionResult.permanentFailure(sfe);
            }
        }
        return ExecutionResult.temporaryFailure(sfe);
    }

    public  MailDelivrer(RemoteDeliveryConfiguration configuration, MailDelivrerToHost mailDelivrerToHost, DNSService dnsServer, Bouncer bouncer);
    @VisibleForTesting  MailDelivrer(RemoteDeliveryConfiguration configuration, MailDelivrerToHost mailDelivrerToHost, DnsHelper dnsHelper, Bouncer bouncer);

}