Cuando trabajamos con Exchange Web Services (EWS) Managed API para conectarnos a Exchange Online en Office 365, solemos trabajar con unas determinadas clases de su modelo de objetos que EWS Managed API pone a nuestra disposición.

Una de ellas es EmailMessage. Con esta clase podemos realizar una serie de operaciones como componer un e-mail, guardarlo en una carpeta del buzón, enviarlo, etc.

Para muestra un botón, con el siguiente código componemos un e-mail y lo guardamos como borrador:

[code javascript]

public Email CreateDraft(IEnumerable<string> to, string subject, string body)
{
    var emailMessage = new EmailMessage(this.Service)
        {
            Subject = subject,
            Body = body
        };
    emailMessage.ToRecipients.AddRange(to);

    emailMessage.Save(WellKnownFolderName.Drafts);

    return new Email
        {
            To = emailMessage.ToRecipients.Select(t => t.Address),
            Subject = emailMessage.Subject,
            Body = emailMessage.Body,
        };

}
[/code]

Si depuramos este código observaremos que la clase EmailMessage tiene una propiedad denominada Id.

image

En este caso no le asignaremos ningún valor. Pero al ejecutar el método Save observaremos que automáticamente se rellena al guardarlo en la carpeta borradores.

image

La propiedad Id no es de tipo Guid, ni int, ni string…, ¡es de tipo ItemId! A primera vista observamos una propiedad UniqueId que, a priori, es la que nos servirá para identificar cada correo dentro del buzón.

image

A continuación vamos a recuperar el borrador que hemos creado en el buzón con el siguiente método:

[code javascript]


public
Email GetDraft(string uniqueId) { var itemId = new ItemId(uniqueId); var draft = EmailMessage.Bind(this.Service, itemId); return new Email { To = draft.ToRecipients.Select(t => t.Address), Subject = draft.Subject, Body = draft.Body, UniqueId = draft.Id.UniqueId, }; }

[/code]
Como vemos en el ejemplo, debemos asignar la Id que hemos obtenido antes y a continuación llamar al método Bind.

Lo siguiente que vamos a probar es a recuperar el borrador, modificarlo y volver a guardarlo. Para ello, usaremos el siguiente método:

[code javascript]

public Email UpdateDraft(Email draft)
{
    var itemId = new ItemId(draft.UniqueId);
    var draftEmailmessage = EmailMessage.Bind(this.Service, itemId);

    draftEmailmessage.ToRecipients.Clear();
    foreach (var to in draft.To)
    {
        draftEmailmessage.ToRecipients.Add(to);
    }
    draftEmailmessage.Subject = draft.Subject;
    draftEmailmessage.Body = draft.Body;
    draftEmailmessage.Update(ConflictResolutionMode.AutoResolve);
    return new Email
    {
        To = draftEmailmessage.ToRecipients.Select(t => t.Address),
        Subject = draftEmailmessage.Subject,
        Body = draftEmailmessage.Body,
        UniqueId = draftEmailmessage.Id.UniqueId
    };
}

[/code]
Si estamos depurando observaremos que la propiedad UniqueId de ItemId ha permanecido igual, sin embargo, otra propiedad de la que todavía no hemos hablado, ChangeKey, sí ha cambiado.

¿Qué significa esto? Realmente la manera correcta de identificar unívocamente a un correo en el servidor de Exchange será a través de los dos identificadores, tanto UniqueId como ChangeKey.

Como hemos observado en esta última prueba, cuando creemos un nuevo borrador automáticamente se le asignará tanto un UniqueId como un ChangeKey. A medida que vayamos modificando y guardando este borrador, la propiedad ChangeKey irá variando. Podría decirse como aproximación que ChangeKey vendría a ser el equivalente a un identificador de la versión de un correo.

Por lo tanto, debemos a modificar nuestro código para usar tanto ChangeKey como UniqueId:

[code javascript]

