Dynamics 365利用email实体的DeliverIncomingEmail来做抓取邮件的进一步处理

我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复421或者20200726可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!

关于这个消息的官方文档请参考 DeliverIncomingEmail Action 。

为了方便测试,我建立一个public queue,如下:

 为Queue的mailbox执行Approve Email 和 Test & Enable Mailbox 后确保其Incoming Email Status 和 Outgoing Email Status 都是Success 。

 然后我撰写了一个插件,代码如下,

using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;

namespace DemoPlugins
{
    public class EmailDeliverIncomingPostPlugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            tracingService.Trace($"Enter {this.GetType()} on {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss:ms")}");
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            tracingService.Trace($"context.UserId = {context.UserId}");
            tracingService.Trace($"context.InitiatingUserId = {context.InitiatingUserId}");
            if (context.InputParameters.Contains("ExtraProperties") && context.InputParameters["ExtraProperties"] is Entity)
            {
                tracingService.Trace("InputParameters contains ExtraProperties and ExtraProperties is Entity.");
                var currentEntity = (Entity)context.InputParameters["ExtraProperties"];
                tracingService.Trace($"ExtraProperties Entity Logical Name = { currentEntity.LogicalName},Entity Id = { currentEntity.Id }");
                foreach (var item in currentEntity.Attributes)
                {
                    if (item.Value != null)
                    {
                        tracingService.Trace($"ExtraProperties attribute key = {item.Key} value = {item.Value.ToString()} type = { item.Value.GetType()}");
                    }
                    else
                    {
                        tracingService.Trace($"ExtraProperties attribute key = {item.Key} value = null");
                    }
                }
            }
            else
            {
                tracingService.Trace("InputParameters does not contain ExtraProperties or ExtraProperties are not Entity.");
            }
            int i = 1;
            if (context.InputParameters.Contains("Attachments") && context.InputParameters["Attachments"] is EntityCollection)
            {
                tracingService.Trace("InputParameters contains Attachments and Attachments is EntityCollection.");
                var ec = (EntityCollection)context.InputParameters["Attachments"];
                foreach (var ecEntity in ec.Entities)
                {
                    tracingService.Trace($"Attachment - {i},Entity Logical Name = {ecEntity.LogicalName},Entity Id ={ecEntity.Id}");
                    foreach (var item in ecEntity.Attributes)
                    {
                        if (item.Value != null)
                        {
                            if (item.Value.ToString().Length >= 210)
                            {
                                tracingService.Trace($"Attachments attribute key = {item.Key} value = {item.Value.ToString().Substring(0, 200)} type = { item.Value.GetType()}");
                            }
                            else
                            {
                                tracingService.Trace($"Attachments attribute key = {item.Key} value = {item.Value.ToString()} type = { item.Value.GetType()}");
                            }
                        }
                        else
                        {
                            tracingService.Trace($"Attachments attribute key = {item.Key} value = null type = { item.Value.GetType()}");
                        }
                    }
                    i++;
                }
            }
            else
            {
                tracingService.Trace("InputParameters does not contain Attachments or Attachments are not EntityCollection.");
            }
        }
    }
}

我将其注册到email实体的DeliverIncoming 消息的PostOperation阶段,为了减少影响,我将Execution Mode设置为Asynchronous .

然后我往往这个queue发一封没有附件的邮件,打开Plug-in Trace Log产生的日志如下,这个User是 SYSTEM 账号。

Enter DemoPlugins.EmailDeliverIncomingPostPlugin on 2020-07-26 09:46:44:4644
context.UserId = 4274a1cf-588b-41b4-8901-1c08551bc142
context.InitiatingUserId = 4274a1cf-588b-41b4-8901-1c08551bc142
InputParameters contains ExtraProperties and ExtraProperties is Entity.
ExtraProperties Entity Logical Name = email,Entity Id = 00000000-0000-0000-0000-000000000000
ExtraProperties attribute key = conversationindex value = 0101D6633143B8D6902F5314F04EA808A611CD7546B2 type = System.String
ExtraProperties attribute key = followemailuserpreference value = False type = System.Boolean
ExtraProperties attribute key = correlationmethod value = 0 type = System.Int32
InputParameters contains Attachments and Attachments is EntityCollection.

