BizTalk SMTP 发送带有附件的邮件(无编排,自定义发送管道组件)

Posted

技术标签:

【中文标题】BizTalk SMTP 发送带有附件的邮件(无编排,自定义发送管道组件)【英文标题】:BizTalk SMTP send mail with attachments (no orchestration, custom send pipeline component) 【发布时间】:2021-12-18 20:31:35 【问题描述】:

我希望有人能帮我解决这个问题,因为当我将 JSON 测试文件放到我的 rcv 文件夹中时,唯一的结果是在 BizTalk 控制台中(在“正在运行的实例”中),消息仅显示“已排队(等待加工)'。我不确定我的问题出在代码中。

我应该收到一个 JSON,其中将包含一些信息和可能的多个附件(Base64 格式),然后将邮件(带有正确格式的附件,即 PDF、txt、xls)发送到某个电子邮件地址.要求之一是不使用编排。但我被困住了,不知道我在做什么了。这个问题与其他问题的不同之处在于我的解决方案中没有编排。一切都将在自定义发送管道组件中处理。 sendpipeline(在编码阶段)确实包含我的自定义组件以及 MIME/SMIME 编码器。我正在使用 SMTP 适配器。

我已经使用向导创建了自定义管道组件,我的初始计划如下:

    接收文件(JSON 格式。它将被转换为 XML 以供进一步处理)。这一切都将在我的 rcv-pipeline 中得到解决,这一步已经对我有效。 从 XML 中挑选出所有必要的变量,以便在电子邮件中发送。这些变量是我想在电子邮件文本中显示的变量。不知道如何更好地解释它。 挑选出 base64 中的所有附件,遍历它们,转换为“常规文件”,然后将它们附加到邮件中(使用正确的文件名、扩展名等)

XML 如下所示:


ArchiveobjectsListErrands
  - ArchiveobjectErrand 
      * UUID (Here are the variables I need to show in the E-mail. The plain text, so to say)
    - ArchiveobjectListPaper
      - Attachments
        * Name
        * Extension
        * Size
        * Base64String (Base64 string which will be needed to be fetched (in GetAttachments) and then processed in (ProcessAttachments))

我的代码如下:

public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(Microsoft.BizTalk.Component.Interop.IPipelineContext pContext, Microsoft.BizTalk.Message.Interop.IBaseMessage pInMsg)
        
            // 1) Read file with XPathNavigator (https://docs.microsoft.com/en-us/dotnet/standard/data/xml/extract-xml-data-using-xpathnavigator)
            XPathNavigator nav = ReadXmlFromMsgBox(pInMsg);

            var outMsg = pContext.GetMessageFactory().CreateMessage();
            outMsg.Context = PipelineUtil.CloneMessageContext(pInMsg.Context);  

            // 2) Pick out the necessary vars that the registrator requires
            GetRegistratorProperties(nav, pContext, outMsg);

            // 3) Read attachments
            var attachments = GetAttachments(pInMsg, nav);

            // 4) Processa attachments
            ProcessAttachments(pContext, outMsg, attachments);

            // 5) Send message along for further processing in the send pipeline
            return outMsg;
        

        private void GetRegistratorProperties(XPathNavigator _nav, IPipelineContext _pContext, IBaseMessage _msg)
        
            var bodyPart = _pContext.GetMessageFactory().CreateMessagePart();             
                     
            bodyPart.ContentType = "text/application";  

            bodyPart.PartProperties.Write("EmailBodyText", "http://schemas.microsoft.com/BizTalk/2003/smtp-properties", "EmailBodyText.");
            bodyPart.PartProperties.Write("Subject", "http://schemas.microsoft.com/BizTalk/2003/smtp-properties", "Registratorsubject - Create errand");

            _msg.AddPart("Body", bodyPart, true); // True for body but false for attachments

        

        private void ProcessAttachments(IPipelineContext _pContext, IBaseMessage _msg, IList<Attachment> _attachments)
        
            
            var msgPart = _pContext.GetMessageFactory().CreateMessagePart();
            //outMsg.Context = PipelineUtil.CloneMessageContext(_msg.Context);  

            int i = 0;            
            foreach (var item in _attachments)
                
                msgPart.PartProperties.Write("FileName", "http://schemas.microsoft.com/BizTalk/2003/mime-properties", item.filnamn+item.extension);
                msgPart.PartProperties.Write("ContentDescription", "http://schemas.microsoft.com/BizTalk/2003/mime-properties", item.contentType);
                msgPart.Data = new MemoryStream(BytesFromBase64String(item.base64));
                //bodyPart.Charset = "utf-8";
                msgPart.ContentType = item.contentType;  

                //_pInMsg.AddPart("Attachment part " + i.ToString(), bodyPart, false); 
                _msg.AddPart("Attachment part " + i.ToString(), msgPart, false); 
                i++;
            
        

        private IList<Attachment> GetAttachments(IBaseMessage pInMsg, XPathNavigator _nav)
        
            XPathNodeIterator iterator =  _nav.Select("Path to attachments in xml");
            IList<Attachment> myList = new List<Attachment>();                        
            

            while (iterator.MoveNext())
            
                XPathNavigator node = iterator.Current;

                Attachment atttachments = new Attachment();              

                atttachments.filenamne = node.SelectSingleNode("Name").Value;
                atttachments.extension = node.SelectSingleNode("Extension").Value;
                atttachments.contentType = node.SelectSingleNode("Mimetype").Value;
                atttachments.base64 = node.SelectSingleNode("Base64String").Value;

                myList.Add(atttachments);
            

            return myList;
        

        private XPathNavigator ReadXmlFromMsgBox(IBaseMessage pInMsg)
        
            // Using XPathNavigator to avoid creating a XMLDoc in memory
            Stream originalMessage = pInMsg.BodyPart.GetOriginalDataStream();

            XPathNavigator _navigator = new XPathDocument(originalMessage).CreateNavigator();
            return _navigator;
                

        [Serializable]
        private class FileStreamFactory : IStreamFactory
        
            byte[] _data;

            public FileStreamFactory(byte[] data)
            
                _data = data;
            

            public Stream CreateStream()
            
                return new MemoryStream(_data);
            
        

        private static byte[] BytesFromBase64String(string msg)
        
            return Convert.FromBase64String(msg);
        
        #endregion
        

