none
BT2010 Sending files as attachments via dynamic SMTP port RRS feed

  • Question

  • Hi all,

    I have following orchestration which processes XMl into CSV, stores CSV into file.

    Then CSV have to be emailed as an attachment.

    So I created dynamic SMTP port, and send via below noted code in Construct message block.
    Everything is ok (mails got mailed) except that attachment is not included in the message.
    To dynamic SMTP port is attached MIME pipeline (pipeline with MIME/SMIME encoder).

    Please help, what's wrong? File exists, I also tried existing file, didn't work...

    filePath = @"c:\\temp\messages\csv\" + uqName + ".csv";

    xc = new System.Xml.XmlDocument();
    xc.LoadXml("<html><body>" + filePath + "</body></html>");
    GenericXML = xc;

    GenericXML(SMTP.From) = "info@elinkx.cz";
    GenericXML(SMTP.Subject) = "BT Payment";
    GenericXML(SMTP.EmailBodyText) = "Payments";
    GenericXML(SMTP.SMTPHost) = "localhost";
    GenericXML(SMTP.Attachments) = filePath;


    GenericXML(Microsoft.XLANGs.BaseTypes.ContentType)="text/html";
    SMTPDynPort(Microsoft.XLANGs.BaseTypes.Address) = PaymentMessage.ADRESS;
    SMTPDynPort(Microsoft.XLANGs.BaseTypes.TransportType) = "SMTP"; 

    Orchestration


    Ondřej Spilka


    Thursday, February 23, 2012 2:17 PM

