!!!IMPORTANT!!! The original code had some issues and was not able to work. Using the To.Array() did only resulted in no error message on the Update. This resulted in a E-Mail with missing information in the "TO" field. (the field was empty).
WORKING CODE AT THE BOTTOM
How can I delete a already deleted contact email address from the "to" field in all related E-Mails?
Example:
from: user
to: x, y
(x should be removed, the email should look like that)
from: user
to: y
I tried it with C# (Don't use this! Use the code below)
var queryEmail = new QueryExpression("email");
queryEmail.Distinct = true;
queryEmail.ColumnSet.AddColumns("subject", "to", "activityid");
queryEmail.AddOrder("subject", OrderType.Ascending);
var email_activityparty = queryEmail.AddLink("activityparty", "activityid", "activityid");
email_activityparty.EntityAlias = "ae";
email_activityparty.Columns.AddColumns("partyid");
email_activityparty.LinkCriteria.AddCondition("partyid", ConditionOperator.Equal, "27d56488-b5ec-e811-a2b8-00505687c621");
EntityCollection emails = service.RetrieveMultiple(queryEmail);
Guid guidToCompare = new Guid("27d56488-b5ec-e811-a2b8-00505687c621");
Dictionary<Guid, string> processed = new Dictionary<Guid, string>();
foreach (Entity email in emails.Entities)
{
EntityCollection to = email.GetAttributeValue<EntityCollection>("to");
List<EntityReference> toUpdate = new List<EntityReference>();
foreach (Entity e in to.Entities)
{
EntityReference partyId = e.GetAttributeValue<EntityReference>("partyid");
if (partyId.Id != guidToCompare)
{
toUpdate.Add(partyId);
}
else
{
var dropped = partyId.Id;
}
}
email["to"] = toUpdate;
//Update record
service.Update(email);
}
But I got this error on the update:
{"The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter schemas.microsoft.com/.../Services:entity. The InnerException message was 'Error in line 1 position 1349. Element 'schemas.datacontract.org/.../System.Collections.Generic:value' contains data from a type that maps to the name 'System.Collections.Generic:List`1'. The deserializer has no knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName method on your DataContractResolver to return a non-null value for name 'List`1' and namespace 'System.Collections.Generic'.'. Please see InnerException for more details."}
Inner Exception: null
Just deactivating the contact will not work, since they named the contact e-mail address like our queue and now it does have multiple connections. If I just delete it, the related entities will generate a error. (For example: If you try the "answer all" button in a email.)
Any ideas would be very nice!
EDIT: I had to rework my Code since it didn't worked. Here is the
Working code:
Dictionary<Guid, string> processed = new Dictionary<Guid, string>();
Guid guidToCompare = new Guid("27d56488-b5ec-e811-a2b8-00505687c621");
string connectionString = "AuthType=AD;Url=http://SERVER/ORG";
CrmServiceClient conn = new CrmServiceClient(connectionString);
IOrganizationService service = (IOrganizationService)conn.OrganizationWebProxyClient != null ? (IOrganizationService)conn.OrganizationWebProxyClient : (IOrganizationService)conn.OrganizationServiceProxy;
var queryEmail = new QueryExpression("email");
queryEmail.Distinct = true;
queryEmail.ColumnSet.AddColumns("subject", "to", "from", "activityid", "statuscode", "statecode");
queryEmail.AddOrder("subject", OrderType.Ascending);
var email_activityparty = queryEmail.AddLink("activityparty", "activityid", "activityid");
email_activityparty.Columns.AddColumns("partyid");
email_activityparty.LinkCriteria.AddCondition("partyid", ConditionOperator.Equal, "27d56488-b5ec-e811-a2b8-00505687c621");
EntityCollection emails = service.RetrieveMultiple(queryEmail);
foreach (Entity email in emails.Entities)
{
EntityCollection to = email.GetAttributeValue<EntityCollection>("to");
List<Entity> entityList = new List<Entity>();
foreach (Entity party in to.Entities)
{
EntityReference partyId = party.GetAttributeValue<EntityReference>("partyid");
// sort the unwantend party out
if (partyId != null && partyId.Id != guidToCompare)
{
entityList.Add(party);
if(!processed.ContainsKey(email.Id))
processed.Add(email.Id, string.Format(email.GetAttributeValue<string>("subject")));
}
else
{
//(just to see what is droped)
if(partyId != null)
{
var dropped = partyId.Id;
}
}
}
EntityCollection toUpdate = new EntityCollection();
foreach (Entity party in entityList)
{
toUpdate.Entities.Add(party);
}
email["to"] = toUpdate;
// Get state
OptionSetValue statecode = email.GetAttributeValue<OptionSetValue>("statecode"); // 1
OptionSetValue statuscode = email.GetAttributeValue<OptionSetValue>("statuscode"); //2
EntityReference emailRef = email.ToEntityReference();
// Set current email state to draft
SetStateRequest stateDraft = new SetStateRequest();
stateDraft.State = new OptionSetValue(0);
stateDraft.Status = new OptionSetValue(1);
stateDraft.EntityMoniker = emailRef;
SetStateResponse stateSetToDraft = (SetStateResponse)service.Execute(stateDraft);
//Update record
service.Update(email);
// Revert state
SetStateRequest stateOrigin = new SetStateRequest();
stateOrigin.State = statecode;
stateOrigin.Status = statuscode;
stateOrigin.EntityMoniker = emailRef;
SetStateResponse stateSetToOrigin = (SetStateResponse)service.Execute(stateOrigin);
}
var result = processed;