public Email CreateDraft(IEnumerable<string> to, string subject, string body)
{
    var emailMessage = new EmailMessage(this.Service)
        {
            Subject = subject,
            Body = body
        };
    emailMessage.ToRecipients.AddRange(to);

    emailMessage.Save(WellKnownFolderName.Drafts);

    return new Email
        {
            To = emailMessage.ToRecipients.Select(t => t.Address),
            Subject = emailMessage.Subject,
            Body = emailMessage.Body,
            UniqueId = emailMessage.Id.UniqueId,
            ChangeKey = emailMessage.Id.ChangeKey
        };

}
public Email GetDraft(string uniqueId, string changeKey)
{
    var itemId = new ItemId(uniqueId);
    itemId.ChangeKey = changeKey;
    var draft = EmailMessage.Bind(this.Service, itemId);
    return new Email
    {
        To = draft.ToRecipients.Select(t => t.Address),
        Subject = draft.Subject,
        Body = draft.Body,
        UniqueId = draft.Id.UniqueId, 
        ChangeKey = draft.Id.ChangeKey
    };
}

[/code]
Sin embargo, nos encontramos con un problemilla… ¡no podemos asignar valor a ChangeKey!

image

Pero no os preocupéis, podemos resolver este problema mediante Reflection de la siguiente manera:

[code javascript]

public EmailMessage GetEmailMessage(string uniqueId, string changeKey)
{
    var itemId = new ItemId(uniqueId);
    var prop = typeof(ItemId).GetProperty("ChangeKey");
    prop.SetValue(itemId, changeKey, null);
    return EmailMessage.Bind(this.Service, itemId);
} 

[/code]

Finalmente, así quedarían los métodos de crear, recuperar, actualizar y mandar borrador.

[code javascript]

public Email CreateDraft(IEnumerable<string> to, string subject, string body)
{
    var emailMessage = new EmailMessage(this.Service)
        {
            Subject = subject,
            Body = body
        };
    emailMessage.ToRecipients.AddRange(to);

    emailMessage.Save(WellKnownFolderName.Drafts);

    return new Email
        {
            To = emailMessage.ToRecipients.Select(t => t.Address),
            Subject = emailMessage.Subject,
            Body = emailMessage.Body,
            UniqueId = emailMessage.Id.UniqueId,
            ChangeKey = emailMessage.Id.ChangeKey
        };
}

public void SendDraft(Email email)
{
    var draft = GetEmailMessage(email.UniqueId, email.ChangeKey);

    draft.SendAndSaveCopy();
}

public Email GetDraft(string uniqueId, string changeKey)
{
    var draft = GetEmailMessage(uniqueId, changeKey);
    return new Email
    {
        To = draft.ToRecipients.Select(t => t.Address),
        Subject = draft.Subject,
        Body = draft.Body,
        UniqueId = draft.Id.UniqueId,
        ChangeKey = draft.Id.ChangeKey
    };
}

public Email UpdateDraft(Email draft)
{
    var draftEmailmessage = GetEmailMessage(draft.UniqueId, draft.ChangeKey);
    draftEmailmessage.ToRecipients.Clear();
    foreach (var to in draft.To)
    {
        draftEmailmessage.ToRecipients.Add(to);
    }
    draftEmailmessage.Subject = draft.Subject;
    draftEmailmessage.Body = draft.Body;
    draftEmailmessage.Update(ConflictResolutionMode.AutoResolve);
    return new Email
    {
        To = draftEmailmessage.ToRecipients.Select(t => t.Address),
        Subject = draftEmailmessage.Subject,
        Body = draftEmailmessage.Body,
        UniqueId = draftEmailmessage.Id.UniqueId,
        ChangeKey = draftEmailmessage.Id.ChangeKey
    };
}

public EmailMessage GetEmailMessage(string uniqueId, string changeKey)
{
    var itemId = new ItemId(uniqueId);
    var prop = typeof(ItemId).GetProperty("ChangeKey");
    prop.SetValue(itemId, changeKey, null);
    return EmailMessage.Bind(this.Service, itemId);
}  

[/code]

Todavía no existe una documentación clara y amplia respecto a este tema. Esperemos que poco a poco se vaya completando tanto en MSDN como por los developers que nos vamos pegando con ésto.