多部分/混合消息中的边界字符串不正确

2024-01-12

我正在使用 Delphi 2006 在仅供个人使用的应用程序中创建并发送带有附件的电子邮件。我使用 TIdSMTP 实例发送邮件,然后将副本放入包含 TIdIMAP4 实例的特定 IMAP 文件夹中。这一切都与 BDS2006 一起分发的 Indy 10 版本配合得很好,但有一个例外:电子邮件标头中的时间总是不正确。

我决定尽可能修复这个问题,在寻找解决方案后,获取最新的 Indy 10 快照并使用它似乎是最合理的。

这会将正确的时间放入电子邮件标题中,但出现了一个新问题。现在,添加到 IMAP 文件夹的邮件标头中的边界字符串与电子邮件正文中的边界字符串不同! (请注意,通过 SMTP 发送的消息是正确的。)

这是旧版本 Indy 10 的相关头信息:

Content-Type: multipart/mixed; boundary="XNlC6OyS4QSiHY2U=_jsXyps6TR34pFNsh"
MIME-Version: 1.0
Date: Tue, 22 Nov 2011 09:11:58 +0000

A test of the BDS2006-bundled version of Indy

--XNlC6OyS4QSiHY2U=_jsXyps6TR34pFNsh
Content-Type: application/octet-stream;
        name="20111122.xls"

这是来自 Indy 10.5.8 的相同标头信息(我昨天安装的快照 10_4702):

Content-Type: multipart/mixed; boundary="CDbEncbFvL7RZdOJ3DOIRoRBs=_nBsbZms"
MIME-Version: 1.0
Date: Tue, 22 Nov 2011 07:33:46 -0600

investigating more deeply, why does the boundary indicator change?

--h=_WzGWJei29fng7SqdPpDh1nkJxJZhiGc
Content-Type: application/octet-stream;
    name="20111122.xls"

时间戳是固定的,但现在边界字符串不正确。结果是,添加到我的 IMAP 文件夹中的邮件中似乎没有任何内容。

以下是创建电子邮件和附件、发送并将副本放入 IMAP 文件夹的相关代码:

  FTheMsg.Date := Now;  // FTheMsg is a component dropped onto the form
  FTheMsg.Recipients.EMailAddresses := edMailTo.Text;
  FTheMsg.ClearBody;
  FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' +
              FormatDateTime('mm/dd/yy', FEndDate);
  FTheMsg.Body.Assign(FMemo.Lines);

  // create the attachment
  TIdAttachmentFile.Create(FTheMsg.MessageParts, fileName);

  // send the mail!
  FSmtp.Host := FSMTPHost;  // values set up elsewhere, FSmtp is a component on the form
  FImap.Host := FIMAPHost;  // FImap is also a component on the form

  FSmtp.Connect;
  try
    FSmtp.Send(FTheMsg);
    FImap.Connect;
    try
      if (not FImap.AppendMsg('Sent Items', FTheMsg, FTheMsg.LastGeneratedHeaders, [mfSeen]))     then
        StatusBar1.Panels[4].Text := 'Failed append msg';
    finally
      FImap.Disconnect;
    end;
  finally
    FSmtp.Disconnect;
  end;

正如我所说,发送的电子邮件很好并且显示正常。但添加到我的 IMAP 文件夹(在上面的 FImap.AppendMsg() 中)的文件夹不正确。我试图追踪代码,看看哪里可能出了问题,但坦率地说,我对 Indy 和各种电子邮件协议/RFC 不够熟悉,无法确定出了什么问题。我所能告诉的是,旧版本在将消息附加到文件夹之前将其保存到临时文件中,而新版本则将其保存到内存流中。显然,有些东西是不同的,但我目前太无知,无法确定是什么。

有没有简单的方法来纠正旧版本中的时间戳问题?如果是这样,那对我来说就很好了,因为其他一切似乎都是正确的。如果不是,我还需要做什么来解决此处显示的边界字符串不正确的问题?

(由于这是一个严格供我自己使用的应用程序,因此如果有必要的话,我可以接受错误的日期,但不能接受“已发送邮件”文件夹中的“空出现”副本。)

如果需要更多信息,我很乐意提供一切我能提供的信息。

[编辑:我确实使用旧版本的 Indy 在我的代码中加入了一些拼凑的东西。我只是在发送消息之前将消息的日期/时间设置为 UTC/GMT 时间,这样至少允许消息在接收方端包含正确的时间。我并不特别关心这个修复,但它确实有效。]


不要使用TIdMessage.Body当存在附件时保存文本的属性。将文本放入TIdText对象代替。更好的是,使用TIdMessageBuilder...类,例如TIdMessageBuilderPlain,准备TIdMessage身体给你。

尝试这个:

