Как правильно установить имя вложения в Outlook

Я создаю электронное письмо с вложением MIME из порта отправки SMTP BizTalk 2016. Однако я думаю, что любые знания, которые кто-либо может поделиться с любого другого языка о странностях Outlook и MIME, могут помочь мне решить проблему ниже.

в Outlook вложение отображается как тело.txt, но когда я нажимаю "сохранить файл", он показывает имя, которое я использовал при его создании (и это то, что пользователь хочет видеть).

то, что я имею в виду, - это левая сторона, где она говорит "тело.txt " над 5k и справа от значка вложения на снимке экрана ниже:

enter image description here

в компоненте конвейера BizTalk C# это вложение было установлено со следующим кодом, где мы задаем свойства контекста в сообщении BizTalk. Я также попытался установить ContentHeader и ContentID.

strFilename = "MyFileName_693.txt";  // Just for example. 
pInMsg.BodyPart.PartProperties.Write(
              "FileName",
              "http://schemas.microsoft.com/BizTalk/2003/mime-properties",
               strFilename);

когда я отправил электронное письмо в Gmail, вложение было показано с собственным именем. Так что мой вопрос особенный. чтобы он появился с нужным именем в Outlook (2016).

1 ответов


до сих пор у меня это работает с оркестровкой с динамическим портом отправки. Это все еще немного работы, но она выполняет работу с компонентом запаса. Следующее описание основано на наличии SMTP-адаптера, включенного в BizTalk 2013R2.

Примечание: несмотря на то, что мое решение работает, это похоже на обходной путь и то, что мне не нужно делать, если адаптер был немного умнее об этом.

прежде всего, давайте посмотрим пример фрагмент электронной почты, который вызывает проблемы в некоторых клиентах:

------=_NextPart_000_0001_01D4502F.8A6A1500
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="utf-8"

See attached email.
------=_NextPart_000_0001_01D4502F.8A6A1500
Content-Type: application/pdf; name="CDM_Order - Copy.pdf"
Content-Disposition: attachment; filename="CDM_Order - Copy.pdf"
Content-Description: body
Content-Transfer-Encoding: base64

JVBERi0xLjQKJeLjz9MNCjUgMCBvYmoKPDwvRFsgMyAwIFIvWFlaIG51bGwgODQxLjg4OTc3IG51
bGwgXQo+PgplbmRvYmoKOCAwIG9iago8PC9EWyAzIDAgUi9YWVogbnVsbCAyOTAuMjM2NTcgbnVs
bCBdCj4+ (etc etc base64 your file)...

уведомления Content-Description: body часть. Вот почему некоторые клиенты читают body.xml или в моем случае body.pdf, хотя часть расположения выглядит великолепно:Content-Disposition: attachment; filename="CDM_Order - Copy.pdf".

жесткий параметр MIME.FileName не просто будет работать, хотя он установит Content-Disposition в конце концов, он никогда не обновит Content-Description. Это потому, что либо на статическом порту отправки вы установили Attach only body part или вы указали соответствующее числовое значение 1 на динамическом порту отправки.

тем не менее, он будет работать с Attach all parts или 2 значение типа MessagePartsAttachments. Это включает в себя создание многосоставного сообщения в вашей оркестровке. Это будет иметь две части;

  • первое-это BodyPart, теперь это будет включать текст Вашего сообщения, а не ваше вложение. Убедитесь, что вы указали это как Message Body Part на Message Type.
  • вторая часть будет ваш реальный вложения, указать этот тип в соответствии с типом крепления. Я назвал это Attachment в этом примере.

теперь вы можете подумать, что он отправит BodyPart как привязанность, так как я сказал, что нам нужно Attach all parts. Это правда, поэтому, чтобы исправить это, ваш BodyPart должно быть определено как RawString, это превращает строку в обычный текст в части сообщения BizTalk. Для полноты я поставлю класс C# внизу Для справки.

теперь, когда он определен как RawString, адаптер SMTP поместит это как тело, а не как вложение. В качестве побочного эффекта адаптер SMTP больше не будет помещать Content-Description: body часть в части крепления, но в фактической части тела вместо этого. Выглядит это так:

------=_NextPart_000_0001_01D450E4.A7E9A5E0
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset="utf-8"
Content-Description: body

See attached email.
------=_NextPart_000_0001_01D450E4.A7E9A5E0
Content-Type: application/pdf; name="ID_0_Nummer_0.pdf"
Content-Disposition: attachment; filename="ID_0_Nummer_0.pdf"
Content-Transfer-Encoding: base64

JVBERi0xLjQKJeLjz9MNCjUgMCBvYmoKPDwvRFsgMyAwIFIvWFlaIG51bGwgODQxLjg4OTc3IG51
bGwgXQo+PgplbmRvYmoKOCAwIG9iago8PC9EWyAzIDAgUi9YWVogbnVsbCAyOTAuMjM2NTcgbnVs
bCBdCj4+ (etc etc base64 your file)...

на самом деле ничто другое не отличается, кроме размещения Content-Description: body часть, именно то, что мы хотим. Теперь электронная почта выглядит отлично для каждого клиента.

самые важные свойства, кроме тех, которые я уже упоминал, необходимо также установить, чтобы он вел себя правильно:

тип содержимого вашего тела:

MsgPdfOrder.BodyPart(Microsoft.XLANGs.BaseTypes.ContentType) = "text/plain";

тип содержимого вашего вложения:

MsgPdfOrder.Attachment(Microsoft.XLANGs.BaseTypes.ContentType) = "application/pdf";

имя файла вложения:

MsgPdfOrder.Attachment(MIME.FileName) =  "CDM_Order - Copy.pdf"

набор символов тела (в результате Unknown Error Description если не установлен):

MsgPdfOrder(SMTP.EmailBodyTextCharset) = "UTF-8";

убедитесь, что вы не Выберите SMTP.EmailBodyText потому что у нас уже есть BodyPart для этого.

класс RawString, используйте его так в оркестровке MsgPdfOrder.BodyPart = new Yournamespace.Components.RawString("See attached email."); :

using System.Runtime.Serialization;
using System;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using Microsoft.XLANGs.BaseTypes;

namespace Yournamespace.Components
{
    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;

        public RawString(string s)
        {
            if (null == s)
                throw new ArgumentNullException();
            _val = s;
        }

        public RawString()
        {
        }

        public byte[] ToByteArray()
        {
            return Encoding.UTF8.GetBytes(_val);
        }

        public override string ToString()
        {
            return _val;
        }
    }
}