如果认为有必要,我可以展示一些 XML 示例文件。由于简洁,也因为它很大,我避免了它。

如果有人能帮助了解代码应该如何实现所需的功能,我将不胜感激,邮件中包含正确命名的有关文件名和扩展名的一些文本和附件。

【问题讨论】:

1) 在一个问题中提出多个问题将使您的问题结束。 2)代码有效还是您有特定问题? 3) 正文和附件只是 MIME 编码电子邮件中的不同部分,通常是纯文本的第一个。 @Dijkgraaf,感谢您的澄清。我希望这篇编辑过的帖子能更清楚地说明问题所在。您说 MIME 编码的电子邮件实际上只有两个部分。那么我在 GetRegistratorProperties 方法中设置的值是否不正确?我正在使用 bodyPart.PartProperties.Write(...) 设置“纯文本属性”(据我所知),然后 _msg.AddPart("Body", bodyPart, true); // 正文为真,附件为假,将所有纯文本字段添加到电子邮件的纯文本段。但这也许是错误的做法? 如果它的状态为'Queued (Awaiting processing)',那么听起来像是期望处理的主机实例就是它,没有处于运行状态。检查发送端口所在的主机实例是否正在运行,并且发送端口处于已启动状态,并且您没有为其设置计划。 @Dijkgraaf,非常感谢您的回答。这让我更进一步。我仍然没有电子邮件出来,但我至少更近了一步。我真的不敢相信微软没有教程或如何实际做到这一点的东西......(PS由于某种原因我不能将你的答案设置为接受的答案。) 那是因为我将其发布为评论,而不是答案。我已将其发布为答案。 【参考方案1】:

正文和附件只是 MIME 编码电子邮件中的不同部分,通常纯文本是第一个。

如果它的状态为“已排队(等待处理)”,那么听起来像

预期处理它的主机实例未处于运行状态。修复:启动主机实例。 发送端口未处于已启动状态。修复:将发送端口设置为已启动 或发送端口上设置了服务窗口。修复:禁用服务窗口。

【讨论】:

以上是关于BizTalk SMTP 发送带有附件的邮件(无编排,自定义发送管道组件)的主要内容,如果未能解决你的问题,请参考以下文章

正文部分在 biztalk 动态 SMTP 发送端口中作为附件发送

使用 smtp 发送带有多个附件的电子邮件

通过 SMTP 发送带有附件、纯文本/文本和文本/html 的电子邮件

为啥我不能通过 BizTalk SMTP 适配器更改正文部分的附件名称?

如何发送带有附件的电子邮件(使用我自己的SMTP服务器)?

带有多个附件 + html 的 SMTP 邮件 Mime