Sending an Email using CRM 2011 Plug In
Hi,
In one of my recent requirements, I had to send an Email using Plug-in (Late Binding). Below is the code snippet.
private void SendEmail(IOrganizationService service, Guid recieverUserId, Guid senderUserId, Guid regardingObjectId, string emailBody, string emailSubject)
{
Entity email = new Entity();
email.LogicalName = “email”;//Set regarding object property (i.e. The entity record, which u want this email associated with)
EntityReference regardingObject = new EntityReference(“{entity_name}”, regardingObjectId);
email.Attributes.Add(“regardingobjectid”,regardingObject);//Defining Activity Parties (starts)
EntityReference from = new EntityReference(“systemuser”, senderUserId);
EntityReference to = new EntityReference(“systemuser”,recieverUserId);
//Derive from party
Entity fromParty = new Entity(“activityparty”);
fromParty.Attributes.Add(“partyid”,from);//Derive to party
Entity toParty = new Entity(“activityparty”);
toParty.Attributes.Add(“partyid”, to);EntityCollection collFromParty = new EntityCollection();
collFromParty.EntityName = “systemuser”;
collFromParty.Entities.Add(fromParty);EntityCollection collToParty = new EntityCollection();
collToParty.EntityName = “systemuser”;
collToParty.Entities.Add(toParty);email.Attributes.Add(“from”,collFromParty);
email.Attributes.Add(“to”, collToParty);//Defining Activity Parties (ends)
//Set subject & body properties
email.Attributes.Add(“subject”,emailSubject);
email.Attributes.Add(“description”, emailBody);//Create email activity
Guid emailID = service.Create(email);
//Sending email
SendEmailRequest reqSendEmail = new SendEmailRequest();
reqSendEmail.EmailId = emailID;//ID of created mail
reqSendEmail.TrackingToken = “”;
reqSendEmail.IssueSend = true;SendEmailResponse res = (SendEmailResponse)service.Execute(reqSendEmail);
}
This is tested code and you can use as it is. Hope it Helps 🙂
hey, looks good, but i have an error by calling the service.create(email).
recieverUserId = systemuserID1
senderUserId = systemuserID2
regardingObjectId = systemuserID1.
im getting an exception because the parent of the email entty is invalid, why ???
By creating emails manually in the crm there are no problem by regarding the email
to an user.
Have you ever get this problem?
Try to run the code without setting the “regardingObject” property.
If it works, Please double check the entity name of parent (i.e., regarding object) you provided.
For further investigation could you please provide me the exception details.
Hi, I tried this code, it executed without any error. But didnt send any email. How?
Hi,
Go to the record’s “Activities” section and check whether the email activity has created or not.
If yes check the email id’s are valid for recepients.
And verify the recepient has subscribed for “Do not send mail” and finally Email router.
I am having the same issue faced by Vidhyut. (“Hi, I tried this code, it executed without any error. But didnt send any email. How?”)
I checked, activities are created and Email is already created but not sent.
Configured E-mail Access Configuration set to Email Router. But not working. How to enable a user to send email. Please give me preferred settings I’m using CRM 2011 Online.
Whom are the recipients in your email?
If recipient has a ‘Contact’, check if the option “Do not send email” is selected in “Contact –> Contact Methods” section.
User in CRM does not have option to enable\disable sending emails.
What should be the message name and primary entity name to register this plugin?
I have created a plugin for sending an email but I would like to call this plugin from WCF Service upon a record creation. I am really stuck on how to consume WCF service from plugin to trigger this email activity. Any help is really appreciated.
Hi Ganesh,
You can consume external WCF service from your Plug-in assembly like any other client application.
Refer this article
http://code.msdn.microsoft.com/How-to-call-External-WCF-42c4490d
Thanks for your prompt response Rajeev. i read this article and followed the same way but I am getting an exception “Microsoft.Crm.Extensibility.InprocessServiceProxy’ cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.”
The code which you have shown above is in Plugin..I just written the same code in my WCF Service..But I am unable to call the WCF service.
Hi Ganesh,
is your WCF service expecting or returning Class object; If yes, make sure to keep [DataContract] tag for Class and [DataMember] for each Class attribute.
No. My service method is a void Method as i mentioned in my previous post it.From my plugin my service should be invoked when i create a record in CRM. Let me share my requirement if you dont mind so that it will be very easy for you to understand. Actually am very new to this CRM..so I am not sure how this works from plugin to CRM.
I tried running this code as it is in my plugin. But it gives me error “The e-mail must have at least one recipient before it can be sent”. I am not sure is there any thing else that I need to change in the above code.
Hi Ganesh,
Make sure in below statement from code, “recieverUserId” is a valid User GUID in your system.
EntityReference to = new EntityReference(“systemuser”,recieverUserId);
Also the User must have “Primary Email” field populated.
In my vehicle entity(vt_vehicle) and I have these fields
1. vt_name
2. vt_make
3. vt_model
4. vt_year
5. vt_vehicleowner
6. emailaddress——this one is autogenerated when i check email option while creating entity.
Now once i create this record and save and email should be created to the vt_vehicleowner. here is my code
public class PostVehicleCreate: Plugin
{
public Guid recieverUserId;
public Guid senderUserId;
public Guid regardingObjectId;
public string emailBody = string.Empty;
public string emailSubject = string.Empty;
public PostVehicleCreate()
: base(typeof(PostVehicleCreate))
{
base.RegisteredEvents.Add(new Tuple<int, string, string, Action>(40, “Create”, “vt_vehicle”, new Action(ExecutePostVehicleCreate)));
}
protected void ExecutePostVehicleCreate(LocalPluginContext localContext)
{
IPluginExecutionContext context = (IPluginExecutionContext)localContext.PluginExecutionContext;
if (context.InputParameters.Contains(“Target”) && (context.InputParameters[“Target”] is Entity))
{
IOrganizationService service = (IOrganizationService)localContext.OrganizationService;
Entity entity = (Entity)context.InputParameters[“Target”];
SendEmail(service, recieverUserId, senderUserId, regardingObjectId, emailBody, emailSubject);
}
}
private void SendEmail(IOrganizationService service, Guid recieverUserId, Guid senderUserId, Guid regardingObjectId, string emailBody, string emailSubject)
{
try
{
Entity email=new Entity();
email.LogicalName = “email”;
//set the regarding object property
//EntityReference regardingObject = new EntityReference(“vt_vehicle”, regardingObjectId);
//email.Attributes.Add(“regardingobjectid”, regardingObject);
//Defining From Attributes
EntityReference from = new EntityReference(“systemuser”, senderUserId);
EntityReference to = new EntityReference(“vt_vehicleowner”, recieverUserId);
Entity fromParty = new Entity(“activityparty”);
fromParty.Attributes.Add(“partyid”, from);
Entity toParty = new Entity(“activityparty”);
toParty.Attributes.Add(“partyid”, to);
EntityCollection ec_from=new EntityCollection();
ec_from.EntityName = “systemuser”;
ec_from.Entities.Add(fromParty);
EntityCollection ec_to = new EntityCollection();
ec_to.EntityName = “vt_vehicle”;
ec_to.Entities.Add(toParty);
email.Attributes.Add(“from”, fromParty);
email.Attributes.Add(“to”, toParty);
//set subject and body properties
email.Attributes.Add(“subject”, emailSubject);
email.Attributes.Add(“description”, emailBody);
//create email activity
Guid emailId = service.Create(email);
//sending email
SendEmailRequest emailRequest=new SendEmailRequest();
emailRequest.EmailId = emailId;
emailRequest.TrackingToken = “”;
emailRequest.IssueSend = true;
SendEmailResponse res = (SendEmailResponse) service.Execute(emailRequest);
}
catch (NullReferenceException ex)
{
throw new NullReferenceException(“Processor Usage” + ex.Message);
}
}
}
Hi Ganesh,
I see you just declared “senderUserId” variable but not providing any value.
Set “senderUserId” variable with valid User GUID.
After i run this code i get this error “The e-mail must have at least one recipient before it can be sent”
But GUID is something autogenerated. How will i set that..is it something like this GUID senderUserId = new GUID; or can you help me how should i set that?
In CRM, every entity has a PrimaryField of type UniqueIdentifier (i.e.,GUID). So when you create Users, every User gets a ‘SystemUserId’ field auto generated.
You can read the ‘SystemUserId’ GUID field and set as ‘To’ Recepient.
I have this in my service1.svc.cs
void IService1.CreateEmailOnVehicleEntity(EmailActivity emailActivity)
{
try
{
CreateRequest reqCreate = new CreateRequest();
Entity emailCreate = new Entity(“email”);
emailCreate[“subject”] = “test subject”;
emailCreate[“description”] = ” test description”;
//emailCreate[“ownerid”] = new EntityReference(“systemuser”, new Guid(OwnerId));
Entity entity = new Entity(“vt_vehicle”);
Entity ap = new Entity();
ap = new Entity(“activityparty”);
Guid ownerGuid = Guid.Empty;
ownerGuid = entity.GetAttributeValue(“vt_owner”).Id;
Entity contact = emailActivity.service.Retrieve(“contact”, ownerGuid, new ColumnSet(new string[] { “fullname” }));
ap[“addressused”] = contact.Attributes[“fullname”];
Entity[] aryTo = { ap };
emailCreate[“to”] = aryTo;
//assigning a systemuser entity to the From attribute for the email acitivity
Entity ap2 = new Entity();
ap2 = new Entity(“activityparty”);
ap2[“partyid”] = new EntityReference(“systemuser”, emailActivity.context.UserId);
Entity[] aryFrom = { ap2 };
emailCreate[“from”] = aryFrom;
// assign a regarding object
// Guid regardingGuid = entity.Id;
//EntityReference regardingObject=new EntityReference(“vt_vehicle”,regardingGuid);
emailCreate[“regardingobjectid”] = entity.ToEntityReference(); //new EntityReference(“vt_vehicle”, regardingGuid);
reqCreate.Target = emailCreate;
CreateResponse resp = (CreateResponse)emailActivity.service.Execute(reqCreate);
}
catch (NullReferenceException ex)
{
throw new NullReferenceException(“Processor Usage” + ex.Message);
}
}
And this one in my Plugin
protected void ExecutePostVehicleCreate(LocalPluginContext localContext)
{
IPluginExecutionContext context = (IPluginExecutionContext)localContext.PluginExecutionContext;
if (context.InputParameters.Contains(“Target”) && (context.InputParameters[“Target”] is Entity))
{
IOrganizationService service = (IOrganizationService)localContext.OrganizationService;
Entity entity = (Entity)context.InputParameters[“Target”];
try
{
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Name = “BasicHttpBinding_IService1”;
myBinding.Security.Mode = BasicHttpSecurityMode.None;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
myBinding.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.None;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;
EndpointAddress endPointAddress = new EndpointAddress(“http://localhost:4353/Service1.svc”);
ChannelFactory factory = new ChannelFactory(myBinding, endPointAddress);
IService1 channel = factory.CreateChannel();
channel.CreateEmailOnVehicleEntity(service, context);
factory.Close();
}
catch (NullReferenceException ex)
{
throw new NullReferenceException(“Processor Usage” + ex.Message);
}
}
}
Now my plugin works fine without error. But when i call the service from my plugin. I get this error.
Unhandled Exception: System.ServiceModel.FaultException`1[[Microsoft.Xrm.Sdk.OrganizationServiceFault, Microsoft.Xrm.Sdk, Version=6.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]: Type ‘Microsoft.Crm.Extensibility.InprocessServiceProxy’ cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.Detail:
-2147220891
OperationStatus
0
SubErrorCode
-2146233088
Type ‘Microsoft.Crm.Extensibility.InprocessServiceProxy’ cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
2014-09-10T18:42:10.6048979Z
[CrmVSSolution_Email.Plugins: CrmVSSolution_Email.Plugins.PostVehicleCreate]
[85ad8342-9c32-e411-9455-0800271b3708: PostVehicleCreate]
Entered CrmVSSolution_Email.Plugins.PostVehicleCreate.Execute(), Correlation Id: 08727641-8866-4746-87ea-79bc23db6c93, Initiating User: afcad25d-bf2c-e411-a5f5-0800271b3708
CrmVSSolution_Email.Plugins.PostVehicleCreate is firing for Entity: vt_vehicle, Message: Create, Correlation Id: 08727641-8866-4746-87ea-79bc23db6c93, Initiating User: afcad25d-bf2c-e411-a5f5-0800271b3708
Exiting CrmVSSolution_Email.Plugins.PostVehicleCreate.Execute(), Correlation Id: 08727641-8866-4746-87ea-79bc23db6c93, Initiating User: afcad25d-bf2c-e411-a5f5-0800271b3708
Hi Rajeev,
I get NullReferenceException Object reference not set to an instance of an object. inside WCF. Could you please suggest me how to fix this.
First create a client (i.e., Console App or Web App) to your WCF service and unit test the code flow.
Its easy to test standalone WCF service than from your Plug-in. Also in your WCF service Trace the exceptions to event viewer to troubleshoot quickly.
Now there is no issue in the plugin. It is throwing NullReferenceException in WCF. this is the service interface i have
[ServiceContract]
[ServiceKnownType(typeof(EmailActivity))]
public interface IService1
{
[OperationContract]
void CreateEmailOnVehicleEntity(EmailActivity emailActivity);
// TODO: Add your service operations here
}
[DataContract]
public class EmailActivity
{
public IOrganizationService _service;
public IPluginExecutionContext _context;
[DataMember]
public IOrganizationService service
{
get
{
return _service;
}
set
{
_service = value;
}
}
[DataMember]
public IPluginExecutionContext context
{
get
{
return _context;
}
set
{
_context = value;
}
}
}
Could you please check this code and the last code and let me know where to enable the tracing and how to troubleshoot this.
I am passing the parameter in the Service1 as CreateEmailonVehicleEntity(IOrganization service)
and in my plugin i am calling channel.CreateEmailonVehicleEntity(service).
But i get an exception Type ‘Microsoft.Crm.Extensibility.InprocessServiceProxy’ cannot be serialized. Consider marking it with the DataContractAttribute attribute, and marking all of its members you want serialized with the DataMemberAttribute attribute. If the type is a collection, consider marking it with the CollectionDataContractAttribute. See the Microsoft .NET Framework documentation for other supported types.
2014-09-10T18:42:10.6048979Z
How do i serialize the IOrganization service. I have already tried using data contract and datamember. But gives the same error.
I have successfully completed this task.
Now I have another task to create custom workflow on creation of record.
I need to check whether the contact in my record has account or not. If not then I have to create one.
I have to create an Entity name bank with one field and link the owner to bank entity.
create a case and link to customer/contact and attach notes with some details like vehicle name , make model etc.
Drop the case in Bank Queue.
Can you sugggest me how should i proceed.
Nice explain