Usuario de Windows que obtiene "acceso denegado" del servidor de Exchange

Tengo una aplicación web MVC que utiliza la autenticación de Windows y los servicios web de Exchange. Durante el desarrollo, esto funcionó muy bien, ya que el grupo de aplicaciones en IIS en mi máquina de desarrollo está configurado para ejecutarse bajo mi usuario de Windows y el servidor de Exchange está en el mismo dominio.

Sin embargo, en el servidor web, todas nuestras aplicaciones están configuradas para ejecutarse bajo un usuario del sistema que tiene acceso a todos los servidores de bases de datos, etc.

He estado tratando de suplantar al usuario actual de Windows a través del código de la siguiente manera:

public abstract class ExchangeServiceImpersonator
{
    private static WindowsImpersonationContext _ctx;

    public Task<string> CreateMeetingAsync(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end)
    {
        var tcs = new TaskCompletionSource<string>();
        EnableImpersonation();

        try
        {
            tcs.TrySetResult(CreateMeetingImpersonated(from, to, subject, body, location, begin, end));
        }
        catch(Exception e)
        {
            tcs.TrySetException(e);
        }
        finally
        {
            DisableImpersonation();
        }

        return tcs.Task;
    }

    public abstract string CreateMeetingImpersonated(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end);

    private static void EnableImpersonation()
    {
        WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
        _ctx = winId.Impersonate();
    }

    private static void DisableImpersonation()
    {
        if (_ctx != null)
            _ctx.Undo();
    }
}

Luego, la clase que implementa los métodos abstractos:

public class ExchangeServiceExtensionsBase : ExchangeServiceImpersonator
{
    private ExchangeService _service;

    public ExchangeService Service
    {
        get
        {
            if (this._service == null)
            {
                this._service = new ExchangeService(ExchangeVersion.Exchange2013);
                this._service.Url = new Uri(WebConfigurationManager.AppSettings["ExchangeServer"]);
                this._service.UseDefaultCredentials = true;
            }

            return this._service;
        }
        set { return; }
    }

    public override string CreateMeetingImpersonated(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end)
    {
        //this.Service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, from);

        Appointment meeting = new Appointment(Service);
        string meetingID = Guid.NewGuid().ToString();

        meeting.Subject = subject;
        meeting.Body = "<span style=\"font-family:'Century Gothic'\" >" + body.Replace(Environment.NewLine, "<br/>") + "<br/><br/>" +
            "<span style=\"color: white;\">Meeting Identifier: " + meetingID + "</span></span><br/><br/>";
        meeting.Body.BodyType = BodyType.HTML;
        meeting.Start = begin;
        meeting.End = end;
        meeting.Location = location;
        meeting.ReminderMinutesBeforeStart = 60;

        foreach (string attendee in to)
        {
            meeting.RequiredAttendees.Add(attendee);
        }
        meeting.Save(SendInvitationsMode.SendToAllAndSaveCopy);

        return meetingID;
    }
}

Luego, se accede a los métodos de la siguiente manera:

public static class ExchangeServiceExtensions
{
    public static async Task<string> CreateMeetingAsync(string from, List<string> to, string subject, string body, string location, DateTime begin, DateTime end)
    {
        ExchangeServiceImpersonator serviceImpersonator = new ExchangeServiceExtensionsBase();
        return await serviceImpersonator.CreateMeetingAsync(from, to, subject, body, location, begin, end);
    }
}

Esto todavía funciona en mi máquina de desarrollo local, pero no importa lo que haga, el usuario que accede desde el servidor sigue obteniendo un acceso denegado desde el servidor de intercambio:

La solicitud falló. El servidor remoto devolvió un error: (401) No autorizado.

Intenté dejarlo con las credenciales predeterminadas:

this._service.UseDefaultCredentials = true;

E intentando establecer manualmente las credenciales para el usuario actual (supuestamente suplantado):

this._service.Credentials = new WebCredentials(CredentialCache.DefaultNetworkCredentials);

Además, he intentado usar el intercambioImpersonatedUserId objeto utilizando la dirección de correo electrónico:

this._service.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, from);

que devuelve la siguiente excepción:

La cuenta no tiene permiso para suplantar al usuario solicitado.

Respuestas a la pregunta(2)

Su respuesta a la pregunta