发一份有附件的邮件,日志如下:

Enter DemoPlugins.EmailDeliverIncomingPostPlugin on 2020-07-26 09:56:59:5659
context.UserId = 4274a1cf-588b-41b4-8901-1c08551bc142
context.InitiatingUserId = 4274a1cf-588b-41b4-8901-1c08551bc142
InputParameters contains ExtraProperties and ExtraProperties is Entity.
ExtraProperties Entity Logical Name = email,Entity Id = 00000000-0000-0000-0000-000000000000
ExtraProperties attribute key = conversationindex value = 0101D663326AC370C067DF46244E8F41F010B7177835 type = System.String
ExtraProperties attribute key = followemailuserpreference value = False type = System.Boolean
ExtraProperties attribute key = correlationmethod value = 0 type = System.Int32
InputParameters contains Attachments and Attachments is EntityCollection.
Attachment - 1,Entity Logical Name = activitymimeattachment,Entity Id =54ea4ca9-5633-40d0-9419-dbcfa1c18642
Attachments attribute key = mimetype value = image/jpeg type = System.String
Attachments attribute key = attachmentcontentid value = [email protected] type = System.String
Attachments attribute key = body value = /9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7 type = System.String
Attachments attribute key = filename value = 罗勇照片_全身.jpg type = System.String
Attachments attribute key = activitymimeattachmentid value = 54ea4ca9-5633-40d0-9419-dbcfa1c18642 type = System.Guid

如果是答复邮件被抓取有啥不一样,我先通过LuoYong Test Queue往我的邮箱发一封邮件,这个邮件与一个订单做了关联,然后我回复邮件,我们通过日志来看:

1. ExtraProperties参数增加了属性 parentactivityid ,类型为Guid,这个值是答复邮件的Guid,有了这个就可以知道邮件是关于那个实体记录,获取关联的实体记录的详细信息。

2. ExtraProperties参数增加了属性 inreplyto ,类型为string,值类似这种 0C27DF54E5964AD88C8EB1A4B0F0576E1D66334DB9AC@LUOYONGMAILFORQUEUE.CRM435740.ONMICROSOFT.COM ,我也不知道用处。

Enter DemoPlugins.EmailDeliverIncomingPostPlugin on 2020-07-26 10:18:31:1831
context.UserId = 4274a1cf-588b-41b4-8901-1c08551bc142
context.InitiatingUserId = 4274a1cf-588b-41b4-8901-1c08551bc142
InputParameters contains ExtraProperties and ExtraProperties is Entity.
ExtraProperties Entity Logical Name = email,Entity Id = 00000000-0000-0000-0000-000000000000
ExtraProperties attribute key = conversationindex value = 015D51E512321D4FBA83806548FAB761C9D66334DB9AF222A0EC8E type = System.String
ExtraProperties attribute key = inreplyto value = <0C27DF54E5964AD88C8EB1A4B0F0576E1D66334DB9AC@LUOYONGMAILFORQUEUE.CRM435740.ONMICROSOFT.COM> type = System.String
ExtraProperties attribute key = followemailuserpreference value = False type = System.Boolean
ExtraProperties attribute key = correlationmethod value = 3 type = System.Int32
ExtraProperties attribute key = parentactivityid value = 6d018be8-27cf-ea11-a813-000d3aa088a2 type = System.Guid
InputParameters contains Attachments and Attachments is EntityCollection.
Attachment - 1,Entity Logical Name = activitymimeattachment,Entity Id =e7d28ef7-abdd-4e2d-bd11-a9ab46d40785
Attachments attribute key = mimetype value = text/plain type = System.String
Attachments attribute key = attachmentcontentid value = [email protected] type = System.String
Attachments attribute key = body value = bHZvX29yZGVyZGVza3JlcXVlc3RzKCkNCi9xdWV1ZXMoOTI5NWZhOWMtNDkxZC1lYTExLWE4MTEtMDAwZDNhMzc4ZjQ3KQ0KL3N5c3RlbXVzZXJzKEB7Ym9keSgnR2V0X09yZGVyX0Rlc2tfUmVjb3JkX0VNRUEnKT9bJ19vd25lcmlkX3ZhbHVlJ119KQ0KDQpjb25j type = System.String
Attachments attribute key = filename value = temp.txt type = System.String
Attachments attribute key = activitymimeattachmentid value = e7d28ef7-abdd-4e2d-bd11-a9ab46d40785 type = System.Guid
Attachment - 2,Entity Logical Name = activitymimeattachment,Entity Id =360999cd-9f0d-46cd-822f-22071c834013
Attachments attribute key = mimetype value = image/png type = System.String
Attachments attribute key = attachmentcontentid value = [email protected] type = System.String
Attachments attribute key = body value = iVBORw0KGgoAAAANSUhEUgAAC7gAAAfQCAIAAADdcIVtAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAHYcAAB2HAY/l8WUAAP+lSURBVHhe7N0NYBTFwf9x2tr6WsFXEBG07VPt86Lt37ZBBfGlFS2iUEVqUaAqgghGFEFAEEENghghQhB5CQqE type = System.String
Attachments attribute key = filename value = 1.png type = System.String
Attachments attribute key = activitymimeattachmentid value = 360999cd-9f0d-46cd-822f-22071c834013 type = System.Guid

