private static MessageStatus RunUnderTableBasedExceptionHandler(IMessageConverter converter, StoreDriverDelegate workerFunction)
        {
            MessageStatus messageStatus = MessageStatus.Success;

            StorageExceptionHandler.diag = converter.Tracer;
            try
            {
                workerFunction();
            }
            catch (Exception exception)
            {
                messageStatus = StorageExceptionHandler.tableBasedExceptionHandler.Handle(converter.IsOutbound ? "Submission" : "Delivery", exception, converter, StorageExceptionHandler.MailboxDeliveryFastQueueRetryInterval, StorageExceptionHandler.QuarantinedMailboxRetryInterval);
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            return(messageStatus);
        }
        private static MessageStatus GetMessageStatus <T>(IMessageConverter converter, MapiRetryableException mapiException, T storageException) where T : Exception
        {
            string        name = mapiException.GetType().Name;
            string        key;
            MessageStatus messageStatus;

            switch (key = name)
            {
            case "MapiExceptionMailboxInTransit":
            case "MapiExceptionServerPaused":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.Skip : MessageAction.Reroute, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false), storageException));

            case "MapiExceptionDismountInProgress":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.RetryQueue : MessageAction.Reroute, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false), storageException));

            case "MapiExceptionLogonFailed":
                return(new MessageStatus(MessageAction.Retry, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.LogonFailure), storageException));

            case "MapiExceptionJetErrorLogWriteFail":
            case "MapiExceptionJetErrorDiskIO":
            case "MapiExceptionJetErrorCheckpointDepthTooDeep":
                return(new MessageStatus(MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.MailboxIOError), storageException));

            case "MapiExceptionJetErrorInstanceUnavailable":
                return(new MessageStatus(MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.MailboxIOError), storageException));

            case "MapiExceptionNetworkError":
                messageStatus = new MessageStatus(MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.MailboxServerOffline), storageException);
                messageStatus.RetryInterval = new TimeSpan?(StorageExceptionHandler.MailboxDeliveryFastQueueRetryInterval);
                return(messageStatus);

            case "MapiExceptionRpcServerTooBusy":
            case "MapiExceptionSessionLimit":
            case "MapiExceptionNotEnoughMemory":
                messageStatus = new MessageStatus(converter.IsOutbound ? MessageAction.RetryMailboxServer : MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, name, false), storageException);
                messageStatus.RetryInterval = new TimeSpan?(StorageExceptionHandler.MailboxDeliveryFastQueueRetryInterval);
                return(messageStatus);

            case "MapiExceptionMaxThreadsPerMdbExceeded":
                messageStatus = new MessageStatus(MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.MailboxServerMaxThreadsPerMdbExceeded), storageException);
                messageStatus.RetryInterval = new TimeSpan?(StorageExceptionHandler.MailboxDeliveryFastQueueRetryInterval);
                return(messageStatus);

            case "MapiExceptionMaxThreadsPerSCTExceeded":
                messageStatus = new MessageStatus(converter.IsOutbound ? MessageAction.Retry : MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.MapiExceptionMaxThreadsPerSCTExceeded), storageException);
                messageStatus.RetryInterval = new TimeSpan?(StorageExceptionHandler.MailboxDeliveryFastQueueRetryInterval);
                return(messageStatus);

            case "MapiExceptionRpcOutOfMemory":
            case "MapiExceptionRpcOutOfResources":
            case "MapiExceptionRpcServerOutOfMemory":
            case "MapiExceptionVersionStoreBusy":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.Retry : MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false), storageException));

            case "MapiExceptionSubsystemStopping":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.RetryMailboxServer : MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false), storageException));

            case "MapiExceptionLowDatabaseDiskSpace":
            case "MapiExceptionLowDatabaseLogDiskSpace":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.Retry : MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.MailboxDiskFull), storageException));

            case "MapiExceptionADNotFound":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.RetryMailboxServer : MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.MailboxDiskFull), storageException));

            case "MapiExceptionMailboxQuarantined":
                if (converter.IsOutbound)
                {
                    return(new MessageStatus(MessageAction.Skip, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true), storageException));
                }
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, AckReason.RecipientMailboxQuarantined), storageException));

            case "MapiExceptionRetryableImportFailure":
            case "MapiExceptionBusy":
            case "MapiExceptionDiskError":
            case "MapiExceptionJetErrorOutOfBuffers":
            case "MapiExceptionJetErrorOutOfCursors":
            case "MapiExceptionJetErrorOutOfMemory":
            case "MapiExceptionJetErrorOutOfSessions":
            case "MapiExceptionJetErrorTooManyOpenTables":
            case "MapiExceptionJetErrorTooManyOpenTablesAndCleanupTimedOut":
            case "MapiExceptionJetErrorVersionStoreOutOfMemory":
            case "MapiExceptionJetErrorVersionStoreOutOfMemoryAndCleanupTimedOut":
            case "MapiExceptionNoFreeJses":
            case "MapiExceptionNotEnoughDisk":
            case "MapiExceptionTimeout":
            case "MapiExceptionWait":
            case "MapiExceptionCollision":
                return(new MessageStatus(MessageAction.Retry, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false), storageException));
            }
            messageStatus = new MessageStatus(MessageAction.Retry, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false), storageException);
            return(messageStatus);
        }
        private static MessageStatus GetMessageStatus <T>(IMessageConverter converter, MapiPermanentException mapiException, T storageException) where T : Exception
        {
            string        name = mapiException.GetType().Name;
            string        key;
            MessageStatus messageStatus;

            switch (key = name)
            {
            case "MapiExceptionJetErrorLogDiskFull":
                return(new MessageStatus(MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, AckReason.MailboxDiskFull), storageException));

            case "MapiExceptionADDuplicateEntry":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.RetryMailboxServer : MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, "Duplicated AD entries found"), storageException));

            case "MapiExceptionNoMoreConnections":
                messageStatus = new MessageStatus(converter.IsOutbound ? MessageAction.RetryMailboxServer : MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, SmtpResponse.TooManyConnectionsPerSource), storageException);
                messageStatus.RetryInterval = new TimeSpan?(StorageExceptionHandler.MailboxDeliveryFastQueueRetryInterval);
                return(messageStatus);

            case "MapiExceptionUnknownUser":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.Retry : MessageAction.Reroute, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true), storageException));

            case "MapiExceptionNoReplicaHere":
            case "MapiExceptionWrongServer":
            case "MapiExceptionWrongMailbox":
                return(new MessageStatus(converter.IsOutbound ? MessageAction.Skip : MessageAction.Reroute, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true), storageException));

            case "MapiExceptionClientVersionDisallowed":
                return(new MessageStatus(MessageAction.Reroute, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true), storageException));

            case "MapiExceptionDuplicateDelivery":
                return(new MessageStatus(MessageAction.LogDuplicate, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true), storageException));

            case "MapiExceptionMaxTimeExpired":
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, null, "4.4.1", "connection timed out", true), storageException));

            case "MapiExceptionUnableToComplete":
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, null, "4.4.1", "connection timed out", true), storageException));

            case "MapiExceptionMessageTooBig":
            case "MapiExceptionTooComplex":
            case "MapiExceptionTooBig":
            case "MapiExceptionMaxAttachmentExceeded":
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, null, "5.3.4", "message exceeds fixed system limits", true), storageException));

            case "MapiExceptionTooManyRecips":
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, null, "5.3.3", "too many recipients", true), storageException));

            case "MapiExceptionQuotaExceeded":
            case "MapiExceptionShutoffQuotaExceeded":
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, null, "5.2.2", "mailbox full", true), storageException));

            case "MapiExceptionNoReplicaAvailable":
            case "MapiExceptionFolderDisabled":
            case "MapiExceptionMailboxDisabled":
            case "MapiExceptionAccountDisabled":
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, null, "5.2.1", "mailbox disabled", true), storageException));

            case "MapiExceptionMdbOffline":
                return(new MessageStatus(MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, AckReason.MDBOffline), storageException));

            case "MapiExceptionMaxObjsExceeded":
            case "MapiExceptionRpcBufferTooSmall":
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, null, "4.3.2", "mailbox busy", true), storageException));

            case "MapiExceptionNoAccess":
                return(new MessageStatus(MessageAction.Retry, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false, AckReason.MapiNoAccessFailure), storageException));

            case "MapiExceptionJetErrorPageNotInitialized":
                return(new MessageStatus(MessageAction.RetryQueue, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true, "Database page not initialized"), storageException));

            case "MapiExceptionOutOfMemory":
            case "MapiExceptionTooManyMountedDatabases":
                return(new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true), storageException));

            case "MapiExceptionUnconfigured":
                return(new MessageStatus(MessageAction.Retry, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, false), storageException));
            }
            messageStatus = new MessageStatus(MessageAction.NDR, StorageExceptionHandler.GetExceptionSmtpResponse(converter, storageException, true), storageException);
            return(messageStatus);
        }
        private static MessageStatus RunUnderExplicitExceptionHandler(IMessageConverter converter, StoreDriverDelegate workerFunction)
        {
            MessageStatus messageStatus = MessageStatus.Success;

            StorageExceptionHandler.diag = converter.Tracer;
            try
            {
                workerFunction();
            }
            catch (StoreDriverAgentRaisedException ex)
            {
                if (ex.InnerException == null)
                {
                    TraceHelper.TraceFail(StorageExceptionHandler.diag, 0L, "StoreDriverAgentRaisedException's InnerException is null. It is expected to contain the actual exception that the agent has thrown. StoreDriverAgentRaisedException.Message: {0}; StoreDriverAgentRaisedException.StackTrace: {1}.", new object[]
                    {
                        ex.Message,
                        ex.StackTrace
                    });
                    throw;
                }
                if (ex.InnerException is StoreDriverAgentTransientException)
                {
                    messageStatus = StorageExceptionHandler.GetMessageStatus(converter, (StoreDriverAgentTransientException)ex.InnerException);
                }
                else if (ex.InnerException is SmtpResponseException)
                {
                    messageStatus = StorageExceptionHandler.ProcessSmtpResponseException((SmtpResponseException)ex.InnerException, converter);
                }
                else if (ex.InnerException is ADTransientException)
                {
                    messageStatus = StorageExceptionHandler.GetMessageStatus(converter, (ADTransientException)ex.InnerException);
                }
                else if (ex.InnerException is DataValidationException)
                {
                    messageStatus = StorageExceptionHandler.GetMessageStatus(converter, (DataValidationException)ex.InnerException);
                }
                else if (ex.InnerException is DataSourceOperationException)
                {
                    messageStatus = StorageExceptionHandler.GetMessageStatus(converter, (DataSourceOperationException)ex.InnerException);
                }
                else if (ex.InnerException is StorageTransientException)
                {
                    messageStatus = StorageExceptionHandler.GetMessageStatus(converter, (StorageTransientException)ex.InnerException);
                }
                else if (ex.InnerException is StoragePermanentException)
                {
                    messageStatus = StorageExceptionHandler.GetMessageStatus(converter, (StoragePermanentException)ex.InnerException);
                }
                else if (ex.InnerException is ExchangeDataException)
                {
                    messageStatus = StorageExceptionHandler.ProcessExchangeDataException((ExchangeDataException)ex.InnerException, converter);
                }
                else
                {
                    if (!(ex.InnerException is IOException))
                    {
                        throw;
                    }
                    messageStatus = StorageExceptionHandler.GetMessageStatus(converter, (IOException)ex.InnerException);
                }
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            catch (StoreDriverAgentTransientException storeDriverAgentTransientException)
            {
                messageStatus = StorageExceptionHandler.GetMessageStatus(converter, storeDriverAgentTransientException);
            }
            catch (SmtpResponseException smtpResponseException)
            {
                messageStatus = StorageExceptionHandler.ProcessSmtpResponseException(smtpResponseException, converter);
            }
            catch (ADTransientException unavailableException)
            {
                messageStatus = StorageExceptionHandler.GetMessageStatus(converter, unavailableException);
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            catch (DataValidationException invalidDataException)
            {
                messageStatus = StorageExceptionHandler.GetMessageStatus(converter, invalidDataException);
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            catch (DataSourceOperationException dataSourceOperationException)
            {
                messageStatus = StorageExceptionHandler.GetMessageStatus(converter, dataSourceOperationException);
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            catch (StorageTransientException storageException)
            {
                messageStatus = StorageExceptionHandler.GetMessageStatus(converter, storageException);
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            catch (StoragePermanentException storageException2)
            {
                messageStatus = StorageExceptionHandler.GetMessageStatus(converter, storageException2);
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            catch (ExchangeDataException exchangeDataException)
            {
                messageStatus = StorageExceptionHandler.ProcessExchangeDataException(exchangeDataException, converter);
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            catch (IOException e)
            {
                messageStatus = StorageExceptionHandler.GetMessageStatus(converter, e);
                if (messageStatus.Action == MessageAction.Throw)
                {
                    throw;
                }
            }
            return(messageStatus);
        }