Answers

  • Hello once again.

    The problem was that CSV send port had not set property Delivery Notification = Transmitted. Thus CSV file did not exist while SMTP send shape was reached.

    Finally got it to work with multipart message scenario, where CSV file I read by custom assembly code, but I suppose Attachment scenarion will work too.

    For others I'm posting complet expression content, message declaration and custom assembly methods code...

    Custom assembly classes (project is part of the solution, compiled, GACed, referenced by the BT project) 

    RawString

    using System;
    using System.IO;
    using System.Text;
    using System.Xml.Serialization;
    using System.Runtime.Serialization;
    
    using Microsoft.XLANGs.BaseTypes;
    
    namespace Microsoft.Samples.BizTalk.XlangCustomFormatters
    {
        public abstract class BaseFormatter : IFormatter
        {
            public virtual SerializationBinder Binder
            {
                get { throw new NotSupportedException(); }
                set { throw new NotSupportedException(); }
            }
    
            public virtual StreamingContext Context
            {
                get { throw new NotSupportedException(); }
                set { throw new NotSupportedException(); }
            }
    
            public virtual ISurrogateSelector SurrogateSelector
            {
                get { throw new NotSupportedException(); }
                set { throw new NotSupportedException(); }
            }
    
            public abstract void Serialize(Stream stm, object obj);
            public abstract object Deserialize(Stream stm);
        }
    
        public class RawStringFormatter : BaseFormatter
        {
            public override void Serialize(Stream s, object o)
            {
                RawString rs = (RawString)o;
                byte[] ba = rs.ToByteArray();
                s.Write(ba, 0, ba.Length);
            }
    
            public override object Deserialize(Stream stm)
            {
                StreamReader sr = new StreamReader(stm, true);
                string s = sr.ReadToEnd();
                return new RawString(s);
            }
        }
    
        [CustomFormatter(typeof(RawStringFormatter))]
        [Serializable]
        public class RawString
        {
            [XmlIgnore]
            string _val;
            [XmlIgnore]
            byte[] _array;
    
            public RawString(string s)
            {
                if (null == s)
                    throw new ArgumentNullException();
                _val = s;
            }
    
            public RawString(byte[] arr)
            {
                if (null == arr)
                    throw new ArgumentNullException();
                _array = arr;
            }
    
            public RawString()
            {
            }
    
            public byte[] ToByteArray()
            {
                if (_array == null)
                    return Encoding.UTF8.GetBytes(_val);
                else
                    return _array;
            }
    
    
            public override string ToString()
            {
                if (_array == null)
                    return _val;
                else
                {
                    return Convert.ToBase64String(_array);
                }
            }
    
        }
    }
    Helper class to get file contents into an attachment
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Schema;
    using System.IO;
    using Microsoft.XLANGs.BaseTypes;
    using Microsoft.Samples.BizTalk.XlangCustomFormatters;
    
    
    namespace GClasses
    {
        public class GCargoBTUtils
        {
            /// <summary>
            /// Read file contents into RawString
            /// </summary>
            /// <param name="fileName"></param>
            /// <returns>RawString with byte array or error code</returns>
            public static RawString FileContents(string fileName)
            {
                RawString rs = new RawString("File not loaded (exists?)");
                if ( File.Exists(fileName) )
                {
    
                    using(var fle = File.Open(fileName, FileMode.Open))
                    using(var br = new BinaryReader(fle) )
                    {
                        if (fle.Length < 1000000)
                            rs = new RawString(br.ReadBytes((int)fle.Length));
                        else
                            rs = new RawString(string.Format("Error, file " + fileName + " is to large:{0} bytes", fle.Length));
                    }
                }
                return rs;
            }
        }
    }
    
    Orchestration
    Set DeliveryNotification=Transmitted on CSV send port

    Multipart Message


    "MessageAsignment" expression content
    filePath = @"c:\temp\messages\csv\" + uqName + ".csv"; //global variable
    msgEnvelope.Body = new Microsoft.Samples.BizTalk.XlangCustomFormatters.RawString(filePath);
    msgEnvelope.Attachment= GClasses.GCargoBTUtils.FileContents(filePath);
    msgEnvelope(SMTP.From) = "info@elinkx.cz";
    msgEnvelope(SMTP.Subject) = "BT Payment";
    msgEnvelope(SMTP.EmailBodyText) = "Payments";
    msgEnvelope(SMTP.SMTPHost) = "localhost";
    msgEnvelope.Attachment(Microsoft.XLANGs.BaseTypes.ContentType) = "text/plain";
    msgEnvelope(SMTP.MessagePartsAttachments) = 1;
    msgEnvelope.Attachment(MIME.FileName) = uqName + ".csv";

    SMTPDynPort(Microsoft.XLANGs.BaseTypes.Address) = PaymentMessage.ADRESS;
    SMTPDynPort(Microsoft.XLANGs.BaseTypes.TransportType) = "SMTP"; 

    Cheers and thanks for your assistance...



    Ondřej Spilka

    • Marked as answer by Ondřej Spilka Friday, February 24, 2012 10:34 AM
    Friday, February 24, 2012 10:33 AM

