• 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 = 864B22EF963CE3409F29B6AB1BBE0796@apcprd06.prod.outlook.com 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 = D0FC301D0909374D96114C3DAC2C0B2B@apcprd06.prod.outlook.com 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 = FEAF071CB08BA14992906D6ACA290018@apcprd06.prod.outlook.com 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 实体记录的话(能知道关联的是哪条记录当然你就可以做得更多),我就创建一个新邮件,将收到的邮件的附件发送给我的邮箱 yong.luo@microsoft.com 。

    请注意,我这里利用了仅限内部使用的参数 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"] = "yong.luo@microsoft.com";
                            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 = "罗 勇" luo.yong@hotmail.com type = System.String
    InputParameters key = To value = LuoYongMailforQueue@CRM435740.onmicrosoft.com 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 = "罗 勇" luo.yong@hotmail.com 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
  • 相关阅读:
    js事件监听机制(事件捕获)
    js预解析
    前端工程师也要关注代码版本控制
    BOM跟DOM的区别和关联
    web开发,click,touch,tap事件浅析
    prototype
    CSS:haslayout
    canvas画图
    第一个json解析:ps:(内容待完善)
    json解析实例
  • 原文地址:https://www.cnblogs.com/luoyong0201/p/Dynamics_365_Using_Email_DeliverIncomingEmail_Action.html
Copyright © 2020-2023  润新知