那下面我们做点增强,如果答复的邮件是关于 ly_order 实体记录的话(能知道关联的是哪条记录当然你就可以做得更多),我就创建一个新邮件,将收到的邮件的附件发送给我的邮箱 [email protected]

请注意,我这里利用了仅限内部使用的参数 ExtraProperties ,参数中的内容有可能变化而不通知,各位谨慎使用。

using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;

namespace DemoPlugins
{
    public class EmailDeliverIncomingPostPlugin : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
            tracingService.Trace($"Enter {this.GetType()} on {DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss:ms")}");
            IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
            tracingService.Trace($"context.UserId = {context.UserId}");
            tracingService.Trace($"context.InitiatingUserId = {context.InitiatingUserId}");
            IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
            IOrganizationService orgSvc = serviceFactory.CreateOrganizationService(null);
            if (context.InputParameters.Contains("ExtraProperties") && context.InputParameters["ExtraProperties"] is Entity)
            {
                tracingService.Trace("InputParameters contains ExtraProperties and ExtraProperties is Entity.");
                var currentEntity = (Entity)context.InputParameters["ExtraProperties"];
                tracingService.Trace($"ExtraProperties Entity Logical Name = { currentEntity.LogicalName},Entity Id = { currentEntity.Id }");
                if (currentEntity.Contains("parentactivityid"))
                {
                    tracingService.Trace($"ExtraProperties parentactivityid = {currentEntity.GetAttributeValue<Guid>("parentactivityid")}");
                    var replytoEmail = orgSvc.Retrieve("email", currentEntity.GetAttributeValue<Guid>("parentactivityid"), new ColumnSet("regardingobjectid"));
                    if (replytoEmail.Contains("regardingobjectid") && replytoEmail.GetAttributeValue<EntityReference>("regardingobjectid").LogicalName == "ly_order")
                    {
                        tracingService.Trace($"Reply to email is regarding {replytoEmail.GetAttributeValue<EntityReference>("regardingobjectid").LogicalName} with id = {replytoEmail.GetAttributeValue<EntityReference>("regardingobjectid").Id}");
                        Entity fromEntity = new Entity("activityparty");
                        fromEntity["partyid"] = new EntityReference("queue", Guid.Parse("86476289-1fcf-ea11-a813-000d3aa088a2"));
                        Entity toEntity = new Entity("activityparty");
                        toEntity["addressused"] = "[email protected]";
                        Entity emailEntity = new Entity("email");
                        emailEntity["from"] = new Entity[] { fromEntity };
                        emailEntity["to"] = new Entity[] { toEntity };
                        emailEntity["regardingobjectid"] = replytoEmail.GetAttributeValue<EntityReference>("regardingobjectid");
                        emailEntity["subject"] = "罗勇撰写的通过Dynamics 365自动抓取邮件附件发送新邮件";
                        emailEntity["description"] = "<h1>罗勇通过程序创建的邮件</h1>";
                        var emailId = orgSvc.Create(emailEntity);
                        tracingService.Trace($"Created email with id ={emailId}");
                        //如果包括附件,为刚才的邮件添加附件
                        if (context.InputParameters.Contains("Attachments") && context.InputParameters["Attachments"] is EntityCollection)
                        {
                            var attachmentEC = context.InputParameters["Attachments"] as EntityCollection;
                            if (attachmentEC.Entities.Count >= 1)
                            {
                                tracingService.Trace($"The reply email has {attachmentEC.Entities.Count} attachments.");
                                foreach (var attachEntity in attachmentEC.Entities)
                                {
                                    var activityMimeAttachment = new Entity("activitymimeattachment");
                                    activityMimeAttachment["objectid"] = new EntityReference("email", emailId);
                                    activityMimeAttachment["objecttypecode"] = "email";
                                    activityMimeAttachment["filename"] = attachEntity.GetAttributeValue<string>("filename");
                                    activityMimeAttachment["body"] = attachEntity.GetAttributeValue<string>("body");
                                    activityMimeAttachment["mimetype"] = attachEntity.GetAttributeValue<string>("mimetype");
                                    orgSvc.Create(activityMimeAttachment);
                                    tracingService.Trace($"Created an activitymimeattachment for email with id = {emailId}");
                                }
                            }
                        }
                        //别忘了发送邮件
                        SendEmailRequest sendEmailRequest = new SendEmailRequest
                        {
                            EmailId = emailId,
                            IssueSend = true
                        };
                        orgSvc.Execute(sendEmailRequest);
                    }
                }
            }
            else
            {
                tracingService.Trace("InputParameters does not contain ExtraProperties or ExtraProperties are not Entity.");
            }            
        }
    }
}