FTheMsg.Clear; 
FTheMsg.Date := Now;  // FTheMsg is a component dropped onto the form 
FTheMsg.Recipients.EMailAddresses := edMailTo.Text; 
FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' + FormatDateTime('mm/dd/yy', FEndDate); 
FTheMsg.ContentType := 'multipart/mixed'; 

TIdText.Create(FTheMsg.MessageParts, FMemo.Lines).ContentType := 'text/plain';
TIdAttachmentFile.Create(FTheMsg.MessageParts, fileName); 

FSmtp.Connect; 
try 
  FSmtp.Send(FTheMsg); 
  FImap.Connect; 
  try 
    if (not FImap.AppendMsg('Sent Items', FTheMsg, nil, [mfSeen])) then 
      StatusBar1.Panels[4].Text := 'Failed append msg'; 
  finally 
    FImap.Disconnect; 
  end; 
finally 
  FSmtp.Disconnect; 
end; 

Or:

FTheMsg.Clear; 
FTheMsg.Date := Now;  // FTheMsg is a component dropped onto the form 
FTheMsg.Recipients.EMailAddresses := edMailTo.Text; 
FTheMsg.Subject := 'Glucose Readings ' + FormatDateTime('mm/dd/yy', FStartDate) + ' - ' + FormatDateTime('mm/dd/yy', FEndDate); 

with TIdMessageBuilderPlain.Create do
try
  PlainText.Assign(FMemo.Lines);
  Attachments.Add(fileName); 
  FillMessage(FTheMsg);
finally
  Free;
end;

FSmtp.Connect; 
try 
  FSmtp.Send(FTheMsg); 
  FImap.Connect; 
  try 
    if (not FImap.AppendMsg('Sent Items', FTheMsg, nil, [mfSeen])) then 
      StatusBar1.Panels[4].Text := 'Failed append msg'; 
  finally 
    FImap.Disconnect; 
  end; 
finally 
  FSmtp.Disconnect; 
end; 

话虽如此,但无论哪种方式它都可能仍然无法正常工作。TIdIMAP4.AppendMsg() calls TIdMessage.SaveToStream()在内部,这会重新生成新鲜的电子邮件内容(从而改变正文中使用的边界)。是否传入已有的TIdMessage.LastGeneratedHeaders or let TIdIMAP4.AppendMsg()抓住电流TIdMessage.Headers,它们将与新边界不同步TIdMessage.SaveToStream()生成。

为了确保 SMTP 和 IMAP4 同步,它们需要接收相同的数据。尝试打电话TIdMessage.SaveToStream()首先手动使用TIdMessage.NoEncode属性设置为 False,然后设置TIdMessage.NoDecode属性为 True 并调用TIdMessage.LoadFromStream()将保存的数据按原样重新加载到TIdMessage.Headers and TIdMessage.Body属性,然后调用TIdSMTP.Send() and TIdIMAP4.AppendMsg()TIdMessage.NoEncode属性设置为 True 所以TIdMessage.Headers and TIdMessage.Body按原样发送。

我知道,这违背了TIdIMAP4.AppendMsg()评论/文档说要做。AppendMsg()目前根本不考虑 MIME,因此它不能确保标头和正文中的 MIME 边界相互匹配。我将尝试检查该问题的修复。对于 Indy 11,Indy 的整个 MIME 处理系统将重新设计,因此我将确保可以保留边界和/或指定自定义边界,因此AppendMsg()可以更好地将正文边界与标题边界匹配。

一般来说,IMAP4 是一个非常棘手的协议。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

多部分/混合消息中的边界字符串不正确 的相关文章