All replies

  • Hi,

    Hi,

    You can use code like below:

    msgEnvelope(SMTP.Subject) = <Email Subject>;
    msgEnvelope(SMTP.From) = <Sender Email>;
    msgEnvelope(SMTP.SMTPHost) = <Email Host name>";
    // This is the default value
    msgEnvelope(SMTP.SMTPAuthenticate) = 0;
    // Set the message text included in the email
    msgEnvelope(SMTP.EmailBodyText) = <Text in body of email>;
    // Important - This is required if the EmailBodyText is set
    msgEnvelope(SMTP.EmailBodyTextCharset) = "utf-8";
    // A value of '1' means include Message Body Part as email attachment
    msgEnvelope(SMTP.MessagePartsAttachments) = 1;

     

    msgEnvelope.EmailBodyString = new Microsoft.XLANGs.CustomFormattersSDK.RawString(“Body”);

    msgEnvelope.EmailBodyString(Microsoft.XLANGs.BaseTypes.ContentType) = "text/plain";

     

    // Important - Change this MIME type if not sending a Text file
    msgEnvelope
    .EmailAttach(Microsoft.XLANGs.BaseTypes.ContentType) = "text/xml";
    // Set the Filename of the attachment
    msgEnvelope.
    EmailAttach = new Microsoft.XLANGs.CustomFormattersSDK.RawString(msg.InnerXml());

    msgEnvelope.EmailAttach(MIME.FileName) = "XMLName.xls";

     

    // We set the Email Address on the Port itself
    Dynamic_Send_Port(Microsoft.XLANGs.BaseTypes.Address) = <recipient email address>;

    Excerpt from this thread.

    HTH

    Steef-Jan Wiggers

    MVP & MCTS BizTalk Server 2010

    http://soa-thoughts.blogspot.com/ | @SteefJan

    If this answers your question please mark it accordingly


    BizTalk

    Thursday, February 23, 2012 3:25 PM
    Moderator
  • And what type is msgEnvelope ?

    Ondřej Spilka

    Thursday, February 23, 2012 3:41 PM
  • Hi,

    The code is just an example, see the link of the thread.

    HTH

    Steef-Jan Wiggers

    MVP & MCTS BizTalk Server 2010

    http://soa-thoughts.blogspot.com/ | @SteefJan

    If this answers your question please mark it accordingly


    BizTalk

    Thursday, February 23, 2012 3:49 PM
    Moderator
  • Sorry, I missed it. Nevertheless I already saw this examples.

    This is different approach, one with SMTP.Attachments is much more suitable for us. Why this is not working?

    On the other side, I'll try this approach with multipart messages.
    Just please can you send simple exmaple how to configure multipart message properly and, how to create it?

    The process of creation multipart messages is uncelar to me. I have construct block, message type setup correctly, but message is "unconstructed".
    Assign plain XmlDocument is message creation?


    Ondřej Spilka

    Thursday, February 23, 2012 3:57 PM
  • Hello Steef,

    so I ported the solution the multipart message scenario. Everything works fine (attachments are attached).
    But the content of the attachment is file name, not the file contents itself. Well, this is logical...

    So is there a way how to attach mapped CSV message into attachments directly from orchestration? In other words, how to encode message in RawString other than use another method in custom assembly? (BTW the fact that assembly must be GACed is let's say uncomfortable - unenlist all orchestartion, remove them, rebuild, deploy, enlist...uuh loooong process for developer )

    I will fiddle with it, but if you know the method it will save a time...

    Thx

    Ondra



    Ondřej Spilka

    Friday, February 24, 2012 6:59 AM
  • Hello once again.

    The problem was that CSV send port had not set property Delivery Notification = Transmitted. Thus CSV file did not exist while SMTP send shape was reached.

    Finally got it to work with multipart message scenario, where CSV file I read by custom assembly code, but I suppose Attachment scenarion will work too.

    For others I'm posting complet expression content, message declaration and custom assembly methods code...

    Custom assembly classes (project is part of the solution, compiled, GACed, referenced by the BT project) 

    RawString

    using System;
    using System.IO;
    using System.Text;
    using System.Xml.Serialization;
    using System.Runtime.Serialization;
    
    using Microsoft.XLANGs.BaseTypes;
    
    namespace Microsoft.Samples.BizTalk.XlangCustomFormatters
    {
        public abstract class BaseFormatter : IFormatter
        {
            public virtual SerializationBinder Binder
            {
                get { throw new NotSupportedException(); }
                set { throw new NotSupportedException(); }
            }
    
            public virtual StreamingContext Context
            {
                get { throw new NotSupportedException(); }
                set { throw new NotSupportedException(); }
            }
    
            public virtual ISurrogateSelector SurrogateSelector
            {
                get { throw new NotSupportedException(); }
                set { throw new NotSupportedException(); }
            }
    
            public abstract void Serialize(Stream stm, object obj);
            public abstract object Deserialize(Stream stm);
        }
    
        public class RawStringFormatter : BaseFormatter
        {
            public override void Serialize(Stream s, object o)
            {
                RawString rs = (RawString)o;
                byte[] ba = rs.ToByteArray();
                s.Write(ba, 0, ba.Length);
            }
    
            public override object Deserialize(Stream stm)
            {
                StreamReader sr = new StreamReader(stm, true);
                string s = sr.ReadToEnd();
                return new RawString(s);
            }
        }
    
        [CustomFormatter(typeof(RawStringFormatter))]
        [Serializable]
        public class RawString
        {
            [XmlIgnore]
            string _val;
            [XmlIgnore]
            byte[] _array;
    
            public RawString(string s)
            {
                if (null == s)
                    throw new ArgumentNullException();
                _val = s;
            }
    
            public RawString(byte[] arr)
            {
                if (null == arr)
                    throw new ArgumentNullException();
                _array = arr;
            }
    
            public RawString()
            {
            }
    
            public byte[] ToByteArray()
            {
                if (_array == null)
                    return Encoding.UTF8.GetBytes(_val);
                else
                    return _array;
            }
    
    
            public override string ToString()
            {
                if (_array == null)
                    return _val;
                else
                {
                    return Convert.ToBase64String(_array);
                }
            }
    
        }
    }
    Helper class to get file contents into an attachment
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml;
    using System.Xml.Schema;
    using System.IO;
    using Microsoft.XLANGs.BaseTypes;
    using Microsoft.Samples.BizTalk.XlangCustomFormatters;
    
    
    namespace GClasses
    {
        public class GCargoBTUtils
        {
            /// <summary>
            /// Read file contents into RawString
            /// </summary>
            /// <param name="fileName"></param>
            /// <returns>RawString with byte array or error code</returns>
            public static RawString FileContents(string fileName)
            {
                RawString rs = new RawString("File not loaded (exists?)");
                if ( File.Exists(fileName) )
                {
    
                    using(var fle = File.Open(fileName, FileMode.Open))
                    using(var br = new BinaryReader(fle) )
                    {
                        if (fle.Length < 1000000)
                            rs = new RawString(br.ReadBytes((int)fle.Length));
                        else
                            rs = new RawString(string.Format("Error, file " + fileName + " is to large:{0} bytes", fle.Length));
                    }
                }
                return rs;
            }
        }
    }
    
    Orchestration
    Set DeliveryNotification=Transmitted on CSV send port

    Multipart Message


    "MessageAsignment" expression content
    filePath = @"c:\temp\messages\csv\" + uqName + ".csv"; //global variable
    msgEnvelope.Body = new Microsoft.Samples.BizTalk.XlangCustomFormatters.RawString(filePath);
    msgEnvelope.Attachment= GClasses.GCargoBTUtils.FileContents(filePath);
    msgEnvelope(SMTP.From) = "info@elinkx.cz";
    msgEnvelope(SMTP.Subject) = "BT Payment";
    msgEnvelope(SMTP.EmailBodyText) = "Payments";
    msgEnvelope(SMTP.SMTPHost) = "localhost";
    msgEnvelope.Attachment(Microsoft.XLANGs.BaseTypes.ContentType) = "text/plain";
    msgEnvelope(SMTP.MessagePartsAttachments) = 1;
    msgEnvelope.Attachment(MIME.FileName) = uqName + ".csv";

    SMTPDynPort(Microsoft.XLANGs.BaseTypes.Address) = PaymentMessage.ADRESS;
    SMTPDynPort(Microsoft.XLANGs.BaseTypes.TransportType) = "SMTP"; 

    Cheers and thanks for your assistance...



    Ondřej Spilka

    • Marked as answer by Ondřej Spilka Friday, February 24, 2012 10:34 AM
    Friday, February 24, 2012 10:33 AM
  • Hi Ondřej,

    Thanks for sharing that. Sorry I could not help you out directly.

    Cheers,

    Steef-Jan Wiggers

    MVP & MCTS BizTalk Server 2010

    http://soa-thoughts.blogspot.com/ | @SteefJan


    BizTalk

    Friday, February 24, 2012 6:54 PM
    Moderator