看我收到了自动转发过来的邮件:

 你可能会问,还能获取其他信息,当然还包括其他信息,比如收件人,邮件标题,邮件内容,发件人,收到邮件的时间等,可以通过官方文档看到包括那些,代码可以通过这样来看下:

            foreach(var item in context.InputParameters)
            {
                if (item.Value != null)
                {
                    tracingService.Trace($"InputParameters key = {item.Key} value = {item.Value.ToString()} type = { item.Value.GetType()}");
                }
                else
                {
                    tracingService.Trace($"InputParameters key = {item.Key} value = null");
                }
            }

我这里提供一个参数值示例,可以看到From的值不只是邮箱,具体情况具体查看。

InputParameters key = MessageId value = <FR1P152MB07091928254D8482F3F57DEE88750@FR1P152MB0709.LAMP152.PROD.OUTLOOK.COM> type = System.String
InputParameters key = From value = "罗 勇" [email protected] type = System.String
InputParameters key = To value = [email protected] type = System.String
InputParameters key = Cc value = type = System.String
InputParameters key = Bcc value = type = System.String
InputParameters key = ReceivedOn value = 7/26/2020 11:16:14 AM type = System.DateTime
InputParameters key = SubmittedBy value = "罗 勇" [email protected] type = System.String
InputParameters key = Importance value = 1 type = System.String
InputParameters key = Body value = body type = System.String
InputParameters key = Attachments value = Microsoft.Xrm.Sdk.EntityCollection type = Microsoft.Xrm.Sdk.EntityCollection
InputParameters key = Subject value = 回复: LuoYong Test Queue给你发一封邮件 CRM:0001001 type = System.String
InputParameters key = ValidateBeforeCreate value = True type = System.Boolean
InputParameters key = ExtraProperties value = Microsoft.Xrm.Sdk.Entity type = Microsoft.Xrm.Sdk.Entity

猜你喜欢

转载自www.cnblogs.com/luoyong0201/p/Dynamics_365_Using_Email_DeliverIncomingEmail_Action.html