如何在附件中发送html?

Posted

技术标签:

【中文标题】如何在附件中发送html?【英文标题】:How to send html in attachment? 【发布时间】:2011-11-05 22:40:43 【问题描述】:

我需要通过电子邮件发送一些 html 文本。但我不需要在电子邮件正文中而是在附件中这样做。我用这段代码 sn-p 形成一个附件:

public MailMessage GetMailMessage(string @from)

  var m = new MailMessage(new MailAddress(@from), new MailAddress(_to)) Subject = _subj;
  var attach = new Attachment(new MemoryStream(
       Encoding.UTF8.GetBytes(_htmlAttach)), _subj + ".html", MediaTypeNames.Text.Html);
  attach.ContentDisposition.Inline = false;
  attach.ContentType.Name = _subj + ".html";
  m.Attachments.Add(attach);
  return m;

但是当我将这样的电子邮件发送到我的 gmail 邮箱时,我会收到一条纯文本消息,其中包含类似这样的文本:

\ =?utf-8?B?dDlDd0lOQy8wTFhSZ05DNDBMN1F0Q0F4Pz0NCiA9P3V0Zi04P0I/TXpv?=\ \ =?utf-
8?B?ME5pQXlPUzR3T0M0eU1ERXhJQzBnTVRRNk1qQWdNamt1TURndU1qQXhN?=\ \ =?utf-8?B?UzVvZEcxcz89?=" 
Content-Transfer-Encoding: base64 Content-Disposition: attachment 
PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMDEvL0VO 
IiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQvc3RyaWN0LmR0ZCI+DQo8aHRt 
bCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgeG1sOmxhbmc9 ImVuIj4NCjxoZWFkPg0KI

在附件中发送 html 文件的正确方法是什么?


UPD:这是原始邮件消息部分:

MIME-Version: 1.0
From: <xxx@xxx.xx>
To: xxx@gmail.com
Date: Mon, 29 Aug 2011 03:29:05 -0700 (PDT)
Subject: xxx
Content-Type: multipart/mixed; boundary=--boundary_0_c99e5172-1766-4cfe-a6e0-7f6b0fa11061
----boundary_0_c99e5172-1766-4cfe-a6e0-7f6b0fa11061
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: quoted-printable


----boundary_0_c99e5172-1766-4cfe-a6e0-7f6b0fa11061
Content-Type: text/html;
name="=?utf-8?B?PT91dGYtOD9CPzBLUFFzdEMxMExUUXZ0QzgwTHZRdGRDOTBMalF0U0RR?=\
\

 =?utf-8?B?dDlDd0lOQy8wTFhSZ05DNDBMN1F0Q0F4Pz0NCiA9P3V0Zi04P0I/TXpv?=\
\

 =?utf-8?B?ME5pQXlPUzR3T0M0eU1ERXhJQzBnTVRRNk1qQWdNamt1TURndU1qQXhN?=\
\
 =?utf-8?B?UzVvZEcxcz89?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment

然后是base64文本:

PCFET0NUWVBFIGh0bWwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMDEvL0VO
IiAiaHR0cDovL3d3dy53My5vcmcvVFIvaHRtbDQvc3RyaWN0LmR0ZCI+DQo8aHRt
bCB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbCIgeG1sOmxhbmc9
ImVuIj4NCjxoZWFkPg0KICAgIDxtZXRhIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hh

最后:

----boundary_0_c99e5172-1766-4cfe-a6e0-7f6b0fa11061--

【问题讨论】:

文件名看起来不对。 “Content-Type: text/html;”之后真的有换行符吗?还有样本中的反斜杠,它们是字面的吗?他们不应该在那里。反斜杠后的换行符也是如此。最后,文件名看起来像是经过了多次 RFC2047 编码;第一个短语解码为以 =?utf-8?B?... 开头的内容 这是解码文件名:=?utf-8?B?0KPQstC10LTQvtC80LvQtdC90LjQtSDQt9CwINC/0LXRgNC40L7QtCAx?= =?utf-8?B?Mzo0NiAyOS4wOC4yMDExIC0gMTQ6MjAgMjkuMDguMjAxMS5odG1s?=(原文如此!)解码反过来产生Уведомление за период 13:46 29.08.2011 - 14:20 29.08.2011.html。你至少应该去掉双重编码。 【参考方案1】:

看起来您在生成的部分之间缺少换行符。因此,您需要输入"To: " + newMailAddress(to) + "\n" 等内容。您还需要构建容器MIME 结构。如果您没有任何实际消息,只需将 HTML 作为单个正文部分发送,而不是作为“附件”发送。像这样的

