使用邮件存储提供程序发送邮件

适用于:Outlook 2013 | Outlook 2016

不需要消息存储提供程序来支持传出消息提交 (即客户端应用程序能够使用消息存储提供程序) 发送消息。 客户端应用程序在发送消息时需要使用消息存储,因为消息的数据必须存储在用户完成撰写该消息的时间和 MAPI 后台处理程序将消息提供给传输提供程序以提交到基础消息系统之间的某个时间之间。 如果消息存储提供程序不支持传出消息提交,则不能将其用作默认消息存储。

若要支持发送消息,消息存储提供程序必须执行以下操作:

SetLockState 方法对于 MAPI 后台处理程序和客户端之间的正确互操作非常重要。 当 MAPI 后台处理程序对传出消息调用 SetLockState 时,消息存储提供程序不得允许客户端打开该消息。 如果客户端尝试打开 MAPI 后台处理程序锁定的消息,消息存储提供程序应返回MAPI_E_NO_ACCESS。 当消息被 MAPI 后台处理程序锁定时,如果存储关闭,则消息的锁定状态不一定是永久性的。

无论 MAPI 后台处理程序是否锁定了传出消息,消息存储提供程序都不应允许打开传出消息队列中的消息进行写入。 如果客户端对具有 MAPI_MODIFY 标志的传出消息调用 IMSgStore::OpenEntry 方法,则调用应失败并返回MAPI_E_SUBMITTED。 如果客户端应用程序对具有 MAPI_BEST_ACCESS 标志的传出消息调用 OpenEntry ,则消息存储提供程序应允许对该消息进行只读访问。

当 MAPI 后台处理程序处理消息时,消息存储提供程序会将消息的 PR_SUBMIT_FLAGS (PidTagSubmitFlags) 属性设置为SUBMITFLAG_LOCKED。 SUBMITFLAG_LOCKED值指示 MAPI 后台处理程序已锁定消息以供其独占使用。 PR_SUBMIT_FLAGS的另一个值(SUBMITFLAG_PREPROCESS)是在消息需要由传输提供程序注册的一个或多个预处理器函数进行预处理时设置的。

以下过程介绍了消息存储、传输和 MAPI 后台处理程序如何交互以将消息从客户端发送到一个或多个收件人。

客户端应用程序调用 IMessage::SubmitMessage 方法。 在 SubmitMessage 中,消息存储提供程序执行以下操作:

  1. 调用 IMAPISupport::P repareSubmit。 如果 MAPI 返回错误,消息存储提供程序会将该错误返回给客户端。

  2. 设置消息的 PR_MESSAGE_FLAGS (PidTagMessageFlags) 属性中的MSGFLAG_SUBMIT位。

  3. 确保收件人表中的 PR_RESPONSIBILITY (PidTagResponsibility) 属性有一列,并将其设置为 FALSE,以指示尚未承担传输邮件的责任。

  4. PR_CLIENT_SUBMIT_TIME (PidTagClientSubmitTime) 属性中设置起源日期和时间。

  5. 调用 IMAPISupport::ExpandRecips 执行以下操作:

    1. 展开所有个人通讯组列表和自定义收件人,并将所有已更改的显示名称替换为其原始名称。

    2. 删除重复名称。

    3. 检查是否有任何必需的预处理,如果需要预处理,请设置NEEDS_PREPROCESSING标志和 PR_PREPROCESS (PidTagPreprocess) 属性,这是为 MAPI 保留的。

    4. 如果邮件存储与传输紧密耦合,并且无法处理所有收件人,请设置NEEDS_SPOOLER标志。

  6. 如果设置了NEEDS_PREPROCESSING消息标志,则执行以下任务:

    1. PR_SUBMIT_FLAGS 属性中 设置SUBMITFLAG_PREPROCESS位的情况下,将消息放入传出队列中。

    2. 通知 MAPI 后台处理程序队列已更改。

    3. 将控制权返回到客户端,消息流继续在 MAPI 后台处理程序中。 MAPI 后台处理程序执行以下任务:

      1. 通过调用 IMsgStore::SetLockState 来锁定消息。

      2. 通过按注册顺序调用所有预处理函数来执行所需的预处理。 传输提供程序调用 IMAPISupport::RegisterPreprocessor 来注册预处理函数。

      3. 对打开的消息调用 IMessage::SubmitMessage ,以向消息存储指示预处理已完成。

如果没有预处理,或者存在预处理和名为 SubmitMessage 的 MAPI 后台处理程序,则消息存储提供程序在客户端进程中执行以下操作:

  • 如果消息存储与传输紧密耦合,并且从 IMAPISupport::ExpandRecips 返回了NEEDS_SPOOLER标志,则执行以下任务:

    • 处理它可以处理的任何收件人。

    • 对于它处理的任何收件人 ,将 PR_RESPONSIBILITY 属性设置为 TRUE。

    • 如果所有收件人都知道此紧密耦合的存储和传输,则执行以下任务:

      • 如果消息已预处理或消息存储提供程序希望 MAPI 后台处理程序完成消息处理,则调用 IMAPISupport::CompleteMsg 。 使用 MAPI 后台处理程序继续消息流。

      • 如果未预处理消息或消息存储提供程序不希望 MAPI 后台处理程序完成消息处理,则执行以下任务:

        1. 将邮件复制到 PR_SENTMAIL_ENTRYID (PidTagSentMailEntryId) 属性中条目标识符标识的文件夹(如果已设置)。

        2. 如果 PR_DELETE_AFTER_SUBMIT (PidTagDeleteAfterSubmit) 属性已设置为 TRUE,则删除消息。

        3. 如果消息已锁定,则解除锁定。

        4. 返回到客户端。 消息流已完成。

    • 如果消息已预处理或提供程序希望 MAPI 后台处理程序完成消息处理,则执行以下任务:

      1. 调用 IMAPISupport::CompleteMsg

      2. 使用 MAPI 后台处理程序继续消息流。 有关详细信息,请参阅 发送消息:MAPI 后台处理程序任务

    • 如果未预处理消息或提供程序不希望后台处理程序完成消息处理,则执行以下任务:

      1. 将邮件复制到 由 PR_SENTMAIL_ENTRYID 属性中的条目标识符标识的文件夹(如果已设置)。

      2. 如果 PR_DELETE_AFTER_SUBMIT 属性已设置为 TRUE,则删除消息。

      3. 如果消息已锁定,则解除锁定。

      4. 返回到调用方。 消息流已完成。

  • 如果邮件存储未紧密耦合到传输,并非所有收件人都为邮件存储区所知,或者设置了NEEDS_SPOOLER标志,则执行以下任务:

    1. 将消息放入传出队列中,而不在 PR_SUBMIT_FLAGS 属性中设置 SUBMITFLAG_PREPROCESS 位。

    2. 通过生成表通知,通知 MAPI 后台处理程序传出队列已更改。

    3. 返回到客户端,消息流继续执行 MAPI 后台处理程序执行的一组任务。

另请参阅