随机推荐

  • SWT 日期时间格式更改

    我正在使用 DateTime SWT 组件 它在显示时具有美国格式 mm dd yyyy 有什么方法可以将格式更改为 dd mm yyyy 吗 DateTime uses http dev eclipse org mhonarc lists
  • 使用 XPath 选择命名空间中的元素

    我想选择具有给定命名空间 前缀 的文档中最顶层的元素 更具体地说 我的 XML 文档要么以 html body 在 XHTML 命名空间中 开头 要么以特定命名空间中的多个元素之一开头 我实际上想删除 html body 并只返回正文内容或
  • jQuery 自动完成,将成功数据传递给 select 方法

    我有 json 响应 它有一些属性 我已经为列表创建了一个数组 当我单击列表项时 一些输入将由项目 ID 填充 为此 我正在考虑将完整的数据对象传递给 select 方法 然后如果单击列表中的某个项目 我将在数据对象中搜索 id 如果找到
  • beans 和 Jackson 库的问题

    HI 我正在使用 json 文件 如下所示 SourceFile videos KobeAlleyOop flv ExifTool ExifToolVersion 8 22 Warning Truncated mdat data Syste
  • 星号 (*) 在 VSCodestasks.json 中不起作用

    当我尝试运行具有多个模块的 C 项目时 它默认只编译选定的模块 我尝试编辑tasks json来编译文件夹中的每个C和头文件 但它只是将星号作为星号传递到我的命令行 我编辑了tasks json并尝试使用以下输出构建项目 Starting
  • Kotlin 的具体化类型对于 JVM 上的原语是否不正确?

    如果 Kotlin 函数调用具体化了一个原语 比如说Int 通过 类是装箱原语的类 而不是未装箱版本的类 inline fun
  • 使用 GCC 语句表达式的匿名函数

    这个问题并不是很具体 这确实是为了丰富我自己的 C 语言 我希望其他人也能发现它很有用 免责声明 我知道很多人都会有这样的冲动 如果你想尝试函数式编程 那么就使用函数式语言 我在需要链接到许多其他 C 库的嵌入式环境中工作 并且没有太多空间
  • 如何在不打补丁的情况下本地化Python的argparse模块?

    当消息的某些部分是用户语言而其他部分是英语时 本地化的命令行应用程序看起来很奇怪 我不知道当我从源代码安装 Python 3 时是否搞砸了任何东西 似乎没有 mo文件 所以argparse 总体而言 没有本地化意识 API 似乎也没有提供本
  • 如何在 Android 的 SD 卡中设置代理自动配置 (PAC) 文件

    打扰一下 我使用以下命令将文件 proxy pac 推送到 SD 卡 adb push C Users zuokang li Documents proxy pac sdcard 我尝试在 android 中设置代理自动配置 所以我设置了
  • 在 Python 中循环 Protocol Buffers 属性

    我想要帮助递归地循环协议缓冲区消息中包含的所有属性 子对象 假设我们不知道它们的名称 或者有多少个 作为示例 请从 google 网站上的教程中获取以下 proto 文件 message Person required string nam
  • Matplotlib Xticks 条形图中的值

    我有这段代码 我正在尝试制作一个图表 列表中的所有值都是正确的 但是 我在 x 轴上遇到问题 首先 前两个价格变动之间存在差距 我阅读了他们网站上的所有 matplotlib 但找不到任何对这个问题有用的东西 我对 xticks 函数很困惑
  • Powershell 3.0:“获取音量”的替代方案

    我正在尝试获取计算机上每个硬盘卷的各种属性 我正在使用 cmdletget volume然后通过它走过foreach 但 Windows Server 2008 中不存在该 cmdlet 有人知道替代方案吗 我只需要驱动器号 objectI
  • WPF 调度程序、后台工作人员和很多痛苦

    好吧 这可能真的很简单 但我尝试的一切似乎都碰壁了 我有一个具有两个属性的视图模型 它们绑定到我的 WPF 表单 bool IsWorking get set ObservableCollection
  • 从tasklet存储在JobExecutionContext中并在另一个tasklet中访问

    我有一个要求 其中一个微线程将目录中的所有文件存储在数组列表中 列表的大小存储在作业执行上下文中 稍后 在另一个步骤中从另一个微线程访问此计数 这是怎么做到的 我尝试存储在作业执行上下文中 在运行时抛出不可修改的集合异常 public Re
  • 为什么评估布尔表达式的普通法则不适合 LINQ?

    在这样的代码中 if insuranceNumberSearch null true ei InsuranceNumber Contains insuranceNumberSearch Trim doSomething where insu
  • Fluent NHibernate 中的 schemaExport 是什么?

    我很想知道更多关于此代码的方式以及执行时的预期结果
  • 如何使用 RxJava 将双精度值的嵌套列表转换为 Java 类?

    在我的 Android 客户端中 我从后端收到以下 JSON 数据 1427378400000 553 1427382000000 553 这是实际加载数据的例程 我在用接收Android https github com Reactive
  • 身份验证 - JavaScript - 注销问题

    我需要一些帮助来解决我的问题 firebase auth onAuthStateChanged user gt if user console log log in window location href event list html
  • Chrome 堆分析器中分离的 DOM 节点的颜色意味着什么?

    当使用 Chrome 开发工具分析堆快照时 我似乎无法弄清楚查看分离 DOM 树时颜色的含义 红色和黄色有什么区别 有一个很好的解释可以在这里找到 http addyosmani com blog taming the unicorn ea
  • 多部分/混合消息中的边界字符串不正确

    我正在使用 Delphi 2006 在仅供个人使用的应用程序中创建并发送带有附件的电子邮件 我使用 TIdSMTP 实例发送邮件 然后将副本放入包含 TIdIMAP4 实例的特定 IMAP 文件夹中 这一切都与 BDS2006 一起分发的