From: me <self@example.net>
To: you <guy@example.com>
Subject: here
MIME-Version: 1.0
Content-type: text/html; name="=?utf-8?q?really_bewildering?=
  =?utf-8?q?_long_name.html?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="=?utf-8?q?really_bewildering?=
  =?utf-8?q?_long_name.html?="

PCFET0NUWVBFIGh0bWwgUFVCTElDICItL ...

您粘贴的示例消息,将正文包裹在单部分多部分/相关结构中,完全等效。

我相信 Content-Disposition 中的 filename= 部分是放置文件名的正确位置,但为了与非常旧的客户端向后兼容,最好将其放在两个位置。

注意包装长标题行的正确方法:换行之前不应有反斜杠;而是用至少一个空格字符缩进后续行。标题中不应有空行(空行是将标题与正文分开;因此错误标题中的第一个空行是将其余标题推入正文)。

base64 编码无处不在是怎么回事?除非您的文档包含大量 8 位内容,否则如果您改用quoted-printable,它可能更小且更易于调试。您会注意到我将文件名更改为quoted-printable 只是为了更易于阅读;你也可以对实际附件的内容做同样的事情。

更新:在示例消息下方添加了 Content-Disposition 和文件名以及 cmets。

重点:直接的问题是您在 MIME 标头中的多行文件名换行不正确。

【讨论】:

查看原始电子邮件,有换行符。我需要在附件中发送一个 html,因为它可能非常大。 添加更多的 MIME 结构会使消息更大,而不是更小。您在问题中粘贴的内容显然缺少标题和换行符;也许您需要使用\r\n 而不仅仅是\n(SMTP 需要 DOS 样式的行尾,但许多 MTA 将接受平台原生行尾约定的输入)。 实际上文件名应该按照RFC5987 正确编码,但这是切线的,所以我没有更新答案。另请参阅***.com/a/6745788/874188【参考方案2】:

与其将字节放入内存流,不如将文本放入?

我认为您可以使用 new Attachment() 的另一个重载并以另一种方式指定内容。

如果您已经将文件存储在某处,则可以附加该文件,或者您可以使用 StreamReader / TextReader 组合来确保将文本数据而不是二进制数据推送到附件内容中。

【讨论】:

我正在使用流,因为没有其他方法可以动态创建附件的内容。 new Attachment() 的其他重载可以从文件中获取内容,而不是从字符串中获取。【参考方案3】:

附件使用SevenBit(最多1000个字符!)或QuotedPrintable作为TransferEncoding

【讨论】:

刚试过。我的电子邮件仍然没有附件,看起来像这样:\ =?utf- 8?B?dDlDd0lOQy8wTFhSZ05DNDBMN1F0Q0F4Pz0NCiA9P3 V0Zi04P0I/T0Rv?=\ \ =?utf-8?B?eU9DQXlOUzR3T0M0eU 1ERXhJQzBnTVRnNk1qZ2dNekF1TURndU1qQXhN?=\ \ =?utf- 8?B?UzVvZEcxcz89?=" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment =0D=0A=0D=0A=0D=0A =0D=0A= =0D=0A =0D=0A = =0D=0A=0D=0A =0D=0A =0D=0A =0D=0A =0D=0A = =0D=0A = =0D=0A【参考方案4】:

您的附件类型很时髦。对于只想发送 UTF8(标准文本)的人来说,必须指定附件内容类型。这需要一个 Stream 它,而不是传递一个字符串。

带有 html 文本列表的示例

System.Net.Mime.ContentType ct 
            = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Html);

HtmlAttachments.Select( str => new Attachment(str.ToStream(), ct))
               .ToList()
               .ForEach( html => mailMessage.Attachments.Add(html));

... Usual loading of to/from etc 

client.Send(mailMessage);

为了完整起见,这里是ToStream extensions:

public static Stream ToStream( this string value ) => ToStream(value, Encoding.UTF8);

public static Stream ToStream( this string value, Encoding encoding )
                        => new MemoryStream(encoding.GetBytes(value ?? string.Empty));

【讨论】:

以上是关于如何在附件中发送html?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ASP.NET 中使用具有 HTML 正文 + 附件的 GMAIL API 发送电子邮件

[单选题]如何将一个数组作为附件发送,并要能在接收后重新组合?

如何使用exchangelib在python中将熊猫数据框作为电子邮件附件发送

如何使用 JavaMail 发送带有附件的 html 电子邮件

高手请帮忙:如何使用nmsmtp控件发送带附件的HTML格式信件

发送带有附件的 HTML 电子邮件