<?xml version="1.0" encoding="UTF-8"?>
  <?xml-stylesheet type="text/xsl" href="rfc2629.xslt" ?>
  <!-- generated by https://github.com/cabo/kramdown-rfc version 1.7.29 (Ruby 2.6.10) -->


<!DOCTYPE rfc  [
  <!ENTITY nbsp    "&#160;">
  <!ENTITY zwsp   "&#8203;">
  <!ENTITY nbhy   "&#8209;">
  <!ENTITY wj     "&#8288;">

]>


<rfc ipr="trust200902" docName="draft-degennaro-mta-hooks-00" category="std" consensus="true" submissionType="IETF" tocInclude="true" sortRefs="true" symRefs="true">
  <front>
    <title abbrev="MTA Hooks">MTA Hooks: An HTTP-Based Mail Processing Protocol</title>

    <author initials="M." surname="De Gennaro" fullname="Mauro De Gennaro">
      <organization abbrev="Stalwart Labs">Stalwart Labs LLC</organization>
      <address>
        <postal>
          <street>1309 Coffeen Avenue, Suite 1200</street>
          <city>Sheridan</city>
          <region>WY</region>
          <code>82801</code>
          <country>USA</country>
        </postal>
        <email>mauro@stalw.art</email>
        <uri>https://stalw.art</uri>
      </address>
    </author>

    <date year="2025" month="December" day="23"/>

    
    
    <keyword>Internet-Draft</keyword>

    <abstract>


<?line 44?>

<t>This document specifies MTA Hooks, an HTTP-based protocol enabling Mail Transfer Agents (MTAs) to delegate message processing decisions to external services. MTA Hooks provides a modern alternative to legacy mail filtering protocols by leveraging ubiquitous HTTP infrastructure, supporting both JSON and CBOR serialization, and offering fine-grained capability negotiation. The protocol supports both inbound message reception and outbound message delivery scenarios, allowing external scanners to inspect messages, modify content, and influence routing decisions at various stages of mail processing.</t>



    </abstract>



  </front>

  <middle>


<?line 48?>

<section anchor="introduction"><name>Introduction</name>

<t>Mail Transfer Agents require extensible mechanisms to integrate with external services for spam filtering, virus scanning, policy enforcement, and compliance monitoring. While legacy protocols such as the Milter protocol have served this purpose, they present challenges in modern deployments including proprietary wire formats, limited tooling, and operational complexity.</t>

<t>MTA Hooks addresses these challenges by defining an HTTP-based protocol for mail processing delegation. The protocol leverages the widespread availability of HTTP client and server implementations, standard serialization formats, and established operational practices for HTTP services.</t>

<t>MTA Hooks achieves broad deployment compatibility by building upon standard HTTP semantics and methods, allowing implementers to leverage existing HTTP client and server libraries. The protocol supports both JSON and CBOR serialization to accommodate environments with different performance and parsing requirements. Capability negotiation during registration enables graceful feature discovery and forward compatibility as the protocol evolves. Mandatory transport encryption protects message content in transit, while the authentication mechanism remains pluggable to integrate with diverse deployment environments. The HTTP foundation ensures compatibility with existing operational infrastructure including load balancers, reverse proxies, and monitoring systems.</t>

<t>MTA Hooks supports two primary use cases: inbound processing during message reception from remote clients, and outbound processing during message delivery to remote servers. Both scenarios follow a consistent request-response pattern where the MTA invokes the registered hook endpoints at configured processing stages.</t>

<section anchor="notational-conventions"><name>Notational Conventions</name>

<t>The key words "<bcp14>MUST</bcp14>", "<bcp14>MUST NOT</bcp14>", "<bcp14>REQUIRED</bcp14>", "<bcp14>SHALL</bcp14>", "<bcp14>SHALL
NOT</bcp14>", "<bcp14>SHOULD</bcp14>", "<bcp14>SHOULD NOT</bcp14>", "<bcp14>RECOMMENDED</bcp14>", "<bcp14>NOT RECOMMENDED</bcp14>",
"<bcp14>MAY</bcp14>", and "<bcp14>OPTIONAL</bcp14>" in this document are to be interpreted as
described in BCP 14 <xref target="RFC2119"/> <xref target="RFC8174"/> when, and only when, they
appear in all capitals, as shown here.</t>

<?line -18?>

</section>
<section anchor="terminology"><name>Terminology</name>

<t>The following terms are used throughout this document:</t>

<t><list style="symbols">
  <t>MTA (Mail Transfer Agent): A software component responsible for transferring electronic mail messages between hosts, as described in <xref target="RFC5321"/>.</t>
  <t>Hook Endpoint: An HTTP server endpoint that receives hook invocations from an MTA and returns processing instructions.</t>
  <t>Scanner: A service that registers with an MTA to receive hook invocations. Scanners perform functions such as spam filtering, virus scanning, or policy enforcement. The terms "scanner" and "hook endpoint" are used interchangeably when referring to the service receiving hook requests.</t>
  <t>Registration: The process by which a scanner establishes a relationship with an MTA, including capability negotiation and callback URL configuration.</t>
  <t>Inbound Processing: Hook invocation during message reception, when the MTA accepts a message from a remote SMTP client.</t>
  <t>Outbound Processing: Hook invocation during message delivery, when the MTA transmits a message to a remote SMTP server.</t>
  <t>Stage: A specific point in mail processing at which the MTA invokes registered hooks. Different stages provide access to different message properties.</t>
  <t>Action: An instruction from a scanner indicating how the MTA should proceed with message processing.</t>
  <t>Modification: A change to message properties requested by a scanner, expressed as operations on the hook request object.</t>
</list></t>

</section>
<section anchor="data-types"><name>Data Types</name>

<t>This specification defines several object types used throughout the protocol. The following primitive types are used:</t>

<dl newline="true">
  <dt><strong>String</strong></dt>
  <dd>
    <t>A JSON string value.</t>
  </dd>
  <dt><strong>Int</strong></dt>
  <dd>
    <t>An integer in the range -2^53+1 &lt;= value &lt;= 2^53-1.</t>
  </dd>
  <dt><strong>UnsignedInt</strong></dt>
  <dd>
    <t>An integer in the range 0 &lt;= value &lt;= 2^53-1.</t>
  </dd>
  <dt><strong>Boolean</strong></dt>
  <dd>
    <t>A JSON boolean value (true or false).</t>
  </dd>
  <dt><strong>UTCDate</strong></dt>
  <dd>
    <t>A string in "date-time" format as defined in <xref target="RFC3339"/>, where the time-offset component <bcp14>MUST</bcp14> be "Z" (UTC time). For example, "2024-12-21T15:30:00Z".</t>
  </dd>
</dl>

</section>
</section>
<section anchor="protocol-overview"><name>Protocol Overview</name>

<t>MTA Hooks defines a request-response protocol where the MTA acts as an HTTP client and scanners act as HTTP servers. During mail processing, the MTA constructs a request containing message properties and context information, transmits it to registered scanner endpoints, and processes the response to determine subsequent actions.</t>

<section anchor="architecture"><name>Architecture</name>

<t>The protocol architecture consists of three primary components:</t>

<t><list style="numbers" type="1">
  <t>The MTA, which initiates HTTP requests to scanner endpoints at configured processing stages.</t>
  <t>Scanner services, which receive requests, perform analysis, and return responses containing actions and modifications.</t>
  <t>A registration mechanism through which scanners declare their capabilities and subscribe to specific processing stages.</t>
</list></t>

<figure title="MTA Hooks Protocol Flow" anchor="fig-architecture"><artwork><![CDATA[
+-------+                              +---------+
|       |  1. Discovery Request        |         |
|       |----------------------------->|         |
|       |  2. Discovery Response       |         |
|       |<-----------------------------|         |
|       |                              |         |
|       |  3. Registration Request     |         |
|  MTA  |----------------------------->| Scanner |
|       |  4. Registration Response    |         |
|       |<-----------------------------|         |
|       |                              |         |
|       |  5. Hook Request             |         |
|       |----------------------------->|         |
|       |  6. Hook Response            |         |
|       |<-----------------------------|         |
+-------+                              +---------+
]]></artwork></figure>

<t>The protocol flow proceeds as follows:</t>

<t><list style="numbers" type="1">
  <t>The MTA discovers scanner capabilities by requesting the well-known discovery endpoint.</t>
  <t>The scanner returns a discovery document describing supported stages, actions, and configuration options.</t>
  <t>The scanner submits a registration request specifying desired stages, properties, and callback configuration.</t>
  <t>The MTA validates the request, optionally verifies the callback endpoint, and returns registration confirmation.</t>
  <t>During mail processing, the MTA invokes the scanner's callback URL with message properties and context.</t>
  <t>The scanner returns a response containing an action and optional modifications.</t>
</list></t>

</section>
<section anchor="serialization"><name>Serialization</name>

<t>Requests and responses are serialized using either JSON <xref target="RFC8259"/> or CBOR <xref target="RFC8949"/>. The serialization format is negotiated during registration and indicated via HTTP <spanx style="verb">Content-Type</spanx> headers.</t>

<t>For JSON serialization, the <spanx style="verb">Content-Type</spanx> header <bcp14>MUST</bcp14> be "application/json". For CBOR serialization, the <spanx style="verb">Content-Type</spanx> header <bcp14>MUST</bcp14> be "application/cbor".</t>

<t>Binary data handling differs between formats. In JSON serialization, binary content such as message body parts <bcp14>MUST</bcp14> be encoded using Base64. In CBOR serialization, binary content <bcp14>SHOULD</bcp14> be transmitted as raw byte strings.</t>

</section>
<section anchor="processing-stages"><name>Processing Stages</name>

<t>MTA Hooks defines processing stages for both inbound and outbound message handling. Scanners subscribe to specific stages during registration and receive invocations only for subscribed stages.</t>

<section anchor="inbound-stages"><name>Inbound Stages</name>

<t>Inbound stages correspond to SMTP protocol events during message reception:</t>

<t><list style="symbols">
  <t>connect: Invoked when a remote client establishes a connection, before any SMTP commands are exchanged.</t>
  <t>ehlo: Invoked after the client sends EHLO or HELO command.</t>
  <t>mail: Invoked after each MAIL FROM command.</t>
  <t>rcpt: Invoked after each RCPT TO command. This stage may be invoked multiple times per transaction.</t>
  <t>data: Invoked after the complete message has been received, following the DATA command and message content.</t>
</list></t>

</section>
<section anchor="outbound-stages"><name>Outbound Stages</name>

<t>Outbound stages correspond to delivery events during message transmission:</t>

<t><list style="symbols">
  <t>delivery: Invoked after a delivery attempt completes for all recipients, regardless of success or failure.</t>
  <t>defer: Invoked only when at least one recipient delivery cannot be completed and requires retry.</t>
  <t>dsn: Invoked when the MTA generates a Delivery Status Notification of any type.</t>
</list></t>

<t>For outbound stages, the hook is invoked once after delivery attempts for all recipients in a given delivery batch have completed. The scanner receives the delivery status for each recipient and may modify per-recipient handling.</t>

</section>
</section>
<section anchor="inbound-message-processing"><name>Inbound Message Processing</name>

<t>During inbound processing, the MTA invokes registered hooks as it receives messages from remote SMTP clients. This corresponds to traditional mail filtering scenarios where external services inspect incoming mail for spam, viruses, or policy violations.</t>

<t>The inbound flow proceeds through SMTP protocol stages:</t>

<t><list style="numbers" type="1">
  <t>A remote client connects to the MTA.</t>
  <t>The MTA invokes hooks registered for the "connect" stage.</t>
  <t>The client sends EHLO/HELO; the MTA invokes "ehlo" stage hooks.</t>
  <t>The client sends MAIL FROM; the MTA invokes "mail" stage hooks.</t>
  <t>The client sends one or more RCPT TO commands; the MTA invokes "rcpt" stage hooks for each.</t>
  <t>The client sends DATA and message content; the MTA invokes "data" stage hooks.</t>
</list></t>

<t>At each stage, scanners may instruct the MTA to accept, reject, or modify the transaction.</t>

<section anchor="multiple-scanner-handling"><name>Multiple Scanner Handling</name>

<t>When multiple scanners are registered for the same stage, the MTA invokes them sequentially in an implementation-defined order. Each scanner's response affects the request seen by subsequent scanners.</t>

<t>The scanner chain terminates early when a scanner returns a terminal action:</t>

<t><list style="symbols">
  <t>Inbound terminal actions: "reject", "discard", "disconnect"</t>
  <t>Outbound terminal actions: "cancel"</t>
</list></t>

<t>Non-terminal actions ("accept", "quarantine" for inbound; "continue" for outbound) allow the chain to proceed, and subsequent scanners may override these actions.</t>

<t>Implementations <bcp14>SHOULD</bcp14> provide configuration options for:</t>

<t><list style="symbols">
  <t>Scanner invocation order (priority-based or explicit ordering)</t>
  <t>Whether to allow subsequent scanners to override "quarantine" decisions</t>
  <t>Logging of chain termination events for operational visibility</t>
</list></t>

<t>Example chain behavior:</t>

<t><list style="numbers" type="1">
  <t>Scanner A (spam filter) sets action to "accept" and adds X-Spam-Score header</t>
  <t>Scanner B (virus scanner) receives modified request, detects malware, sets action to "reject"</t>
  <t>Chain terminates; Scanner C is not invoked</t>
  <t>MTA rejects the message</t>
</list></t>

</section>
</section>
<section anchor="outbound-message-processing"><name>Outbound Message Processing</name>

<t>During outbound processing, the MTA invokes registered hooks as it delivers messages to remote SMTP servers. This supports use cases including delivery logging, compliance monitoring, and routing decisions.</t>

<t>The outbound flow proceeds as follows:</t>

<t><list style="numbers" type="1">
  <t>The MTA selects a queued message for delivery and identifies the recipients due for delivery at this time.</t>
  <t>The MTA attempts delivery to all selected recipients.</t>
  <t>After all attempts in this delivery job complete, the MTA invokes hooks registered for the "delivery" stage.</t>
  <t>If any recipient requires retry, the MTA invokes "defer" stage hooks.</t>
  <t>If the MTA generates a DSN, it invokes "dsn" stage hooks before sending.</t>
</list></t>

<t>A delivery job represents a single processing cycle where the MTA retrieves a message from the queue and attempts delivery to one or more recipients. The specific batching of recipients into delivery jobs is implementation-defined and may depend on factors such as destination domain, connection reuse, or queue configuration. The "delivery" stage hook is invoked once per delivery job after all recipient attempts within that job have completed.</t>

<t>Scanners may modify per-recipient delivery status, suppress DSN generation, or alter retry scheduling.</t>

</section>
<section anchor="modifications"><name>Modifications</name>

<t>Scanners communicate changes through modifications to the hook request object. Modifications are expressed as operations on JSON Pointers <xref target="RFC6901"/> referencing properties within the request structure.</t>

<t>Three modification operations are supported:</t>

<t><list style="symbols">
  <t>Set: Replace the value at a specified path.</t>
  <t>Add: Insert a value at a specified path, including array element insertion.</t>
  <t>Delete: Remove the value at a specified path.</t>
</list></t>

<t>The MTA applies modifications in a defined order: set operations first, followed by add operations, and finally delete operations. Any modification that fails (for example, referencing a non-existent path for deletion) <bcp14>SHOULD</bcp14> be logged and included in failure statistics, but <bcp14>MUST NOT</bcp14> cause the entire response to be rejected.</t>

<t>If a scanner modifies both the "message" and "rawMessage" properties, the "rawMessage" modification takes precedence and "message" modifications are ignored.</t>

</section>
</section>
<section anchor="discovery"><name>Discovery</name>

<t>MTAs discover scanner capabilities through a well-known HTTP endpoint. Discovery is <bcp14>OPTIONAL</bcp14>; scanner endpoints <bcp14>MAY</bcp14> alternatively be configured manually.</t>

<section anchor="well-known-endpoint"><name>Well-Known Endpoint</name>

<t>Scanners that support discovery <bcp14>MUST</bcp14> expose a discovery document at the path "/.well-known/mta-hooks". The MTA retrieves this document using an HTTP GET request.</t>

<t>The discovery endpoint <bcp14>MUST</bcp14> support JSON serialization. Support for CBOR serialization is <bcp14>OPTIONAL</bcp14>.</t>

</section>
<section anchor="discovery-document-format"><name>Discovery Document Format</name>

<t>The discovery document is a JSON or CBOR object containing the following fields:</t>

<dl newline="true">
  <dt><strong>version</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>The protocol version. This specification defines version "1.0".</t>
  </dd>
  <dt><strong>endpoints</strong>: <spanx style="verb">DiscoveryEndpoints</spanx></dt>
  <dd>
    <t>URLs for protocol operations.</t>
  </dd>
  <dt><strong>serialization</strong>: <spanx style="verb">String[]</spanx></dt>
  <dd>
    <t>Supported serialization formats. Valid values are "json" and "cbor".</t>
  </dd>
  <dt><strong>capabilities</strong>: <spanx style="verb">DiscoveryCapabilities</spanx></dt>
  <dd>
    <t>Supported protocol capabilities.</t>
  </dd>
  <dt><strong>limits</strong>: <spanx style="verb">DiscoveryLimits|null</spanx></dt>
  <dd>
    <t>Operational limits, or null if no specific limits are advertised.</t>
  </dd>
  <dt><strong>extensions</strong>: <spanx style="verb">String[]|null</spanx></dt>
  <dd>
    <t>Supported protocol extensions. Extension identifiers <bcp14>SHOULD</bcp14> use a reverse domain name prefix for vendor-specific extensions.</t>
  </dd>
</dl>

<t>A <strong>DiscoveryEndpoints</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>registration</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>URL path for submitting registration requests.</t>
  </dd>
  <dt><strong>deregistration</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>URL path template for deregistration, with "{registration_id}" placeholder.</t>
  </dd>
</dl>

<t>A <strong>DiscoveryCapabilities</strong> object has the following properties:</t>

<dl>
  <dt><strong>inbound</strong>: <spanx style="verb">DirectionCapabilities|null</spanx></dt>
  <dd>
    <t>Inbound processing capabilities, or null if inbound processing is not supported.</t>
  </dd>
  <dt><strong>outbound</strong>: <spanx style="verb">DirectionCapabilities|null</spanx></dt>
  <dd>
    <t>Outbound processing capabilities, or null if outbound processing is not supported.</t>
  </dd>
</dl>

<t>A <strong>DirectionCapabilities</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>stages</strong>: <spanx style="verb">String[]</spanx></dt>
  <dd>
    <t>Supported stages for this processing direction.</t>
  </dd>
  <dt><strong>actions</strong>: <spanx style="verb">String[]</spanx></dt>
  <dd>
    <t>Supported actions that scanners may request.</t>
  </dd>
  <dt><strong>fetchProperties</strong>: <spanx style="verb">String[]</spanx></dt>
  <dd>
    <t>JSON Pointers for properties the MTA can include in hook requests.</t>
  </dd>
  <dt><strong>updateProperties</strong>: <spanx style="verb">String[]</spanx></dt>
  <dd>
    <t>JSON Pointers for properties scanners may modify.</t>
  </dd>
</dl>

<t>A <strong>DiscoveryLimits</strong> object has the following properties:</t>

<dl>
  <dt><strong>maxMessageSize</strong>: <spanx style="verb">UnsignedInt|null</spanx></dt>
  <dd>
    <t>Maximum message size in bytes the scanner accepts.</t>
  </dd>
  <dt><strong>maxRegistrations</strong>: <spanx style="verb">UnsignedInt|null</spanx></dt>
  <dd>
    <t>Maximum concurrent registrations.</t>
  </dd>
  <dt><strong>timeoutMs</strong>: <spanx style="verb">UnsignedInt|null</spanx></dt>
  <dd>
    <t>Default timeout in milliseconds for hook invocations.</t>
  </dd>
</dl>

<t>The <spanx style="verb">fetchProperties</spanx> and <spanx style="verb">updateProperties</spanx> arrays contain JSON Pointers as defined in <xref target="RFC6901"/>.  Each pointer identifies a property within
the hook request structure that the MTA supports including or that scanners may modify. For example, "/envelope/from/address" refers to the sender's email address within the envelope object.</t>

<section anchor="example-discovery-document"><name>Example Discovery Document</name>

<figure><sourcecode type="json"><![CDATA[
{
  "version": "1.0",

  "endpoints": {
    "registration": "/v1/hooks/register",
    "deregistration": "/v1/hooks/register/{registration_id}"
  },

  "serialization": ["json", "cbor"],

  "capabilities": {
    "inbound": {
      "stages": ["connect", "ehlo", "mail", "rcpt", "data"],
      "actions": ["accept", "reject", "discard",
                  "quarantine", "disconnect"],
      "fetchProperties": ["/envelope", "/message", "/rawMessage",
                          "/server", "/tls", "/auth", "/senderAuth",
                          "/client", "/stage", "/action", 
                          "/timestamp","/response", "/protocol", 
                          "/queue"],
      "updateProperties": ["/envelope", "/message", "/rawMessage",
                           "/action", "/response"]
    },
    "outbound": {
      "stages": ["delivery", "defer", "dsn"],
      "actions": ["continue", "cancel"],
      "fetchProperties": ["/envelope", "/message", "/rawMessage",
                          "/server", "/queue", "/stage", "/action",
                          "/timestamp", "/protocol"],
      "updateProperties": ["/envelope/to", "/action", "/message",
                           "/rawMessage"]
    }
  },

  "limits": {
    "maxMessageSize": 52428800,
    "maxRegistrations": 64,
    "timeoutMs": 30000
  },

  "extensions": ["x-vendor-feature"]
}
]]></sourcecode></figure>

</section>
</section>
<section anchor="manual-configuration"><name>Manual Configuration</name>

<t>Discovery is <bcp14>OPTIONAL</bcp14>. Administrators <bcp14>MAY</bcp14> configure scanner endpoints manually, including capability restrictions and authentication credentials. Manual configuration may be necessary in environments where the well-known endpoint is not accessible or where policy requires explicit configuration.</t>

</section>
</section>
<section anchor="registration"><name>Registration</name>

<t>Scanners register with MTAs to establish callback configuration and negotiate capabilities. Registration creates a persistent relationship that remains active until explicit deregistration or expiration.</t>

<section anchor="registration-request"><name>Registration Request</name>

<t>Scanners submit registration requests via HTTP POST to the registration endpoint. The request body contains a JSON or CBOR object with the following fields:</t>

<dl newline="true">
  <dt><strong>name</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Human-readable name identifying the scanner.</t>
  </dd>
  <dt><strong>version</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>Scanner software version string.</t>
  </dd>
  <dt><strong>callback</strong>: <spanx style="verb">CallbackConfig</spanx></dt>
  <dd>
    <t>Callback configuration.</t>
  </dd>
  <dt><strong>expiresAt</strong>: <spanx style="verb">UTCDate|null</spanx></dt>
  <dd>
    <t>Requested registration expiration timestamp. The MTA <bcp14>MAY</bcp14> assign a different expiration based on policy.</t>
  </dd>
  <dt><strong>serialization</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Requested serialization format for hook requests. <bcp14>MUST</bcp14> be a value from the MTA's supported serialization list.</t>
  </dd>
  <dt><strong>inbound</strong>: <spanx style="verb">StageSubscription|null</spanx></dt>
  <dd>
    <t>Inbound hook configuration. Omit or set to null if not subscribing to inbound stages.</t>
  </dd>
  <dt><strong>outbound</strong>: <spanx style="verb">StageSubscription|null</spanx></dt>
  <dd>
    <t>Outbound hook configuration. Omit or set to null if not subscribing to outbound stages.</t>
  </dd>
  <dt><strong>filter</strong>: <spanx style="verb">FilterOperator|FilterCondition|null</spanx></dt>
  <dd>
    <t>Filter configuration to limit which messages trigger hooks. Uses filter syntax from <xref section="5.5" sectionFormat="of" target="RFC8620"/>.</t>
  </dd>
  <dt><strong>metadata</strong>: <spanx style="verb">String[String]|null</spanx></dt>
  <dd>
    <t>Arbitrary key-value pairs for scanner identification and operational metadata.</t>
  </dd>
</dl>

<t>A <strong>CallbackConfig</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>url</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>HTTPS URL where the MTA sends hook requests.</t>
  </dd>
  <dt><strong>timeoutMs</strong>: <spanx style="verb">UnsignedInt|null</spanx></dt>
  <dd>
    <t>Requested timeout in milliseconds. The MTA <bcp14>MAY</bcp14> ignore or cap this value.</t>
  </dd>
</dl>

<t>A <strong>StageSubscription</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>stages</strong>: <spanx style="verb">String[]</spanx></dt>
  <dd>
    <t>Stages to subscribe to. <bcp14>MUST</bcp14> be a subset of the MTA's supported stages for this direction.</t>
  </dd>
  <dt><strong>properties</strong>: <spanx style="verb">String[]|null</spanx></dt>
  <dd>
    <t>JSON Pointers specifying message properties to receive. A value of null requests all supported properties.</t>
  </dd>
</dl>

<t>At least one of "inbound" or "outbound" <bcp14>MUST</bcp14> be present and non-null in the registration request.</t>

<section anchor="filter-configuration"><name>Filter Configuration</name>

<t>The filter field uses the FilterOperator and FilterCondition syntax defined in <xref section="5.5" sectionFormat="of" target="RFC8620"/>. A FilterOperator combines multiple conditions using AND, OR, or NOT logic. A FilterCondition specifies criteria that a message must match.</t>

<t>Filter conditions follow <xref section="4.4.1" sectionFormat="of" target="RFC8621"/> with the following restrictions on metadata conditions: only the "size" condition from <xref section="4.1.1" sectionFormat="of" target="RFC8621"/> is permitted. All other metadata conditions are NOT supported as they depend on mailbox state or JMAP-specific concepts not applicable to MTA processing:</t>

<t><list style="symbols">
  <t>inMailbox</t>
  <t>inMailboxOtherThan</t>
  <t>before</t>
  <t>after</t>
  <t>minSize</t>
  <t>maxSize</t>
  <t>allInThreadHaveKeyword</t>
  <t>someInThreadHaveKeyword</t>
  <t>noneInThreadHaveKeyword</t>
  <t>hasKeyword</t>
  <t>notKeyword</t>
</list></t>

<t>All other filter conditions defined in <xref section="4.4.1" sectionFormat="of" target="RFC8621"/> are permitted by this specification, including text-matching conditions such as "from", "to", "cc", "bcc", "subject", "body", "header", and "text". However, support for specific conditions is determined by the MTA implementation. If a scanner specifies a filter condition that the MTA does not support, the registration <bcp14>MUST</bcp14> be rejected with an UNSUPPORTED_FILTER error.</t>

<t>The following additional conditions are defined for envelope filtering:</t>

<dl newline="true">
  <dt><strong>envelopeFrom</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Matches if the MAIL FROM address matches the given value. The value <bcp14>MAY</bcp14> include wildcards using the "*" character, which matches zero or more characters.</t>
  </dd>
  <dt><strong>envelopeTo</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Matches if any RCPT TO address matches the given value. The value <bcp14>MAY</bcp14> include wildcards using the "*" character, which matches zero or more characters.</t>
  </dd>
</dl>

<t>Filters apply only to the "data" stage for content-based conditions (those examining message headers or body). For the "mail" and "rcpt" stages, only envelopeFrom and envelopeTo conditions are evaluated; other conditions are ignored for these stages. Messages or envelope commands not matching the filter do not trigger hook invocations.</t>

</section>
<section anchor="example-registration-request"><name>Example Registration Request</name>

<figure><artwork><![CDATA[
POST /v1/hooks/register HTTP/1.1
Host: mta.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

{
  "name": "Acme Spam Filter",
  "version": "2.1.0",

  "callback": {
    "url": "https://scanner.example.com/hooks/scan",
    "timeoutMs": 25000
  },

  "expiresAt": "2025-12-21T15:30:00Z",

  "serialization": "json",

  "inbound": {
    "stages": ["data"],
    "properties": ["/message", "/envelope", "/senderAuth"]
  },

  "outbound": {
    "stages": ["delivery"],
    "properties": null
  },

  "filter": {
    "operator": "OR",
    "conditions": [
      {"from": "*@external.example.com"},
      {"envelopeFrom": "*@partner.example.org"}
    ]
  },

  "metadata": {
    "vendor": "acme-security",
    "environment": "production",
    "instance": "scanner-01"
  }
}
]]></artwork></figure>

</section>
</section>
<section anchor="callback-verification"><name>Callback Verification</name>

<t>Upon receiving a registration request, the MTA <bcp14>SHOULD</bcp14> verify that the callback URL is reachable and operated by the registering party. Verification proceeds as follows:</t>

<t><list style="numbers" type="1">
  <t>The MTA generates a unique verification token.</t>
  <t>The MTA sends an HTTP POST request to the callback URL with <spanx style="verb">Content-Type</spanx> set to the serialization format requested in the registration request. The request body contains:</t>
</list></t>

<figure><sourcecode type="json"><![CDATA[
{
  "action": "verify",
  "token": "vrf_8f3a2b1c9d4e5f6a7b8c9d0e1f2a3b4c"
}
]]></sourcecode></figure>

<t><list style="numbers" type="1">
  <t>The scanner <bcp14>MUST</bcp14> respond with HTTP status 200 and a body containing the same token:</t>
</list></t>

<figure><sourcecode type="json"><![CDATA[
{
  "token": "vrf_8f3a2b1c9d4e5f6a7b8c9d0e1f2a3b4c"
}
]]></sourcecode></figure>

<t><list style="numbers" type="1">
  <t>The MTA confirms the response token matches the request token.</t>
</list></t>

<t>If verification fails, the MTA <bcp14>MUST</bcp14> reject the registration request:</t>

<t><list style="symbols">
  <t>If the callback URL is unreachable or times out: HTTP 422 with error code CALLBACK_UNREACHABLE</t>
  <t>If the callback responds but the token does not match: HTTP 422 with error code CALLBACK_VERIFICATION_FAILED</t>
  <t>If the callback URL does not use HTTPS: HTTP 422 with error code TLS_REQUIRED</t>
  <t>If the callback URL's TLS certificate is invalid: HTTP 422 with error code TLS_CERTIFICATE_INVALID</t>
</list></t>

</section>
<section anchor="registration-response"><name>Registration Response</name>

<t>Upon successful registration, the MTA returns HTTP status 201 Created with a response body containing:</t>

<dl newline="true">
  <dt><strong>registrationId</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Unique identifier for this registration. The identifier <bcp14>MUST</bcp14> consist of ASCII alphanumeric characters plus hyphen (-), underscore (_), and colon (:), with a maximum length of 255 characters.</t>
  </dd>
  <dt><strong>status</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Registration status. Values are "active", "suspended", or "pending_verification".</t>
  </dd>
  <dt><strong>createdAt</strong>: <spanx style="verb">UTCDate</spanx></dt>
  <dd>
    <t>Timestamp of registration creation.</t>
  </dd>
  <dt><strong>expiresAt</strong>: <spanx style="verb">UTCDate|null</spanx></dt>
  <dd>
    <t>Timestamp when registration expires, or null if no expiration is set.</t>
  </dd>
  <dt><strong>callback</strong>: <spanx style="verb">CallbackConfig</spanx></dt>
  <dd>
    <t>Confirmed callback configuration, which may differ from the request if the MTA adjusted values.</t>
  </dd>
  <dt><strong>negotiated</strong>: <spanx style="verb">NegotiatedCapabilities</spanx></dt>
  <dd>
    <t>Final negotiated capabilities representing the intersection of scanner request and MTA support.</t>
  </dd>
  <dt><strong>endpoints</strong>: <spanx style="verb">RegistrationEndpoints</spanx></dt>
  <dd>
    <t>URLs for managing this registration.</t>
  </dd>
</dl>

<t>A <strong>NegotiatedCapabilities</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>serialization</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Confirmed serialization format.</t>
  </dd>
  <dt><strong>inbound</strong>: <spanx style="verb">NegotiatedSubscription|null</spanx></dt>
  <dd>
    <t>Confirmed inbound configuration, or null if not registered for inbound processing.</t>
  </dd>
  <dt><strong>outbound</strong>: <spanx style="verb">NegotiatedSubscription|null</spanx></dt>
  <dd>
    <t>Confirmed outbound configuration, or null if not registered for outbound processing.</t>
  </dd>
</dl>

<t>A <strong>NegotiatedSubscription</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>stages</strong>: <spanx style="verb">String[]</spanx></dt>
  <dd>
    <t>Confirmed stages.</t>
  </dd>
  <dt><strong>properties</strong>: <spanx style="verb">String[]</spanx></dt>
  <dd>
    <t>Confirmed property list.</t>
  </dd>
</dl>

<t>A <strong>RegistrationEndpoints</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>deregistration</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>URL for deregistration requests.</t>
  </dd>
  <dt><strong>status</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>URL for status queries.</t>
  </dd>
</dl>

<section anchor="example-registration-response"><name>Example Registration Response</name>

<figure><artwork><![CDATA[
HTTP/1.1 201 Created
Content-Type: application/json
Location: /v1/hooks/register/reg_7a3b9c2e-4d5f-6a7b-8c9d-0e1f2a3b4c5d

{
  "registrationId": "reg_7a3b9c2e-4d5f-6a7b-8c9d-0e1f2a3b4c5d",
  "status": "active",
  "createdAt": "2024-12-21T15:30:00Z",
  "expiresAt": "2025-12-21T15:30:00Z",

  "callback": {
    "url": "https://scanner.example.com/hooks/scan",
    "timeoutMs": 25000
  },

  "negotiated": {
    "serialization": "json",
    "inbound": {
      "stages": ["data"],
      "properties": ["/message", "/envelope", "/senderAuth"]
    },
    "outbound": {
      "stages": ["delivery"],
      "properties": ["/message", "/envelope", "/queue", "/server"]
    }
  },

  "endpoints": {
    "deregistration": "/v1/hooks/register/reg_7a3b9c2e",
    "status": "/v1/hooks/register/reg_7a3b9c2e/status"
  }
}
]]></artwork></figure>

</section>
</section>
<section anchor="authentication"><name>Authentication</name>

<t>Authentication for registration requests is <bcp14>REQUIRED</bcp14> but the specific mechanism is out of scope for this specification. Implementations <bcp14>SHOULD</bcp14> support at least one of the following authentication methods:</t>

<t><list style="symbols">
  <t>Bearer tokens via the HTTP Authorization header</t>
  <t>Mutual TLS with client certificate verification</t>
  <t>HMAC-based pre-shared key authentication</t>
</list></t>

<t>See <xref target="security-considerations"/> for deployment guidance on authentication.</t>

</section>
<section anchor="registration-lifecycle"><name>Registration Lifecycle</name>

<section anchor="status-queries"><name>Status Queries</name>

<t>Scanners <bcp14>MAY</bcp14> query their registration status via HTTP GET to the status endpoint returned during registration.</t>

<figure><artwork><![CDATA[
GET /v1/hooks/register/reg_7a3b9c2e/status HTTP/1.1
Host: mta.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
]]></artwork></figure>

<t>The response contains registration status and optional statistics:</t>

<dl newline="true">
  <dt><strong>registrationId</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>The registration identifier.</t>
  </dd>
  <dt><strong>status</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Current status: "active", "suspended", or "deregistered".</t>
  </dd>
  <dt><strong>createdAt</strong>: <spanx style="verb">UTCDate|null</spanx></dt>
  <dd>
    <t>Timestamp of creation.</t>
  </dd>
  <dt><strong>expiresAt</strong>: <spanx style="verb">UTCDate|null</spanx></dt>
  <dd>
    <t>Timestamp of expiration.</t>
  </dd>
  <dt><strong>lastInvocation</strong>: <spanx style="verb">UTCDate|null</spanx></dt>
  <dd>
    <t>Timestamp of most recent hook invocation.</t>
  </dd>
  <dt><strong>statistics</strong>: <spanx style="verb">RegistrationStatistics|null</spanx></dt>
  <dd>
    <t>Operational statistics.</t>
  </dd>
  <dt><strong>health</strong>: <spanx style="verb">HealthStatus|null</spanx></dt>
  <dd>
    <t>Health check status.</t>
  </dd>
</dl>

<t>A <strong>RegistrationStatistics</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>invocations</strong>: <spanx style="verb">InvocationCounts</spanx></dt>
  <dd>
    <t>Invocation counts.</t>
  </dd>
  <dt><strong>errors</strong>: <spanx style="verb">InvocationCounts</spanx></dt>
  <dd>
    <t>Error counts with the same time period structure as invocations.</t>
  </dd>
  <dt><strong>averageResponseMs</strong>: <spanx style="verb">Number</spanx></dt>
  <dd>
    <t>Average response time in milliseconds.</t>
  </dd>
</dl>

<t>An <strong>InvocationCounts</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>total</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Total count since registration.</t>
  </dd>
  <dt><strong>last24h</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Count in past 24 hours.</t>
  </dd>
  <dt><strong>last7d</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Count in past 7 days.</t>
  </dd>
  <dt><strong>last30d</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Count in past 30 days.</t>
  </dd>
</dl>

<t>A <strong>HealthStatus</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>status</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Health status: "healthy", "degraded", or "unhealthy".</t>
  </dd>
  <dt><strong>lastCheck</strong>: <spanx style="verb">UTCDate</spanx></dt>
  <dd>
    <t>Timestamp of last health check.</t>
  </dd>
  <dt><strong>consecutiveFailures</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Count of consecutive failed health checks.</t>
  </dd>
</dl>

</section>
<section anchor="example-status-response"><name>Example Status Response</name>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "registrationId": "reg_7a3b9c2e-4d5f-6a7b-8c9d-0e1f2a3b4c5d",
  "status": "active",
  "createdAt": "2024-12-21T15:30:00Z",
  "expiresAt": "2025-12-21T15:30:00Z",
  "lastInvocation": "2024-12-21T16:42:18Z",

  "statistics": {
    "invocations": {
      "total": 15482,
      "last24h": 3241,
      "last7d": 10234,
      "last30d": 43210
    },
    "errors": {
      "total": 32,
      "last24h": 5,
      "last7d": 12,
      "last30d": 28
    },
    "averageResponseMs": 45
  },

  "health": {
    "status": "healthy",
    "lastCheck": "2024-12-21T16:44:00Z",
    "consecutiveFailures": 0
  }
}
]]></artwork></figure>

</section>
<section anchor="registration-expiration-and-renewal"><name>Registration Expiration and Renewal</name>

<t>Registrations <bcp14>MAY</bcp14> have an expiration time set by the MTA based on policy. Scanners <bcp14>MUST</bcp14> re-register before expiration to maintain continuous service. Re-registration follows the same process as initial registration and requires full capability renegotiation.</t>

<t>The MTA <bcp14>SHOULD</bcp14> provide advance notice of pending expiration through the status endpoint. Scanners <bcp14>SHOULD</bcp14> monitor their registration status and initiate re-registration before expiration.</t>

</section>
</section>
<section anchor="deregistration"><name>Deregistration</name>

<t>Scanners deregister by sending an HTTP DELETE request to the deregistration endpoint.</t>

<figure><artwork><![CDATA[
DELETE /v1/hooks/register/reg_7a3b9c2e HTTP/1.1
Host: mta.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
]]></artwork></figure>

<t>Upon successful deregistration, the MTA returns HTTP status 200 with confirmation:</t>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "registrationId": "reg_7a3b9c2e-4d5f-6a7b-8c9d-0e1f2a3b4c5d",
  "status": "deregistered",
  "deregisteredAt": "2024-12-21T16:45:00Z"
}
]]></artwork></figure>

<t>After deregistration, the MTA <bcp14>MUST NOT</bcp14> send further hook invocations to the scanner's callback URL.</t>

<section anchor="in-flight-requests"><name>In-Flight Requests</name>

<t>Hook invocations that are in-flight at the time of deregistration <bcp14>MAY</bcp14> complete normally. The MTA <bcp14>SHOULD</bcp14> accept and process responses from these in-flight invocations. Scanners <bcp14>SHOULD</bcp14> continue to respond to hook requests that arrive during or shortly after deregistration processing, as network latency may cause requests dispatched before deregistration to arrive afterward.</t>

<t>Once deregistration completes, the MTA <bcp14>MUST NOT</bcp14> initiate new hook invocations to the deregistered scanner's callback URL. The MTA <bcp14>SHOULD</bcp14> allow a brief grace period (implementation-defined, but typically a few seconds) for in-flight responses before considering the deregistration fully complete.</t>

</section>
<section anchor="automatic-deregistration"><name>Automatic Deregistration</name>

<t>The MTA <bcp14>MAY</bcp14> automatically deregister scanners that become unreachable. Implementation-specific policies govern the threshold for automatic deregistration, such as consecutive failure counts or timeout periods. The MTA <bcp14>SHOULD</bcp14> log automatic deregistrations for operational visibility.</t>

</section>
</section>
</section>
<section anchor="hook-request"><name>Hook Request</name>

<t>When processing reaches a stage for which scanners are registered, the MTA constructs a hook request and transmits it to each registered scanner's callback URL.</t>

<section anchor="request-structure"><name>Request Structure</name>

<t>Hook requests are transmitted via HTTP POST to the scanner's callback URL. The <spanx style="verb">Content-Type</spanx> header indicates the serialization format negotiated during registration.</t>

<t>The MTA <bcp14>MAY</bcp14> include an <spanx style="verb">X-MTA-Hooks-Registration</spanx> header containing the registration identifier. This header is <bcp14>OPTIONAL</bcp14> but can assist scanners that handle multiple registrations at a single endpoint.</t>

<t>The request body contains a JSON or CBOR object with properties determined by the scanner's registration. The following sections describe available properties organized by category.</t>

</section>
<section anchor="common-properties"><name>Common Properties</name>

<t>The following properties are available for both inbound and outbound processing:</t>

<dl newline="true">
  <dt><strong>stage</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>The current processing stage.</t>
  </dd>
  <dt><strong>action</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>The action the MTA will perform if no scanner modifications occur. For inbound processing, values are "accept", "reject", "discard", "quarantine", or "disconnect". For outbound processing, values are "continue" or "cancel".</t>
  </dd>
  <dt><strong>envelope</strong>: <spanx style="verb">Envelope</spanx></dt>
  <dd>
    <t>The message envelope containing sender and recipient information.</t>
  </dd>
  <dt><strong>message</strong>: <spanx style="verb">Object|null</spanx></dt>
  <dd>
    <t>A structured representation of the email message based on the Email object defined in <xref section="4" sectionFormat="of" target="RFC8621"/>.</t>
  </dd>
  <dt><strong>rawMessage</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>The complete message in Internet Message Format as defined in <xref target="RFC5322"/>. In JSON serialization, the value is Base64-encoded. In CBOR serialization, the value is a raw byte string.</t>
  </dd>
  <dt><strong>timestamp</strong>: <spanx style="verb">UTCDate</spanx></dt>
  <dd>
    <t>Timestamp when the current stage began.</t>
  </dd>
  <dt><strong>protocol</strong>: <spanx style="verb">ProtocolInfo|null</spanx></dt>
  <dd>
    <t>Protocol information.</t>
  </dd>
  <dt><strong>queue</strong>: <spanx style="verb">QueueInfo|null</spanx></dt>
  <dd>
    <t>Queue information.</t>
  </dd>
  <dt><strong>server</strong>: <spanx style="verb">ServerInfo|null</spanx></dt>
  <dd>
    <t>Information about the MTA.</t>
  </dd>
</dl>

</section>
<section anchor="envelope-properties"><name>Envelope Properties</name>

<t>An <strong>Envelope</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>from</strong>: <spanx style="verb">EnvelopeAddress</spanx></dt>
  <dd>
    <t>Sender information from MAIL FROM command.</t>
  </dd>
  <dt><strong>to</strong>: <spanx style="verb">EnvelopeAddress[]|DeliveryRecipient[]</spanx></dt>
  <dd>
    <t>Recipient information from RCPT TO commands. For inbound processing, this is an array of EnvelopeAddress objects. For outbound processing, this is an array of DeliveryRecipient objects.</t>
  </dd>
</dl>

<t>An <strong>EnvelopeAddress</strong> object represents an address in the message envelope and has the following properties:</t>

<dl>
  <dt><strong>address</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>The email address. For MAIL FROM, this <bcp14>MAY</bcp14> be null to represent the null reverse-path. For RCPT TO, this <bcp14>MUST NOT</bcp14> be null.</t>
  </dd>
  <dt><strong>parameters</strong>: <spanx style="verb">String[String]</spanx></dt>
  <dd>
    <t>SMTP parameters associated with the address as key-value pairs. Common parameters include ORCPT, ENVID, and other DSN-related parameters defined in <xref target="RFC3461"/>.</t>
  </dd>
</dl>

<t>For outbound processing, recipient objects include additional delivery status fields described in <xref target="outbound-properties"/>.</t>

</section>
<section anchor="queue-properties"><name>Queue Properties</name>

<t>A <strong>QueueInfo</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>id</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Unique queue identifier for this message within this MTA. The identifier <bcp14>MUST</bcp14> be unique for the lifetime of the message in the queue and <bcp14>SHOULD</bcp14> remain stable across hook invocations for the same queued message.</t>
  </dd>
</dl>

</section>
<section anchor="message-properties"><name>Message Properties</name>

<section anchor="structured-message"><name>Structured Message</name>

<t>The <spanx style="verb">message</spanx> property contains a structured representation of the email message based on the Email object defined in <xref section="4" sectionFormat="of" target="RFC8621"/>. The following differences from the JMAP Email object apply:</t>

<t><list style="symbols">
  <t>Metadata properties defined in <xref section="4.1.1" sectionFormat="of" target="RFC8621"/> are not included, with the exception of the "size" property which <bcp14>MAY</bcp14> be present.</t>
  <t>The <spanx style="verb">blobId</spanx> property is replaced by a <spanx style="verb">blob</spanx> property containing the actual content. In JSON serialization, blob values are Base64-encoded strings. In CBOR serialization, blob values are raw byte strings.</t>
</list></t>

<t>Property availability depends on the processing stage and MTA capabilities. At early stages such as "connect" or "ehlo", message properties are not available.</t>

</section>
<section anchor="raw-message"><name>Raw Message</name>

<t>The <spanx style="verb">rawMessage</spanx> property contains the complete message in Internet Message Format as defined in <xref target="RFC5322"/>, including all MIME parts
and attachments. In JSON serialization, the value is Base64-encoded. In CBOR serialization, the value is a raw byte string.</t>

<t>The <spanx style="verb">rawMessage</spanx> property represents the entire message as stored or received by the MTA. When present, it provides byte-exact access to the message content, which is necessary for operations such as cryptographic signature verification.</t>

<t>Scanners <bcp14>MAY</bcp14> request both <spanx style="verb">message</spanx> and <spanx style="verb">rawMessage</spanx> properties. If a scanner's response modifies both properties, only <spanx style="verb">rawMessage</spanx> modifications are applied; <spanx style="verb">message</spanx> modifications are ignored.</t>

<t>The raw message content <bcp14>MUST NOT</bcp14> appear within the <spanx style="verb">message</spanx> property as a blob value. The <spanx style="verb">message</spanx> property contains only the structured parsed representation with individual body part contents available via <spanx style="verb">bodyValues</spanx>, while <spanx style="verb">rawMessage</spanx> contains the complete unparsed message.</t>

</section>
<section anchor="choosing-between-structured-and-raw"><name>Choosing Between Structured and Raw</name>

<t>The <spanx style="verb">message</spanx> property provides a structured, parsed representation suitable for:</t>

<t><list style="symbols">
  <t>Header inspection and modification</t>
  <t>Recipient analysis</t>
  <t>Content-type aware body part processing</t>
  <t>Efficient access to specific message components</t>
</list></t>

<t>The <spanx style="verb">rawMessage</spanx> property provides the complete RFC 5322 message suitable for:</t>

<t><list style="symbols">
  <t>Cryptographic verification (DKIM signature validation)</t>
  <t>Archival or compliance logging</t>
  <t>Processing that requires byte-exact message content</t>
  <t>Forwarding or re-injection without modification</t>
</list></t>

<t>Scanners that need both structured access and raw content <bcp14>SHOULD</bcp14> request both properties. When modifying messages, scanners <bcp14>SHOULD</bcp14> prefer structured modifications via the <spanx style="verb">message</spanx> property unless byte-exact control is required. Modifications to <spanx style="verb">rawMessage</spanx> require the scanner to produce a complete, valid RFC 5322 message.</t>

</section>
</section>
<section anchor="server-properties"><name>Server Properties</name>

<t>A <strong>ServerInfo</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>name</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Server hostname.</t>
  </dd>
  <dt><strong>ip</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Server IP address.</t>
  </dd>
  <dt><strong>port</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Server port number.</t>
  </dd>
</dl>

</section>
<section anchor="protocol-properties"><name>Protocol Properties</name>

<t>A <strong>ProtocolInfo</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>version</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>MTA Hooks protocol version.</t>
  </dd>
</dl>

</section>
<section anchor="inbound-properties"><name>Inbound Properties</name>

<t>The following properties are available only during inbound processing:</t>

<dl>
  <dt><strong>response</strong>: <spanx style="verb">SmtpResponse|null</spanx></dt>
  <dd>
    <t>The SMTP response the MTA would send if no scanner modifications occur.</t>
  </dd>
  <dt><strong>client</strong>: <spanx style="verb">ClientInfo|null</spanx></dt>
  <dd>
    <t>Information about the connecting SMTP client.</t>
  </dd>
  <dt><strong>senderAuth</strong>: <spanx style="verb">SenderAuthentication|null</spanx></dt>
  <dd>
    <t>Results of sender authentication checks.</t>
  </dd>
  <dt><strong>auth</strong>: <spanx style="verb">SmtpAuthentication|null</spanx></dt>
  <dd>
    <t>SMTP authentication information, if the client authenticated.</t>
  </dd>
  <dt><strong>tls</strong>: <spanx style="verb">TlsInfo|null</spanx></dt>
  <dd>
    <t>TLS connection information.</t>
  </dd>
</dl>

<section anchor="smtp-response-properties"><name>SMTP Response Properties</name>

<t>An <strong>SmtpResponse</strong> object represents an SMTP response and has the following properties:</t>

<dl newline="true">
  <dt><strong>code</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>The three-digit SMTP status code.</t>
  </dd>
  <dt><strong>enhancedCode</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>The enhanced status code as defined in <xref target="RFC3461"/>, if available.</t>
  </dd>
  <dt><strong>message</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>The human-readable response text.</t>
  </dd>
</dl>

</section>
<section anchor="client-properties"><name>Client Properties</name>

<t>A <strong>ClientInfo</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>ip</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Client IP address.</t>
  </dd>
  <dt><strong>port</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Client port number.</t>
  </dd>
  <dt><strong>ptr</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>PTR record for client IP, if available.</t>
  </dd>
  <dt><strong>ehlo</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>EHLO or HELO string sent by client.</t>
  </dd>
  <dt><strong>asn</strong>: <spanx style="verb">UnsignedInt|null</spanx></dt>
  <dd>
    <t>Autonomous System Number for client IP, if available.</t>
  </dd>
  <dt><strong>country</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>ISO 3166-1 alpha-2 country code for client IP, if available.</t>
  </dd>
  <dt><strong>activeConnections</strong>: <spanx style="verb">UnsignedInt|null</spanx></dt>
  <dd>
    <t>Number of concurrent connections from this client.</t>
  </dd>
</dl>

</section>
<section anchor="tls-properties"><name>TLS Properties</name>

<t>A <strong>TlsInfo</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>version</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>TLS protocol version (e.g., "TLSv1.3").</t>
  </dd>
  <dt><strong>cipher</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Cipher suite name.</t>
  </dd>
  <dt><strong>cipherBits</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Cipher key length in bits.</t>
  </dd>
  <dt><strong>certIssuer</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>Client certificate issuer, if a client certificate was presented.</t>
  </dd>
  <dt><strong>certSubject</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>Client certificate subject, if a client certificate was presented.</t>
  </dd>
</dl>

</section>
<section anchor="sender-authentication-properties"><name>Sender Authentication Properties</name>

<t>A <strong>SenderAuthentication</strong> object has the following properties:</t>

<dl>
  <dt><strong>spf-ehlo</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>SPF result for EHLO identity as defined in <xref target="RFC7208"/>.</t>
  </dd>
  <dt><strong>spf-mail</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>SPF result for MAIL FROM identity as defined in <xref target="RFC7208"/>.</t>
  </dd>
  <dt><strong>dkim</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>DKIM verification result as defined in <xref target="RFC6376"/>.</t>
  </dd>
  <dt><strong>arc</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>ARC verification result.</t>
  </dd>
  <dt><strong>dmarc</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>DMARC evaluation result as defined in <xref target="RFC7489"/>.</t>
  </dd>
</dl>

<t>Authentication result values follow the conventions established in the respective specifications.</t>

</section>
<section anchor="smtp-authentication-properties"><name>SMTP Authentication Properties</name>

<t>An <strong>SmtpAuthentication</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>login</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Authenticated username.</t>
  </dd>
  <dt><strong>method</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>SASL mechanism used for authentication.</t>
  </dd>
</dl>

</section>
</section>
<section anchor="outbound-properties"><name>Outbound Properties</name>

<t>The following properties are available only during outbound processing.</t>

<section anchor="extended-queue-properties"><name>Extended Queue Properties</name>

<t>For outbound processing, the queue property uses an <strong>OutboundQueueInfo</strong> object, which extends QueueInfo with additional fields:</t>

<dl newline="true">
  <dt><strong>id</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>Unique queue identifier for this message.</t>
  </dd>
  <dt><strong>expiresAt</strong>: <spanx style="verb">UTCDate|null</spanx></dt>
  <dd>
    <t>Timestamp when the queue entry expires.</t>
  </dd>
  <dt><strong>attempts</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>Total delivery attempts made so far.</t>
  </dd>
</dl>

</section>
<section anchor="recipient-delivery-status"><name>Recipient Delivery Status</name>

<t>For outbound processing, each recipient in envelope.to is represented as a DeliveryRecipient object.</t>

<t>A <strong>DeliveryRecipient</strong> object extends EnvelopeAddress with delivery status information and has the following properties:</t>

<dl newline="true">
  <dt><strong>address</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>The recipient email address.</t>
  </dd>
  <dt><strong>parameters</strong>: <spanx style="verb">String[String]</spanx></dt>
  <dd>
    <t>SMTP parameters associated with the address as key-value pairs.</t>
  </dd>
  <dt><strong>status</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>The delivery status for this recipient. Values are "pending", "delivered", "deferred", "failed", or "failed-silent".</t>
  </dd>
  <dt><strong>attempt</strong>: <spanx style="verb">UnsignedInt</spanx></dt>
  <dd>
    <t>The current delivery attempt number for this recipient.</t>
  </dd>
  <dt><strong>lastResponse</strong>: <spanx style="verb">SmtpResponse|null</spanx></dt>
  <dd>
    <t>The last SMTP response received for this recipient, or null if no attempt has been made.</t>
  </dd>
  <dt><strong>nextAttemptAt</strong>: <spanx style="verb">UTCDate|null</spanx></dt>
  <dd>
    <t>The scheduled time for the next delivery attempt, or null if no retry is scheduled.</t>
  </dd>
  <dt><strong>nextDsnAt</strong>: <spanx style="verb">UTCDate|null</spanx></dt>
  <dd>
    <t>The scheduled time for the next DSN generation, or null if no DSN is scheduled.</t>
  </dd>
  <dt><strong>queueName</strong>: <spanx style="verb">String|null</spanx></dt>
  <dd>
    <t>The name of the outbound queue handling this recipient, if applicable.</t>
  </dd>
</dl>

<t>For the "dsn" stage, the <spanx style="verb">message</spanx> and <spanx style="verb">rawMessage</spanx> properties contain the DSN message that the MTA is about to send. Scanners <bcp14>MAY</bcp14> modify or delete these properties to alter or suppress DSN generation.</t>

</section>
</section>
<section anchor="example-inbound-hook-request"><name>Example Inbound Hook Request</name>

<figure><artwork><![CDATA[
POST /hooks/scan HTTP/1.1
Host: scanner.example.com
Content-Type: application/json
X-MTA-Hooks-Registration: reg_7a3b9c2e

{
  "stage": "data",
  "action": "accept",
  "timestamp": "2024-12-21T16:30:00Z",

  "response": {
    "code": 250,
    "enhancedCode": "2.0.0",
    "message": "OK"
  },

  "protocol": {
    "version": "1.0"
  },

  "queue": {
    "id": "queue_abc123"
  },

  "envelope": {
    "from": {
      "address": "sender@example.org",
      "parameters": {}
    },
    "to": [
      {
        "address": "recipient@example.com",
        "parameters": {}
      }
    ]
  },

  "message": {
    "size": 2048,
    "subject": "Meeting Tomorrow",
    "from": [
      {
        "name": "Sender Name",
        "email": "sender@example.org"
      }
    ],
    "to": [
      {
        "email": "recipient@example.com"
      }
    ],
    "sentAt": "2024-12-21T16:29:00Z",
    "messageId": ["<msg123@example.org>"],
    "headers": [
      {"name": "From", "value": "Sender Name <sender@example.org>"},
      {"name": "To", "value": "recipient@example.com"},
      {"name": "Subject", "value": "Meeting Tomorrow"},
      {"name": "Date", "value": "Sat, 21 Dec 2024 16:29:00 +0000"},
      {"name": "Message-ID", "value": "<msg123@example.org>"}
    ],
    "bodyStructure": {
      "type": "text/plain",
      "charset": "utf-8",
      "size": 28
    },
    "bodyValues": {
      "1": {
        "value": "Let's meet tomorrow at 10am.",
        "isEncodingProblem": false,
        "isTruncated": false
      }
    }
  },

  "client": {
    "ip": "192.0.2.100",
    "port": 54321,
    "ptr": "mail.example.org",
    "ehlo": "mail.example.org",
    "activeConnections": 3
  },

  "server": {
    "name": "mx1.example.com",
    "ip": "198.51.100.25",
    "port": 25
  },

  "tls": {
    "version": "TLSv1.3",
    "cipher": "TLS_AES_256_GCM_SHA384",
    "cipherBits": 256
  },

  "senderAuth": {
    "spf-mail": "pass",
    "dkim": "pass",
    "dmarc": "pass"
  }
}
]]></artwork></figure>

</section>
<section anchor="example-outbound-hook-request"><name>Example Outbound Hook Request</name>

<figure><artwork><![CDATA[
POST /hooks/delivery HTTP/1.1
Host: scanner.example.com
Content-Type: application/json
X-MTA-Hooks-Registration: reg_7a3b9c2e

{
  "stage": "delivery",
  "action": "continue",
  "timestamp": "2024-12-21T17:00:00Z",

  "protocol": {
    "version": "1.0"
  },

  "queue": {
    "id": "queue_def456",
    "expiresAt": "2024-12-24T17:00:00Z",
    "attempts": 3
  },

  "envelope": {
    "from": {
      "address": "notifications@example.com",
      "parameters": {}
    },
    "to": [
      {
        "address": "user1@recipient.example",
        "parameters": {},
        "status": "delivered",
        "attempt": 1,
        "lastResponse": {
          "code": 250,
          "enhancedCode": "2.0.0",
          "message": "Message accepted"
        }
      },
      {
        "address": "user2@recipient.example",
        "parameters": {},
        "status": "deferred",
        "attempt": 3,
        "lastResponse": {
          "code": 451,
          "enhancedCode": "4.7.1",
          "message": "Try again later"
        },
        "nextAttemptAt": "2024-12-21T18:00:00Z",
        "nextDsnAt": "2024-12-22T17:00:00Z"
      }
    ]
  },

  "message": {
    "subject": "Your order has shipped",
    "from": [{"email": "notifications@example.com"}],
    "to": [
      {"email": "user1@recipient.example"},
      {"email": "user2@recipient.example"}
    ],
    "size": 4096
  },

  "server": {
    "name": "smtp-out.example.com",
    "ip": "198.51.100.50",
    "port": 25
  }
}
]]></artwork></figure>

</section>
</section>
<section anchor="hook-response"><name>Hook Response</name>

<t>Scanners respond to hook requests with modifications to the request object. These modifications instruct the MTA how to proceed with message processing.</t>

<section anchor="response-structure"><name>Response Structure</name>

<t>Scanners respond with an HTTP 200 status code. The response body contains a JSON or CBOR object specifying modifications to apply to the hook request. The object has the following fields:</t>

<dl>
  <dt><strong>set</strong>: <spanx style="verb">SetOperation[]|null</spanx></dt>
  <dd>
    <t>An array of set operations to apply, or null if no set operations.</t>
  </dd>
  <dt><strong>add</strong>: <spanx style="verb">AddOperation[]|null</spanx></dt>
  <dd>
    <t>An array of add operations to apply, or null if no add operations.</t>
  </dd>
  <dt><strong>delete</strong>: <spanx style="verb">DeleteOperation[]|null</spanx></dt>
  <dd>
    <t>An array of delete operations to apply, or null if no delete
operations.</t>
  </dd>
</dl>

<t>A <strong>SetOperation</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>path</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>JSON Pointer (per <xref target="RFC6901"/>) to the property to replace.</t>
  </dd>
  <dt><strong>value</strong>: <spanx style="verb">any</spanx></dt>
  <dd>
    <t>The new value for the property.</t>
  </dd>
</dl>

<t>An <strong>AddOperation</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>path</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>JSON Pointer to the location where the value should be added.</t>
  </dd>
  <dt><strong>value</strong>: <spanx style="verb">any</spanx></dt>
  <dd>
    <t>The value to add.</t>
  </dd>
  <dt><strong>index</strong>: <spanx style="verb">UnsignedInt|null</spanx></dt>
  <dd>
    <t>For array additions, the zero-based index at which to insert the
value. If null or omitted, the value is appended to the array.</t>
  </dd>
</dl>

<t>A <strong>DeleteOperation</strong> object has the following properties:</t>

<dl newline="true">
  <dt><strong>path</strong>: <spanx style="verb">String</spanx></dt>
  <dd>
    <t>JSON Pointer to the property to remove.</t>
  </dd>
</dl>

</section>
<section anchor="actions"><name>Actions</name>

<t>Scanners change the MTA's action by including a set operation targeting the "/action" path. The following values are valid for inbound and outbound processing respectively.</t>

<t>The following action values are valid:</t>

<section anchor="inbound-actions"><name>Inbound Actions</name>

<dl newline="true">
  <dt><strong>accept</strong></dt>
  <dd>
    <t>Accept the message for delivery to recipients. Non-terminal; chain
continues.</t>
  </dd>
  <dt><strong>reject</strong></dt>
  <dd>
    <t>Reject the message and return an error response to the sending
client. Terminal; chain stops.</t>
  </dd>
  <dt><strong>discard</strong></dt>
  <dd>
    <t>Accept the message from the client but do not deliver it. The
client receives a success response. Terminal; chain stops.</t>
  </dd>
  <dt><strong>quarantine</strong></dt>
  <dd>
    <t>Accept the message and place it in quarantine for administrative
review. Quarantine location and handling are implementation-defined.
Non-terminal; chain continues.</t>
  </dd>
  <dt><strong>disconnect</strong></dt>
  <dd>
    <t>Terminate the SMTP connection immediately. Terminal; chain stops.</t>
  </dd>
</dl>

</section>
<section anchor="outbound-actions"><name>Outbound Actions</name>

<dl>
  <dt><strong>continue</strong></dt>
  <dd>
    <t>Proceed with normal processing. Non-terminal; chain continues.</t>
  </dd>
  <dt><strong>cancel</strong></dt>
  <dd>
    <t>Cancel all pending deliveries for this message. Terminal; chain stops.</t>
  </dd>
</dl>

</section>
</section>
<section anchor="modifications-1"><name>Modifications</name>

<t>Scanners communicate changes by specifying operations on the hook request object. The response contains JSON Pointer paths identifying properties to modify and the operations to perform. These modifications can alter any aspect of the transaction that the MTA permits, including:</t>

<t><list style="symbols">
  <t>The action the MTA should take (accept, reject, quarantine, etc.)</t>
  <t>The SMTP response to send to the client or expect from the server</t>
  <t>Message headers and body content</t>
  <t>Envelope addresses (sender and recipients)</t>
  <t>Per-recipient delivery status for outbound processing</t>
</list></t>

<t>Three modification operations are supported:</t>

<dl newline="true">
  <dt><strong>set</strong></dt>
  <dd>
    <t>Replace the value at a specified path with a new value.</t>
  </dd>
  <dt><strong>add</strong></dt>
  <dd>
    <t>Insert a value at a specified path. For objects, this adds a new
property. For arrays, this inserts an element at the specified
index or appends if no index is given.</t>
  </dd>
  <dt><strong>delete</strong></dt>
  <dd>
    <t>Remove the value at a specified path.</t>
  </dd>
</dl>

<section anchor="set-operations"><name>Set Operations</name>

<t>Set operations replace values at specified paths.</t>

<figure><sourcecode type="json"><![CDATA[
{
  "set": [
    {
      "path": "/action",
      "value": "reject"
    },
    {
      "path": "/response",
      "value": {
        "code": 550,
        "enhancedCode": "5.7.1",
        "message": "Message rejected due to policy"
      }
    }
  ]
}
]]></sourcecode></figure>

</section>
<section anchor="add-operations"><name>Add Operations</name>

<t>Add operations insert new values. For arrays, an optional index specifies insertion position.</t>

<figure><sourcecode type="json"><![CDATA[
{
  "add": [
    {
      "path": "/message/headers",
      "value": {"name": "X-Spam-Score", "value": "5.2"},
      "index": 0
    },
    {
      "path": "/envelope/to",
      "value": {
        "address": "archive@example.com",
        "parameters": {}
      }
    }
  ]
}
]]></sourcecode></figure>

</section>
<section anchor="delete-operations"><name>Delete Operations</name>

<t>Delete operations remove values at specified paths. When deleting array elements, indices refer to positions in the array at the time each delete operation executes. Because delete operations execute sequentially and earlier deletions cause subsequent elements to shift to lower indices, scanners <bcp14>SHOULD</bcp14> order array deletions from highest to lowest index to avoid unexpected results.</t>

<t>For example, to delete elements originally at indices 1 and 3 from an array:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "delete": [
    {"path": "/message/headers/3"},
    {"path": "/message/headers/1"}
  ]
}
]]></sourcecode></figure>

<t>Deleting index 3 first leaves the element originally at index 1 still at index 1. If the order were reversed, deleting index 1 first would shift the element originally at index 3 to index 2.</t>

</section>
<section anchor="modification-order"><name>Modification Order</name>

<t>The MTA applies modifications in the following order:</t>

<t><list style="numbers" type="1">
  <t>Set operations</t>
  <t>Add operations</t>
  <t>Delete operations</t>
</list></t>

<t>This ordering allows predictable results when multiple operations affect related paths.</t>

<t>To change the action the MTA takes, the scanner sets the "/action" path to the desired value. To modify the SMTP response, the scanner can either set individual response fields (e.g., "/response/code", "/response/message") or replace the entire response object by setting "/response".</t>

<t>If a scanner modifies both the "message" and "rawMessage" properties, the "rawMessage" modification takes precedence and "message" modifications are ignored.</t>

</section>
<section anchor="conflicting-operations"><name>Conflicting Operations</name>

<t>If a response contains multiple operations targeting the same path or overlapping paths, the MTA applies them in the defined order (set, then add, then delete). The final state reflects all operations applied sequentially. For example, if a response sets "/message/subject" and also deletes "/message/subject", the subject will be deleted (delete operations execute last).</t>

<t>Implementations <bcp14>SHOULD NOT</bcp14> submit responses with conflicting operations targeting the same path, as the resulting behavior, while deterministic, may be confusing.</t>

</section>
<section anchor="no-modification-response"><name>No Modification Response</name>

<t>If a scanner has no modifications to request, it <bcp14>MUST</bcp14> return either:</t>

<t><list style="symbols">
  <t>An empty JSON/CBOR object: <spanx style="verb">{}</spanx></t>
  <t>A response with empty or null modification arrays: <spanx style="verb">{"set": null, "add": null, "delete": null}</spanx></t>
  <t>An HTTP 204 No Content response with no body</t>
</list></t>

<t>In all cases, the MTA proceeds with the action specified in the original request. The scanner chain continues to the next registered scanner unless the current action is terminal.</t>

</section>
<section anchor="size-limits"><name>Size Limits</name>

<t>MTAs <bcp14>MAY</bcp14> impose limits on the size of modification values. If a modification would cause a header or message to exceed configured size limits, the MTA <bcp14>SHOULD</bcp14> reject that specific modification and log the failure.</t>

</section>
<section anchor="modification-errors"><name>Modification Errors</name>

<t>If a modification cannot be applied (for example, the path references a non-existent property for deletion, or the path is not in the permitted updateProperties list), the MTA <bcp14>SHOULD</bcp14>:</t>

<t><list style="numbers" type="1">
  <t>Log the error with sufficient detail for debugging</t>
  <t>Increment modification failure statistics</t>
  <t>Continue processing remaining modifications in the response</t>
</list></t>

<t>The MTA <bcp14>MUST NOT</bcp14> reject the entire response due to a single failed modification unless the failed modification is critical to interpreting the response (such as an invalid action value).</t>

</section>
</section>
<section anchor="example-hook-responses"><name>Example Hook Responses</name>

<section anchor="accept-with-header-addition"><name>Accept with Header Addition</name>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "add": [
    {
      "path": "/message/headers",
      "value": {"name": "X-Spam-Status", "value": "No"},
      "index": 0
    },
    {
      "path": "/message/headers",
      "value": {"name": "X-Spam-Score", "value": "1.2"},
      "index": 1
    }
  ]
}
]]></artwork></figure>

</section>
<section anchor="reject-with-custom-response"><name>Reject with Custom Response</name>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "set": [
    {
      "path": "/action",
      "value": "reject"
    },
    {
      "path": "/response",
      "value": {
        "code": 550,
        "enhancedCode": "5.7.1",
        "message": "Message rejected: virus detected"
      }
    }
  ]
}
]]></artwork></figure>

</section>
<section anchor="modify-subject-and-add-recipient"><name>Modify Subject and Add Recipient</name>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "set": [
    {
      "path": "/message/subject",
      "value": "[EXTERNAL] Original Subject"
    }
  ],
  "add": [
    {
      "path": "/envelope/to",
      "value": {
        "address": "compliance@example.com",
        "parameters": {}
      }
    }
  ]
}
]]></artwork></figure>

</section>
<section anchor="cancel-specific-recipient-delivery"><name>Cancel Specific Recipient Delivery</name>

<t>For outbound processing, to cancel delivery for a specific recipient:</t>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "set": [
    {
      "path": "/envelope/to/1/status",
      "value": "failed-silent"
    }
  ]
}
]]></artwork></figure>

</section>
<section anchor="no-action-response"><name>No Action Response</name>

<t>If a scanner has no changes to request, it returns an empty response body or a response with no action or modifications:</t>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{}
]]></artwork></figure>

<t>The MTA proceeds with the default action specified in the request.</t>

</section>
</section>
</section>
<section anchor="transport"><name>Transport</name>

<t>This section specifies HTTP transport requirements for MTA Hooks communications.</t>

<section anchor="http-version"><name>HTTP Version</name>

<t>Implementations <bcp14>MUST</bcp14> support HTTP/1.1 <xref target="RFC9112"/>. Implementations <bcp14>SHOULD</bcp14> support HTTP/2 <xref target="RFC9113"/> for improved performance through multiplexing. Implementations <bcp14>MAY</bcp14> support HTTP/3 <xref target="RFC9114"/>.</t>

<t>When multiple HTTP versions are available, implementations <bcp14>SHOULD</bcp14> prefer newer versions for their performance benefits while maintaining fallback to HTTP/1.1.</t>

</section>
<section anchor="tls-requirements"><name>TLS Requirements</name>

<t>All MTA Hooks communications <bcp14>MUST</bcp14> use TLS. Implementations <bcp14>MUST</bcp14> support TLS 1.2 <xref target="RFC5246"/> and <bcp14>SHOULD</bcp14> support TLS 1.3 <xref target="RFC8446"/>.</t>

<t>Implementations <bcp14>MUST</bcp14> validate server certificates against trusted certificate authorities. Self-signed certificates <bcp14>SHOULD NOT</bcp14> be accepted in production deployments unless explicitly configured by administrators.</t>

<t>Cipher suite selection <bcp14>SHOULD</bcp14> follow current best practices. Implementations <bcp14>SHOULD</bcp14> disable cipher suites known to be weak or compromised.</t>

</section>
<section anchor="request-methods"><name>Request Methods</name>

<t>The following HTTP methods are used:</t>

<t><list style="symbols">
  <t>GET: Discovery document retrieval and status queries</t>
  <t>POST: Registration requests and hook invocations</t>
  <t>DELETE: Deregistration requests</t>
</list></t>

</section>
<section anchor="content-negotiation"><name>Content Negotiation</name>

<t>For hook requests and responses, the <spanx style="verb">Content-Type</spanx> header <bcp14>MUST</bcp14> be set to "application/json" for JSON serialization or "application/cbor" for CBOR serialization.</t>

<t>The <spanx style="verb">Accept</spanx> header <bcp14>MAY</bcp14> be used during discovery to indicate preferred serialization format. If the scanner cannot provide the requested format, it <bcp14>SHOULD</bcp14> return the discovery document in JSON format.</t>

</section>
<section anchor="error-handling"><name>Error Handling</name>

<section anchor="http-status-codes"><name>HTTP Status Codes</name>

<t>MTAs <bcp14>SHOULD</bcp14> interpret HTTP status codes as follows:</t>

<t><list style="symbols">
  <t>2xx: Request successful. Process response body.</t>
  <t>4xx: Client error. Do not retry; log error and proceed with default action.</t>
  <t>5xx: Server error. May retry according to policy.</t>
</list></t>

</section>
<section anchor="timeout-handling"><name>Timeout Handling</name>

<t>If a scanner does not respond within the configured timeout, the MTA <bcp14>SHOULD</bcp14> proceed with the default action. Timeout handling policy (fail-open vs. fail-closed) is implementation-defined and <bcp14>SHOULD</bcp14> be configurable.</t>

</section>
<section anchor="retry-policy"><name>Retry Policy</name>

<t>For transient errors (5xx status codes, network failures, timeouts), implementations <bcp14>SHOULD</bcp14> implement retry with exponential backoff. A recommended policy is:</t>

<t><list style="symbols">
  <t>Maximum 3 retry attempts</t>
  <t>Initial delay: 100 milliseconds</t>
  <t>Backoff multiplier: 2</t>
  <t>Maximum delay: 5 seconds</t>
  <t>Add random jitter of 0-100 milliseconds</t>
</list></t>

<t>Implementations <bcp14>MAY</bcp14> provide configuration options to adjust retry parameters.</t>

</section>
</section>
<section anchor="connection-management"><name>Connection Management</name>

<t>Implementations <bcp14>SHOULD</bcp14> use connection pooling to reduce latency for repeated requests to the same scanner endpoint. HTTP/2 multiplexing, where available, reduces the need for multiple connections.</t>

<t>Implementations <bcp14>SHOULD</bcp14> respect HTTP keep-alive semantics and connection limits advertised by scanners.</t>

</section>
</section>
<section anchor="implementation-considerations"><name>Implementation Considerations</name>

<section anchor="mta-considerations"><name>MTA Considerations</name>

<section anchor="multiple-scanner-handling-1"><name>Multiple Scanner Handling</name>

<t>When multiple scanners are registered for the same stage, the MTA invokes them sequentially in an implementation-defined order. Each scanner's response affects the request seen by subsequent scanners.</t>

<t>Implementations <bcp14>SHOULD</bcp14> provide configuration options for:</t>

<t><list style="symbols">
  <t>Scanner invocation order (priority-based or explicit ordering)</t>
  <t>Conflict resolution when scanners return conflicting actions</t>
  <t>Short-circuit behavior (whether to skip remaining scanners after certain actions)</t>
</list></t>

</section>
<section anchor="unavailable-scanners"><name>Unavailable Scanners</name>

<t>When a scanner becomes unavailable (timeouts, errors, deregistration), the MTA must determine how to proceed. Common policies include:</t>

<t><list style="symbols">
  <t>Fail-open: Proceed with default action as if scanner approved</t>
  <t>Fail-closed: Reject or defer message processing</t>
</list></t>

<t>The appropriate policy depends on deployment requirements. Security-focused deployments may prefer fail-closed, while availability-focused deployments may prefer fail-open. Implementations <bcp14>SHOULD</bcp14> make this policy configurable.</t>

</section>
<section anchor="performance-considerations"><name>Performance Considerations</name>

<t>Synchronous hook invocation adds latency to mail processing. Implementations <bcp14>SHOULD</bcp14> consider:</t>

<t><list style="symbols">
  <t>Connection pooling and keep-alive for scanner connections</t>
  <t>Parallel invocation of independent scanners where ordering is not required</t>
  <t>Timeout tuning based on scanner response time characteristics</t>
</list></t>

</section>
</section>
<section anchor="scanner-considerations"><name>Scanner Considerations</name>

<section anchor="idempotency"><name>Idempotency</name>

<t>Scanners <bcp14>SHOULD</bcp14> design their processing to be idempotent. Network issues or MTA retries may result in duplicate invocations for the same message. Scanners <bcp14>SHOULD</bcp14> handle duplicate requests gracefully.</t>

</section>
<section anchor="response-time"><name>Response Time</name>

<t>Scanners operate in the critical path of mail delivery. Long response times delay message processing and may cause timeouts. Scanners <bcp14>SHOULD</bcp14>:</t>

<t><list style="symbols">
  <t>Process requests promptly</t>
  <t>Implement internal timeouts shorter than MTA timeouts</t>
  <t>Consider asynchronous processing for expensive operations</t>
  <t>Return default responses when processing cannot complete in time</t>
</list></t>

</section>
<section anchor="stateless-design"><name>Stateless Design</name>

<t>Scanners <bcp14>SHOULD</bcp14> avoid relying on state from previous invocations. Each hook request contains complete context for processing decisions. Stateless design improves reliability and simplifies horizontal scaling.</t>

</section>
</section>
<section anchor="large-message-handling"><name>Large Message Handling</name>

<t>Large messages present challenges for both MTAs and scanners. Implementations <bcp14>SHOULD</bcp14> consider:</t>

<t><list style="symbols">
  <t>Message size limits advertised in discovery documents</t>
  <t>Truncation policies for oversized messages</t>
  <t>Memory management for large message bodies</t>
</list></t>

<t>Streaming or chunked delivery is not currently specified. For very large messages, implementations <bcp14>MAY</bcp14> arrange out-of-band content retrieval, though this is outside the scope of this specification.</t>

</section>
<section anchor="high-availability"><name>High Availability</name>

<section anchor="scanner-high-availability"><name>Scanner High Availability</name>

<t>For production deployments, scanners <bcp14>SHOULD</bcp14> be deployed with redundancy. Approaches include:</t>

<t><list style="symbols">
  <t>Multiple scanner instances behind a load balancer</t>
  <t>Health checking with automatic failover</t>
  <t>Geographic distribution for disaster recovery</t>
</list></t>

<t>The MTA registers a single callback URL; load balancing occurs at the network layer.</t>

</section>
<section anchor="registration-state"><name>Registration State</name>

<t>Registration state resides at the MTA. Scanner instances <bcp14>SHOULD NOT</bcp14> assume persistent local state. If scanner instances share a registration, they <bcp14>MUST</bcp14> coordinate to avoid conflicting operations (such as simultaneous deregistration).</t>

</section>
</section>
</section>
<section anchor="security-considerations"><name>Security Considerations</name>

<section anchor="authentication-and-authorization"><name>Authentication and Authorization</name>

<t>Authentication of registration requests is critical to prevent unauthorized scanners from receiving email content. Implementations <bcp14>MUST</bcp14> require authentication for registration operations.</t>

<t>Recommended authentication approaches:</t>

<t><list style="symbols">
  <t>Bearer tokens: Simple to implement; tokens should be generated with sufficient entropy and rotated periodically.</t>
  <t>Mutual TLS: Provides strong authentication and binds identity to transport security.</t>
  <t>HMAC signatures: Allows authentication without transmitting secrets; requires secure key distribution.</t>
</list></t>

<t>Authorization policies <bcp14>SHOULD</bcp14> restrict which scanners may register and what capabilities they may request. Policies may be based on scanner identity, requested stages, or other criteria.</t>

</section>
<section anchor="transport-security"><name>Transport Security</name>

<t>All MTA Hooks communications <bcp14>MUST</bcp14> use TLS to protect message content and authentication credentials in transit. Implementations <bcp14>MUST</bcp14> validate certificates to prevent man-in-the-middle attacks.</t>

<t>For internal network deployments, administrators may choose to use private certificate authorities. However, disabling certificate validation is <bcp14>NOT RECOMMENDED</bcp14> even for internal communications.</t>

</section>
<section anchor="message-confidentiality"><name>Message Confidentiality</name>

<t>Email messages frequently contain sensitive personal or business information. Scanners necessarily receive access to message content to perform their functions. Deployments <bcp14>SHOULD</bcp14> consider:</t>

<t><list style="symbols">
  <t>Data handling policies for scanner operators</t>
  <t>Logging policies that avoid recording message content</t>
  <t>Data retention limits at scanner endpoints</t>
  <t>Regulatory requirements such as GDPR for personal data processing</t>
</list></t>

</section>
<section anchor="denial-of-service"><name>Denial of Service</name>

<section anchor="registration-attacks"><name>Registration Attacks</name>

<t>Attackers may attempt to exhaust MTA resources through excessive registration requests. Implementations <bcp14>SHOULD</bcp14>:</t>

<t><list style="symbols">
  <t>Rate limit registration attempts per source</t>
  <t>Limit maximum concurrent registrations</t>
  <t>Require authentication before processing registrations</t>
  <t>Validate callback URLs before completing registration</t>
</list></t>

</section>
<section anchor="scanner-resource-exhaustion"><name>Scanner Resource Exhaustion</name>

<t>Malicious or misconfigured MTAs could overwhelm scanners with requests. Scanners <bcp14>SHOULD</bcp14>:</t>

<t><list style="symbols">
  <t>Implement rate limiting</t>
  <t>Set appropriate resource limits</t>
  <t>Monitor for unusual request patterns</t>
</list></t>

</section>
<section anchor="slow-scanner-attacks"><name>Slow Scanner Attacks</name>

<t>Slow responses from scanners can exhaust MTA resources (connection limits, memory). MTAs <bcp14>SHOULD</bcp14>:</t>

<t><list style="symbols">
  <t>Enforce strict timeouts</t>
  <t>Limit concurrent requests to any single scanner</t>
  <t>Implement circuit breaker patterns for repeatedly slow scanners</t>
</list></t>

</section>
</section>
<section anchor="injection-attacks"><name>Injection Attacks</name>

<t>Scanner responses contain modifications applied to message processing. Implementations <bcp14>MUST</bcp14> validate all scanner-provided data:</t>

<t><list style="symbols">
  <t>Header values <bcp14>MUST</bcp14> be validated to prevent header injection</t>
  <t>Recipient addresses <bcp14>MUST</bcp14> be validated against policy</t>
  <t>Body modifications <bcp14>MUST</bcp14> not introduce malformed content</t>
</list></t>

</section>
<section anchor="privacy-considerations"><name>Privacy Considerations</name>

<t>Email processing inherently involves access to personal communications. Implementations <bcp14>SHOULD</bcp14> minimize data exposure:</t>

<t><list style="symbols">
  <t>Scanners <bcp14>SHOULD</bcp14> request only necessary properties</t>
  <t>MTAs <bcp14>SHOULD</bcp14> honor property restrictions from capability negotiation</t>
  <t>Logging <bcp14>SHOULD</bcp14> avoid recording message content or metadata</t>
  <t>Scanner operators <bcp14>SHOULD</bcp14> implement appropriate data protection measures</t>
</list></t>

</section>
</section>
<section anchor="iana-considerations"><name>IANA Considerations</name>

<section anchor="well-known-uri-registration"><name>Well-Known URI Registration</name>

<t>This document registers the following well-known URI per <xref target="RFC8615"/>:</t>

<t>URI suffix: mta-hooks</t>

<t>Change controller: IETF</t>

<t>Specification document: This document</t>

<t>Status: permanent</t>

<t>Related information: N/A</t>

</section>
<section anchor="mta-hooks-serialization-format-registry"><name>MTA Hooks Serialization Format Registry</name>

<t>IANA is requested to create a new registry entitled "MTA Hooks Serialization Formats" with the following initial contents:</t>

<t><list style="symbols">
  <t>Format: json
  <list style="symbols">
      <t>Description: JSON serialization per RFC 8259</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Format: cbor
  <list style="symbols">
      <t>Description: CBOR serialization per RFC 8949</t>
      <t>Reference: This document</t>
    </list></t>
</list></t>

<t>New registrations require Specification Required per <xref target="RFC8126"/>.</t>

</section>
<section anchor="mta-hooks-inbound-action-registry"><name>MTA Hooks Inbound Action Registry</name>

<t>IANA is requested to create a new registry entitled "MTA Hooks Inbound Actions" with the following initial contents:</t>

<t><list style="symbols">
  <t>Action: accept
  <list style="symbols">
      <t>Description: Accept message for delivery</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Action: reject
  <list style="symbols">
      <t>Description: Reject message with error response</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Action: discard
  <list style="symbols">
      <t>Description: Accept but do not deliver message</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Action: quarantine
  <list style="symbols">
      <t>Description: Place message in quarantine</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Action: disconnect
  <list style="symbols">
      <t>Description: Terminate SMTP connection</t>
      <t>Reference: This document</t>
    </list></t>
</list></t>

<t>New registrations require Specification Required per <xref target="RFC8126"/>.</t>

</section>
<section anchor="mta-hooks-outbound-action-registry"><name>MTA Hooks Outbound Action Registry</name>

<t>IANA is requested to create a new registry entitled "MTA Hooks Outbound Actions" with the following initial contents:</t>

<t><list style="symbols">
  <t>Action: continue
  <list style="symbols">
      <t>Description: Proceed with normal delivery processing</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Action: cancel
  <list style="symbols">
      <t>Description: Cancel pending deliveries</t>
      <t>Reference: This document</t>
    </list></t>
</list></t>

<t>New registrations require Specification Required per <xref target="RFC8126"/>.</t>

</section>
<section anchor="mta-hooks-inbound-stage-registry"><name>MTA Hooks Inbound Stage Registry</name>

<t>IANA is requested to create a new registry entitled "MTA Hooks Inbound Stages" with the following initial contents:</t>

<t><list style="symbols">
  <t>Stage: connect
  <list style="symbols">
      <t>Description: Client connection established</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Stage: ehlo
  <list style="symbols">
      <t>Description: EHLO/HELO command received</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Stage: mail
  <list style="symbols">
      <t>Description: MAIL FROM command received</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Stage: rcpt
  <list style="symbols">
      <t>Description: RCPT TO command received</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Stage: data
  <list style="symbols">
      <t>Description: Message content received</t>
      <t>Reference: This document</t>
    </list></t>
</list></t>

<t>New registrations require Specification Required per <xref target="RFC8126"/>.</t>

</section>
<section anchor="mta-hooks-outbound-stage-registry"><name>MTA Hooks Outbound Stage Registry</name>

<t>IANA is requested to create a new registry entitled "MTA Hooks Outbound Stages" with the following initial contents:</t>

<t><list style="symbols">
  <t>Stage: delivery
  <list style="symbols">
      <t>Description: Delivery attempt completed</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Stage: defer
  <list style="symbols">
      <t>Description: Delivery deferred for retry</t>
      <t>Reference: This document</t>
    </list></t>
  <t>Stage: dsn
  <list style="symbols">
      <t>Description: DSN generation pending</t>
      <t>Reference: This document</t>
    </list></t>
</list></t>

<t>New registrations require Specification Required per <xref target="RFC8126"/>.</t>

</section>
<section anchor="mta-hooks-error-code-registry"><name>MTA Hooks Error Code Registry</name>

<t>IANA is requested to create a new registry entitled "MTA Hooks Error Codes" with the initial contents specified in <xref target="error-codes"/>.</t>

<t>New registrations require Specification Required per <xref target="RFC8126"/>.</t>

</section>
</section>


  </middle>

  <back>


<references title='References' anchor="sec-combined-references">

    <references title='Normative References' anchor="sec-normative-references">



<reference anchor="RFC5321">
  <front>
    <title>Simple Mail Transfer Protocol</title>
    <author fullname="J. Klensin" initials="J." surname="Klensin"/>
    <date month="October" year="2008"/>
    <abstract>
      <t>This document is a specification of the basic protocol for Internet electronic mail transport. It consolidates, updates, and clarifies several previous documents, making all or parts of most of them obsolete. It covers the SMTP extension mechanisms and best practices for the contemporary Internet, but does not provide details about particular extensions. Although SMTP was designed as a mail transport and delivery protocol, this specification also contains information that is important to its use as a "mail submission" protocol for "split-UA" (User Agent) mail reading systems and mobile environments. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="5321"/>
  <seriesInfo name="DOI" value="10.17487/RFC5321"/>
</reference>

<reference anchor="RFC5322">
  <front>
    <title>Internet Message Format</title>
    <author fullname="P. Resnick" initials="P." role="editor" surname="Resnick"/>
    <date month="October" year="2008"/>
    <abstract>
      <t>This document specifies the Internet Message Format (IMF), a syntax for text messages that are sent between computer users, within the framework of "electronic mail" messages. This specification is a revision of Request For Comments (RFC) 2822, which itself superseded Request For Comments (RFC) 822, "Standard for the Format of ARPA Internet Text Messages", updating it to reflect current practice and incorporating incremental changes that were specified in other RFCs. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="5322"/>
  <seriesInfo name="DOI" value="10.17487/RFC5322"/>
</reference>

<reference anchor="RFC6901">
  <front>
    <title>JavaScript Object Notation (JSON) Pointer</title>
    <author fullname="P. Bryan" initials="P." role="editor" surname="Bryan"/>
    <author fullname="K. Zyp" initials="K." surname="Zyp"/>
    <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
    <date month="April" year="2013"/>
    <abstract>
      <t>JSON Pointer defines a string syntax for identifying a specific value within a JavaScript Object Notation (JSON) document.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="6901"/>
  <seriesInfo name="DOI" value="10.17487/RFC6901"/>
</reference>

<reference anchor="RFC8259">
  <front>
    <title>The JavaScript Object Notation (JSON) Data Interchange Format</title>
    <author fullname="T. Bray" initials="T." role="editor" surname="Bray"/>
    <date month="December" year="2017"/>
    <abstract>
      <t>JavaScript Object Notation (JSON) is a lightweight, text-based, language-independent data interchange format. It was derived from the ECMAScript Programming Language Standard. JSON defines a small set of formatting rules for the portable representation of structured data.</t>
      <t>This document removes inconsistencies with other specifications of JSON, repairs specification errors, and offers experience-based interoperability guidance.</t>
    </abstract>
  </front>
  <seriesInfo name="STD" value="90"/>
  <seriesInfo name="RFC" value="8259"/>
  <seriesInfo name="DOI" value="10.17487/RFC8259"/>
</reference>

<reference anchor="RFC8620">
  <front>
    <title>The JSON Meta Application Protocol (JMAP)</title>
    <author fullname="N. Jenkins" initials="N." surname="Jenkins"/>
    <author fullname="C. Newman" initials="C." surname="Newman"/>
    <date month="July" year="2019"/>
    <abstract>
      <t>This document specifies a protocol for clients to efficiently query, fetch, and modify JSON-based data objects, with support for push notification of changes and fast resynchronisation and for out-of- band binary data upload/download.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8620"/>
  <seriesInfo name="DOI" value="10.17487/RFC8620"/>
</reference>

<reference anchor="RFC8621">
  <front>
    <title>The JSON Meta Application Protocol (JMAP) for Mail</title>
    <author fullname="N. Jenkins" initials="N." surname="Jenkins"/>
    <author fullname="C. Newman" initials="C." surname="Newman"/>
    <date month="August" year="2019"/>
    <abstract>
      <t>This document specifies a data model for synchronising email data with a server using the JSON Meta Application Protocol (JMAP). Clients can use this to efficiently search, access, organise, and send messages, and to get push notifications for fast resynchronisation when new messages are delivered or a change is made in another client.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8621"/>
  <seriesInfo name="DOI" value="10.17487/RFC8621"/>
</reference>

<reference anchor="RFC8949">
  <front>
    <title>Concise Binary Object Representation (CBOR)</title>
    <author fullname="C. Bormann" initials="C." surname="Bormann"/>
    <author fullname="P. Hoffman" initials="P." surname="Hoffman"/>
    <date month="December" year="2020"/>
    <abstract>
      <t>The Concise Binary Object Representation (CBOR) is a data format whose design goals include the possibility of extremely small code size, fairly small message size, and extensibility without the need for version negotiation. These design goals make it different from earlier binary serializations such as ASN.1 and MessagePack.</t>
      <t>This document obsoletes RFC 7049, providing editorial improvements, new details, and errata fixes while keeping full compatibility with the interchange format of RFC 7049. It does not create a new version of the format.</t>
    </abstract>
  </front>
  <seriesInfo name="STD" value="94"/>
  <seriesInfo name="RFC" value="8949"/>
  <seriesInfo name="DOI" value="10.17487/RFC8949"/>
</reference>

<reference anchor="RFC3339">
  <front>
    <title>Date and Time on the Internet: Timestamps</title>
    <author fullname="G. Klyne" initials="G." surname="Klyne"/>
    <author fullname="C. Newman" initials="C." surname="Newman"/>
    <date month="July" year="2002"/>
    <abstract>
      <t>This document defines a date and time format for use in Internet protocols that is a profile of the ISO 8601 standard for representation of dates and times using the Gregorian calendar.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="3339"/>
  <seriesInfo name="DOI" value="10.17487/RFC3339"/>
</reference>

<reference anchor="RFC2119">
  <front>
    <title>Key words for use in RFCs to Indicate Requirement Levels</title>
    <author fullname="S. Bradner" initials="S." surname="Bradner"/>
    <date month="March" year="1997"/>
    <abstract>
      <t>In many standards track documents several words are used to signify the requirements in the specification. These words are often capitalized. This document defines these words as they should be interpreted in IETF documents. This document specifies an Internet Best Current Practices for the Internet Community, and requests discussion and suggestions for improvements.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="2119"/>
  <seriesInfo name="DOI" value="10.17487/RFC2119"/>
</reference>

<reference anchor="RFC8174">
  <front>
    <title>Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words</title>
    <author fullname="B. Leiba" initials="B." surname="Leiba"/>
    <date month="May" year="2017"/>
    <abstract>
      <t>RFC 2119 specifies common key words that may be used in protocol specifications. This document aims to reduce the ambiguity by clarifying that only UPPERCASE usage of the key words have the defined special meanings.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="14"/>
  <seriesInfo name="RFC" value="8174"/>
  <seriesInfo name="DOI" value="10.17487/RFC8174"/>
</reference>

<reference anchor="RFC9112">
  <front>
    <title>HTTP/1.1</title>
    <author fullname="R. Fielding" initials="R." role="editor" surname="Fielding"/>
    <author fullname="M. Nottingham" initials="M." role="editor" surname="Nottingham"/>
    <author fullname="J. Reschke" initials="J." role="editor" surname="Reschke"/>
    <date month="June" year="2022"/>
    <abstract>
      <t>The Hypertext Transfer Protocol (HTTP) is a stateless application-level protocol for distributed, collaborative, hypertext information systems. This document specifies the HTTP/1.1 message syntax, message parsing, connection management, and related security concerns.</t>
      <t>This document obsoletes portions of RFC 7230.</t>
    </abstract>
  </front>
  <seriesInfo name="STD" value="99"/>
  <seriesInfo name="RFC" value="9112"/>
  <seriesInfo name="DOI" value="10.17487/RFC9112"/>
</reference>

<reference anchor="RFC9113">
  <front>
    <title>HTTP/2</title>
    <author fullname="M. Thomson" initials="M." role="editor" surname="Thomson"/>
    <author fullname="C. Benfield" initials="C." role="editor" surname="Benfield"/>
    <date month="June" year="2022"/>
    <abstract>
      <t>This specification describes an optimized expression of the semantics of the Hypertext Transfer Protocol (HTTP), referred to as HTTP version 2 (HTTP/2). HTTP/2 enables a more efficient use of network resources and a reduced latency by introducing field compression and allowing multiple concurrent exchanges on the same connection.</t>
      <t>This document obsoletes RFCs 7540 and 8740.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9113"/>
  <seriesInfo name="DOI" value="10.17487/RFC9113"/>
</reference>

<reference anchor="RFC9114">
  <front>
    <title>HTTP/3</title>
    <author fullname="M. Bishop" initials="M." role="editor" surname="Bishop"/>
    <date month="June" year="2022"/>
    <abstract>
      <t>The QUIC transport protocol has several features that are desirable in a transport for HTTP, such as stream multiplexing, per-stream flow control, and low-latency connection establishment. This document describes a mapping of HTTP semantics over QUIC. This document also identifies HTTP/2 features that are subsumed by QUIC and describes how HTTP/2 extensions can be ported to HTTP/3.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="9114"/>
  <seriesInfo name="DOI" value="10.17487/RFC9114"/>
</reference>

<reference anchor="RFC5246">
  <front>
    <title>The Transport Layer Security (TLS) Protocol Version 1.2</title>
    <author fullname="T. Dierks" initials="T." surname="Dierks"/>
    <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
    <date month="August" year="2008"/>
    <abstract>
      <t>This document specifies Version 1.2 of the Transport Layer Security (TLS) protocol. The TLS protocol provides communications security over the Internet. The protocol allows client/server applications to communicate in a way that is designed to prevent eavesdropping, tampering, or message forgery. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="5246"/>
  <seriesInfo name="DOI" value="10.17487/RFC5246"/>
</reference>

<reference anchor="RFC8446">
  <front>
    <title>The Transport Layer Security (TLS) Protocol Version 1.3</title>
    <author fullname="E. Rescorla" initials="E." surname="Rescorla"/>
    <date month="August" year="2018"/>
    <abstract>
      <t>This document specifies version 1.3 of the Transport Layer Security (TLS) protocol. TLS allows client/server applications to communicate over the Internet in a way that is designed to prevent eavesdropping, tampering, and message forgery.</t>
      <t>This document updates RFCs 5705 and 6066, and obsoletes RFCs 5077, 5246, and 6961. This document also specifies new requirements for TLS 1.2 implementations.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8446"/>
  <seriesInfo name="DOI" value="10.17487/RFC8446"/>
</reference>

<reference anchor="RFC8615">
  <front>
    <title>Well-Known Uniform Resource Identifiers (URIs)</title>
    <author fullname="M. Nottingham" initials="M." surname="Nottingham"/>
    <date month="May" year="2019"/>
    <abstract>
      <t>This memo defines a path prefix for "well-known locations", "/.well-known/", in selected Uniform Resource Identifier (URI) schemes.</t>
      <t>In doing so, it obsoletes RFC 5785 and updates the URI schemes defined in RFC 7230 to reserve that space. It also updates RFC 7595 to track URI schemes that support well-known URIs in their registry.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="8615"/>
  <seriesInfo name="DOI" value="10.17487/RFC8615"/>
</reference>

<reference anchor="RFC8126">
  <front>
    <title>Guidelines for Writing an IANA Considerations Section in RFCs</title>
    <author fullname="M. Cotton" initials="M." surname="Cotton"/>
    <author fullname="B. Leiba" initials="B." surname="Leiba"/>
    <author fullname="T. Narten" initials="T." surname="Narten"/>
    <date month="June" year="2017"/>
    <abstract>
      <t>Many protocols make use of points of extensibility that use constants to identify various protocol parameters. To ensure that the values in these fields do not have conflicting uses and to promote interoperability, their allocations are often coordinated by a central record keeper. For IETF protocols, that role is filled by the Internet Assigned Numbers Authority (IANA).</t>
      <t>To make assignments in a given registry prudently, guidance describing the conditions under which new values should be assigned, as well as when and how modifications to existing values can be made, is needed. This document defines a framework for the documentation of these guidelines by specification authors, in order to assure that the provided guidance for the IANA Considerations is clear and addresses the various issues that are likely in the operation of a registry.</t>
      <t>This is the third edition of this document; it obsoletes RFC 5226.</t>
    </abstract>
  </front>
  <seriesInfo name="BCP" value="26"/>
  <seriesInfo name="RFC" value="8126"/>
  <seriesInfo name="DOI" value="10.17487/RFC8126"/>
</reference>




    </references>

    <references title='Informative References' anchor="sec-informative-references">



<reference anchor="RFC3461">
  <front>
    <title>Simple Mail Transfer Protocol (SMTP) Service Extension for Delivery Status Notifications (DSNs)</title>
    <author fullname="K. Moore" initials="K." surname="Moore"/>
    <date month="January" year="2003"/>
    <abstract>
      <t>This memo defines an extension to the Simple Mail Transfer Protocol (SMTP) service, which allows an SMTP client to specify (a) that Delivery Status Notifications (DSNs) should be generated under certain conditions, (b) whether such notifications should return the contents of the message, and (c) additional information, to be returned with a DSN, that allows the sender to identify both the recipient(s) for which the DSN was issued, and the transaction in which the original message was sent. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="3461"/>
  <seriesInfo name="DOI" value="10.17487/RFC3461"/>
</reference>

<reference anchor="RFC6376">
  <front>
    <title>DomainKeys Identified Mail (DKIM) Signatures</title>
    <author fullname="D. Crocker" initials="D." role="editor" surname="Crocker"/>
    <author fullname="T. Hansen" initials="T." role="editor" surname="Hansen"/>
    <author fullname="M. Kucherawy" initials="M." role="editor" surname="Kucherawy"/>
    <date month="September" year="2011"/>
    <abstract>
      <t>DomainKeys Identified Mail (DKIM) permits a person, role, or organization that owns the signing domain to claim some responsibility for a message by associating the domain with the message. This can be an author's organization, an operational relay, or one of their agents. DKIM separates the question of the identity of the Signer of the message from the purported author of the message. Assertion of responsibility is validated through a cryptographic signature and by querying the Signer's domain directly to retrieve the appropriate public key. Message transit from author to recipient is through relays that typically make no substantive change to the message content and thus preserve the DKIM signature.</t>
      <t>This memo obsoletes RFC 4871 and RFC 5672. [STANDARDS-TRACK]</t>
    </abstract>
  </front>
  <seriesInfo name="STD" value="76"/>
  <seriesInfo name="RFC" value="6376"/>
  <seriesInfo name="DOI" value="10.17487/RFC6376"/>
</reference>

<reference anchor="RFC7208">
  <front>
    <title>Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, Version 1</title>
    <author fullname="S. Kitterman" initials="S." surname="Kitterman"/>
    <date month="April" year="2014"/>
    <abstract>
      <t>Email on the Internet can be forged in a number of ways. In particular, existing protocols place no restriction on what a sending host can use as the "MAIL FROM" of a message or the domain given on the SMTP HELO/EHLO commands. This document describes version 1 of the Sender Policy Framework (SPF) protocol, whereby ADministrative Management Domains (ADMDs) can explicitly authorize the hosts that are allowed to use their domain names, and a receiving host can check such authorization.</t>
      <t>This document obsoletes RFC 4408.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="7208"/>
  <seriesInfo name="DOI" value="10.17487/RFC7208"/>
</reference>

<reference anchor="RFC7489">
  <front>
    <title>Domain-based Message Authentication, Reporting, and Conformance (DMARC)</title>
    <author fullname="M. Kucherawy" initials="M." role="editor" surname="Kucherawy"/>
    <author fullname="E. Zwicky" initials="E." role="editor" surname="Zwicky"/>
    <date month="March" year="2015"/>
    <abstract>
      <t>Domain-based Message Authentication, Reporting, and Conformance (DMARC) is a scalable mechanism by which a mail-originating organization can express domain-level policies and preferences for message validation, disposition, and reporting, that a mail-receiving organization can use to improve mail handling.</t>
      <t>Originators of Internet Mail need to be able to associate reliable and authenticated domain identifiers with messages, communicate policies about messages that use those identifiers, and report about mail using those identifiers. These abilities have several benefits: Receivers can provide feedback to Domain Owners about the use of their domains; this feedback can provide valuable insight about the management of internal operations and the presence of external domain name abuse.</t>
      <t>DMARC does not produce or encourage elevated delivery privilege of authenticated email. DMARC is a mechanism for policy distribution that enables increasingly strict handling of messages that fail authentication checks, ranging from no action, through altered delivery, up to message rejection.</t>
    </abstract>
  </front>
  <seriesInfo name="RFC" value="7489"/>
  <seriesInfo name="DOI" value="10.17487/RFC7489"/>
</reference>




    </references>

</references>


<?line 1965?>

<section anchor="error-codes"><name>Error Codes</name>

<t>This appendix defines error codes used in MTA Hooks error responses.</t>

<section anchor="error-response-structure"><name>Error Response Structure</name>

<t>Error responses use the following structure:</t>

<figure><sourcecode type="json"><![CDATA[
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error description"
  }
}
]]></sourcecode></figure>

</section>
<section anchor="http-400-bad-request"><name>HTTP 400 Bad Request</name>

<t><list style="symbols">
  <t>INVALID_REQUEST: Malformed JSON/CBOR or missing required fields.</t>
  <t>INVALID_CALLBACK_URL: Callback URL is malformed or uses disallowed scheme.</t>
  <t>CAPABILITY_MISMATCH: Requested capability not supported by MTA.</t>
  <t>INVALID_STAGE: One or more requested stages are not valid.</t>
  <t>INVALID_ACTION: One or more requested actions are not valid.</t>
  <t>INVALID_MODIFICATION: One or more requested modifications are not valid.</t>
  <t>NO_STAGES_REQUESTED: Neither inbound nor outbound stages were specified.</t>
  <t>FILTER_INVALID: Filter configuration is syntactically invalid.</t>
</list></t>

</section>
<section anchor="http-401-unauthorized"><name>HTTP 401 Unauthorized</name>

<t><list style="symbols">
  <t>AUTHENTICATION_REQUIRED: No authentication credentials provided.</t>
  <t>INVALID_CREDENTIALS: Provided credentials are invalid or expired.</t>
</list></t>

</section>
<section anchor="http-403-forbidden"><name>HTTP 403 Forbidden</name>

<t><list style="symbols">
  <t>REGISTRATION_DENIED: Valid credentials but not authorized to register.</t>
  <t>DOMAIN_NOT_ALLOWED: Scanner not authorized for requested domains.</t>
  <t>CALLBACK_NOT_ALLOWED: Callback URL not in allowlist.</t>
</list></t>

</section>
<section anchor="http-404-not-found"><name>HTTP 404 Not Found</name>

<t><list style="symbols">
  <t>REGISTRATION_NOT_FOUND: No registration exists with the specified ID.</t>
</list></t>

</section>
<section anchor="http-409-conflict"><name>HTTP 409 Conflict</name>

<t><list style="symbols">
  <t>ALREADY_REGISTERED: Scanner with same callback URL already registered.</t>
  <t>REGISTRATION_LIMIT_REACHED: Maximum number of registrations exceeded.</t>
</list></t>

</section>
<section anchor="http-422-unprocessable-entity"><name>HTTP 422 Unprocessable Entity</name>

<t><list style="symbols">
  <t>UNSUPPORTED_FILTER: The filter contains conditions that are not supported by this MTA.</t>
  <t>CALLBACK_UNREACHABLE: MTA could not reach callback URL for verification.</t>
  <t>CALLBACK_VERIFICATION_FAILED: Callback URL responded but verification failed.</t>
  <t>TLS_REQUIRED: Callback URL must use HTTPS.</t>
  <t>TLS_CERTIFICATE_INVALID: Callback URL TLS certificate is invalid or untrusted.</t>
</list></t>

</section>
<section anchor="http-429-too-many-requests"><name>HTTP 429 Too Many Requests</name>

<t><list style="symbols">
  <t>RATE_LIMITED: Too many registration attempts; retry after specified time.</t>
</list></t>

</section>
<section anchor="http-500-internal-server-error"><name>HTTP 500 Internal Server Error</name>

<t><list style="symbols">
  <t>INTERNAL_ERROR: Unexpected server error during processing.</t>
</list></t>

</section>
<section anchor="http-503-service-unavailable"><name>HTTP 503 Service Unavailable</name>

<t><list style="symbols">
  <t>REGISTRATION_DISABLED: Registration temporarily disabled by administrator.</t>
</list></t>

</section>
</section>
<section anchor="complete-example-flows"><name>Complete Example Flows</name>

<t>This appendix provides complete request and response examples for common scenarios.</t>

<section anchor="inbound-spam-filtering"><name>Inbound Spam Filtering</name>

<t>This example shows a complete flow for spam filtering during inbound message reception.</t>

<section anchor="discovery-1"><name>Discovery</name>

<figure><artwork><![CDATA[
GET /.well-known/mta-hooks HTTP/1.1
Host: scanner.example.com
Accept: application/json
]]></artwork></figure>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "version": "1.0",
  "endpoints": {
    "registration": "/v1/hooks/register",
    "deregistration": "/v1/hooks/register/{registration_id}"
  },
  "serialization": ["json"],
  "capabilities": {
    "inbound": {
      "stages": ["data"],
      "actions": ["accept", "reject", "quarantine"],
      "fetchProperties": ["/message", "/envelope", "/senderAuth",
                          "/client"],
      "updateProperties": ["/message/headers", "/action", "/response"]
    }
  },
  "limits": {
    "maxMessageSize": 26214400,
    "timeoutMs": 30000
  }
}
]]></artwork></figure>

</section>
<section anchor="registration-1"><name>Registration</name>

<figure><artwork><![CDATA[
POST /v1/hooks/register HTTP/1.1
Host: scanner.example.com
Content-Type: application/json
Authorization: Bearer sk_live_abc123

{
  "name": "SpamFilter Pro",
  "version": "3.0.1",
  "callback": {
    "url": "https://filter.example.net/hooks/spam",
    "timeoutMs": 20000
  },
  "serialization": "json",
  "inbound": {
    "stages": ["data"],
    "properties": ["/message", "/envelope", "/senderAuth", "/client"]
  },
  "metadata": {
    "customer": "acme-corp"
  }
}
]]></artwork></figure>

</section>
<section anchor="verification-callback"><name>Verification Callback</name>

<figure><artwork><![CDATA[
POST /hooks/spam HTTP/1.1
Host: filter.example.net
Content-Type: application/json

{
  "action": "verify",
  "token": "vrf_xyz789"
}
]]></artwork></figure>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "token": "vrf_xyz789"
}
]]></artwork></figure>

</section>
<section anchor="registration-response-1"><name>Registration Response</name>

<figure><artwork><![CDATA[
HTTP/1.1 201 Created
Content-Type: application/json
Location: /v1/hooks/register/reg_spam_001

{
  "registrationId": "reg_spam_001",
  "status": "active",
  "createdAt": "2024-12-21T10:00:00Z",
  "expiresAt": "2025-01-21T10:00:00Z",
  "callback": {
    "url": "https://filter.example.net/hooks/spam",
    "timeoutMs": 20000
  },
  "negotiated": {
    "serialization": "json",
    "inbound": {
      "stages": ["data"],
      "properties": ["/message", "/envelope", "/senderAuth", "/client"]
    }
  },
  "endpoints": {
    "deregistration": "/v1/hooks/register/reg_spam_001",
    "status": "/v1/hooks/register/reg_spam_001/status"
  }
}
]]></artwork></figure>

</section>
<section anchor="hook-invocation-clean-message"><name>Hook Invocation - Clean Message</name>

<figure><artwork><![CDATA[
POST /hooks/spam HTTP/1.1
Host: filter.example.net
Content-Type: application/json
X-MTA-Hooks-Registration: reg_spam_001

{
  "stage": "data",
  "action": "accept",
  "timestamp": "2024-12-21T10:30:00Z",
  "response": {
    "code": 250,
    "enhancedCode": "2.0.0",
    "message": "OK"
  },
  "envelope": {
    "from": {"address": "alice@sender.example", "parameters": {}},
    "to": [{"address": "bob@recipient.example", "parameters": {}}]
  },
  "message": {
    "subject": "Quarterly Report",
    "from": [{"email": "alice@sender.example", "name": "Alice Smith"}],
    "to": [{"email": "bob@recipient.example"}],
    "size": 15360,
    "bodyValues": {
      "1": {
        "value": "Please find attached the Q4 report...",
        "isEncodingProblem": false,
        "isTruncated": false
      }
    }
  },
  "senderAuth": {
    "spf-mail": "pass",
    "dkim": "pass",
    "dmarc": "pass"
  },
  "client": {
    "ip": "192.0.2.50",
    "ehlo": "mail.sender.example"
  }
}
]]></artwork></figure>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "add": [
    {
      "path": "/message/headers",
      "value": {"name": "X-Spam-Status", "value": "No, score=0.5"},
      "index": 0
    }
  ]
}
]]></artwork></figure>

</section>
<section anchor="hook-invocation-spam-detected"><name>Hook Invocation - Spam Detected</name>

<figure><artwork><![CDATA[
POST /hooks/spam HTTP/1.1
Host: filter.example.net
Content-Type: application/json
X-MTA-Hooks-Registration: reg_spam_001

{
  "stage": "data",
  "action": "accept",
  "timestamp": "2024-12-21T10:35:00Z",
  "response": {
    "code": 250,
    "enhancedCode": "2.0.0",
    "message": "OK"
  },
  "envelope": {
    "from": {"address": "promo@spammer.invalid", "parameters": {}},
    "to": [{"address": "bob@recipient.example", "parameters": {}}]
  },
  "message": {
    "subject": "YOU HAVE WON $1,000,000!!!",
    "from": [{"email": "winner@lottery.invalid"}],
    "to": [{"email": "bob@recipient.example"}],
    "size": 8192
  },
  "senderAuth": {
    "spf-mail": "fail",
    "dkim": "none",
    "dmarc": "fail"
  },
  "client": {
    "ip": "203.0.113.99",
    "ehlo": "totally-legit.invalid"
  }
}
]]></artwork></figure>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "set": [
    {
      "path": "/action",
      "value": "reject"
    },
    {
      "path": "/response",
      "value": {
        "code": 550,
        "enhancedCode": "5.7.1",
        "message": "Message rejected due to spam content"
      }
    }
  ]
}
]]></artwork></figure>

</section>
</section>
<section anchor="outbound-delivery-logging"><name>Outbound Delivery Logging</name>

<t>This example shows outbound hook usage for delivery status logging and compliance.</t>

<section anchor="registration-2"><name>Registration</name>

<figure><artwork><![CDATA[
POST /v1/hooks/register HTTP/1.1
Host: mta.example.com
Content-Type: application/json
Authorization: Bearer sk_live_def456

{
  "name": "Delivery Logger",
  "version": "1.0.0",
  "callback": {
    "url": "https://logger.example.net/hooks/delivery",
    "timeoutMs": 5000
  },
  "serialization": "json",
  "outbound": {
    "stages": ["delivery", "dsn"],
    "actions": ["continue"],
    "properties": null
  }
}
]]></artwork></figure>

<figure><artwork><![CDATA[
HTTP/1.1 201 Created
Content-Type: application/json

{
  "registrationId": "reg_logger_001",
  "status": "active",
  "createdAt": "2024-12-21T11:00:00Z",
  "negotiated": {
    "serialization": "json",
    "outbound": {
      "stages": ["delivery", "dsn"],
      "actions": ["continue"],
      "properties": ["/envelope", "/message", "/queue", "/context"]
    }
  },
  "endpoints": {
    "deregistration": "/v1/hooks/register/reg_logger_001",
    "status": "/v1/hooks/register/reg_logger_001/status"
  }
}
]]></artwork></figure>

</section>
<section anchor="hook-invocation-partial-delivery"><name>Hook Invocation - Partial Delivery</name>

<figure><artwork><![CDATA[
POST /hooks/delivery HTTP/1.1
Host: logger.example.net
Content-Type: application/json
X-MTA-Hooks-Registration: reg_logger_001

{
  "stage": "delivery",
  "action": "continue",
  "timestamp": "2024-12-21T12:00:00Z",
  "queue": {
    "id": "q_msg_12345",
    "expiresAt": "2024-12-24T12:00:00Z",
    "attempts": 1
  },
  "envelope": {
    "from": {"address": "notify@example.com", "parameters": {}},
    "to": [
      {
        "address": "user1@active.example",
        "parameters": {},
        "status": "delivered",
        "attempt": 1,
        "lastResponse": {
          "code": 250,
          "enhancedCode": "2.0.0",
          "message": "Delivered"
        }
      },
      {
        "address": "user2@slow.example",
        "parameters": {},
        "status": "deferred",
        "attempt": 1,
        "lastResponse": {
          "code": 451,
          "enhancedCode": "4.7.1",
          "message": "Greylisted, try again"
        },
        "nextAttemptAt": "2024-12-21T12:15:00Z"
      },
      {
        "address": "user3@invalid.example",
        "parameters": {},
        "status": "failed",
        "attempt": 1,
        "lastResponse": {
          "code": 550,
          "enhancedCode": "5.1.1",
          "message": "User unknown"
        }
      }
    ]
  },
  "message": {
    "subject": "System Notification",
    "messageId": "<notify-12345@example.com>",
    "size": 2048
  }
}
]]></artwork></figure>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "action": "continue"
}
]]></artwork></figure>

</section>
</section>
<section anchor="deregistration-1"><name>Deregistration</name>

<figure><artwork><![CDATA[
DELETE /v1/hooks/register/reg_spam_001 HTTP/1.1
Host: scanner.example.com
Authorization: Bearer sk_live_abc123
]]></artwork></figure>

<figure><artwork><![CDATA[
HTTP/1.1 200 OK
Content-Type: application/json

{
  "registrationId": "reg_spam_001",
  "status": "deregistered",
  "deregisteredAt": "2024-12-21T18:00:00Z"
}
]]></artwork></figure>

</section>
</section>
<section anchor="acknowledgments"><name>Acknowledgments</name>

<t>The authors thank the developers and operators of existing mail filtering systems whose experience informed this design.</t>

</section>
<section anchor="changes"><name>Changes</name>

<t>[[This section to be removed by RFC Editor]]</t>

<t><strong>draft-degennaro-mta-hooks-00</strong></t>

<t><list style="symbols">
  <t>Initial version</t>
</list></t>

</section>


  </back>

<!-- ##markdown-source:
H4sIAJ+5SmkAA91963rb1pXofz4Fqpzvq+0haZGSHFvpdEJLcqxWF1eS02bS
HAUiQAk1CXAAUDbr8TzLeZbzZGdd9w0gJStOO2fyfa0pEtiXtdde90uv1+vU
WT1Nd6ON44tR9Loo3lW70SiPXl9cvOm9jKs0iY7jbBq9KYtxWlVZfo0f62Jc
TDc68dVVmd7uRubVTlKM83gGwyVlPKl7SXqd5nlcFr1ZHfdu8JHe5manWlzN
MhisyC+Wc3j48ODiVWcc1+l1US53o6pOOot5An/DWjrFVVVMU/zcyeblblSX
i6oebm6+2Bx23qXL90WZwAh5nZZ5Wvf2cd5OVcd5chlPixxGX6ZVZ57tRj/C
qrtRVZR1mU4q+LSc4YefOp14Ud8U5W4n6nUi+C/LYd7jfrSfRt/x8ulr3thx
vCiL8KeivN6Nzut4+j4u6+govqqio6M9+klh5P1Kv1SwjrTejQZbmy+ivWIy
SdM8Gt2m+SLtRueLrE6jAeyTnh1nNQDm/CYtsyTO6asyvQYA7kZ//oGfKBJY
3fPh882B/L3Ia4Tm2/MRfZHO4Bx3oxmu/9sKV9OH5dBPixLAc1PX82r36VP7
UycvyllcZ7cpgCY6e7W3szUc2I9D+fjsxaZ++3y480I/Phtu2o/mgRfb+sDW
1hZ87GT5JJhla/uZPv5s6+tn8vHr4eZz/bj9HN/s9XoAXYBiPIa1XtxkVQTo
t5ileR1V83ScTbK0srjZjWJB6ytC67mgcZTm8dUUEZsQ/aKM82qSltEIULeu
okcwQPU4qosoSafpNSBlNIOLEF+nOILeiQSmQ3yu8MH0AyJjPI2qtLzN4JG+
XQW+dJslsLA4msGRlXkUT+lxhAC+jZOMlxGeVjTJ8DecQFdbRVdLeOQ2LeNr
/H5xlf0HoEqxqGhvgLuTMgaYLMb1ogQ8qhbzOWA8PnpV1DfRH85PTwAQSbT3
8vQMF5jF0+zvMHmRd+l7xEOacZLlae+6jOGfJBrH8/gqmwIWRjnc0jqjN/rR
xU1qASlzVTxTll8BCiYGWmU6Tuf4Fk+zqP2fAboAgHIZVWM4kDIr8MCm0+I9
rsVCdBzneVoSmOGawinXOgI8DwDNJktAfaAGec37AYBMF2k+hgXAnP5ZxXV0
i1MB8ADrYQjYPQPeHm2fEW2WJck07XS+QlJTFgnAF4bodFpxpkzhTMqUlp1X
2dUUcWZ8E+dZNZOlA60rEZfeZwCqBsJEcCcAh+OZxYBudJuVuFCEAP09L6YZ
IEqKF2iczsyOx8VsPs1i3PKsyAE38PV+9OebDNYh2GXRqVqMb6IYVgUneUyT
2QO9iQElcU2AATXer/minBcVoBU8jYOkFV422Nl0muYIvyxXrE7S+bRYzgge
WT6eLhJB43mZpXUMB/0eQcSXH85ums2A4sE8RTGl7RGWzAHPEdAAG9pW+gFQ
EI7E3qc4SWAZVUo7qFJ3MXBTkhTQGCdecfcRzsGB6z1v4rdcO54Klg+3GEAQ
J1F8C0Po/QAUops4nmYIHNwGgbCMMtwAQoQGRw6EbCouE/8eWpjguyk8BOSp
ukl9cMyR7BlcoRkNufHgM77JYN0AjbKApdpjIYDCaLJsANbVIpvSKS3msAqz
OBl7FucwX0WLmqXAMBP3hpq9yeVUWAFuZxVduxVAmWZXJdxBJJJriMkasoWz
xWPYDCAe3qg0h4tS5Ix5dL2AKMDlxHkBfgRcvBs42jwu6cjlwtI7/WivldhF
yaLkZ68zZDr0HfEOAC5c5nE6WQBCpTESXpizGhdEz3AemPQ9gtIHudw6y4hu
i+ktcQuEPNzbJQg7QFkQDjDTuFwy/cQXgPBVhnYKwcPbRy9kQAne03XH8VG6
SfHseMmGEsFOAPWBDM6ni+tr3EcLaUqQKFepizcugPnQ6GgnSM4VKhXAoAq2
K6RO0MHFZZ9pOeRiiih7FU/xwEpAtzLl1QAEPmSp3BBL5ECkq+p05l8Ag0j1
+wJezGZIexZIKYAUgKCnfMqlAHzSTc41KQsCG8BfUFnWYNjZ6lEMgwMgyxB8
BQCILxHHDeMDUOK1AgkBDrYCeCHUEUWBFvQArnA7EQZxjVwDDhpwm8k37DnL
b4t3QqEYU+HXJELRG44lmRcZXosYb38+ya4XZeqtmdkgwO+rr6KTotYD2ivy
W0QhmBglrTQCwTtCybsCveHt+cVGl/+NTk7p89nBn94enh3s4+fz16OjI/Oh
I0+cvz59e7RvP9k3906Pjw9O9vll+DbyvupsHI9+2GCgb5y+uTg8PRkdbRDm
ewJgXBI2X6WE0CXQaWQuMWgoaTUus6sUJYPo5d6b//t/BtvRx4+/AblyOBi8
+PRJ/ng++Hob/gDoqmCUT5fyJ3K/Tjyfp3GJowARRAEpA8EZ0QFQ7qZ4n0d4
LgDJJz8iZH7ajX53NZ4Ptn8vX+CGvS8VZt6XBLPmN42XGYgtX7VMY6DpfR9A
2l/v6Afvb4W78+Xv/g24dhr1Bs//7fcdQp+LtJxleTEtrpeMM4zViGVwICAH
4REtKhItQDS7voE75B8iyviE1I9apKzHoKaCMjep3+M4SGlA2aN7QveDhC7k
jLW8RXcROPsYpLc8GzPXV9ER8KR+j+rXTVHVfIYennz8KNrPp08oDxJliQ7k
Ohl9WVma3jPYTVwT9ciQAdMdxPvJhLhiagKCCW4RMQxwdFHmlXsfgTwTWcTn
aeZzFoBp88zudRa+68LyZFQiNTR9Y/a+DlUpV4wmi5xnMkLhXSIowLcphTJP
4DPeEIF9gy+sR4Y2LAbQHUW2dJ0CH+JrBivXY4NtID3TDfOW8AcaTygjw+fM
4c67KlEgNFHAAZ6I+1ItwpGtUB0r0ymD5iabu1DsOgypXQ9isRvIwFU8fhe9
PTsy1JXFSFzYobAZa0jZZTSyZ7KS73QZIErjQdqB70mDlCcZk5StnB8bSYum
PlXm9BlzK7cKpqbbBIK6OznKX97UfA0YXZGfELKyQj6O+GagnhCI3YDEfD4h
KwvYGGDuvhHoRG0TpZogU5H8aWU+R1sHRK+zlBFlNGYUgbvrXDKFpGJIlick
NxGuvTdLAwK/mArjhGURsjStAjTPMeqkInshIBjLcYnNhSkqw5CArWYVXZCa
5qTkIAezkhN85JNxr0FUXP0NiByz8P24jiO0sVViINFjkDNH7QimrUhYn8qr
UY0vtJBmK6ryFbcEHcWqjA0Y9K5ebKDgH3dvgYqM00+dJ0/Oa8SxJ086CAgS
6Sv6BrRw0NGRVz4B7Zp/z1kSpTNgaYbg1hv+752tfxlEv/tXfgk/4Fe9Ab3+
Fij/dZ4mdw2zuWqAl6B+pnHurvGKv5LHHwGqpEj4JsDt08c868UeQDqVl2RP
MN8GKiS9OpulG6LUMWeZkE1F+Qoawj596jqCHL7RKyaTKq0dzkZSAwg0G/++
ET2CKemxx/3oFSwm/RCjAgYS03BzuN0bDHvDwcVgZ3drc3dz8983EBuM3TY6
vUVCmr53pWRFhbhF0NT3fEkzRg0krlSz9lQ75SzwDD7iMEe8vUJp/PvfNQOj
0Ev30VkNqTgxq/It94bNHnDQH5C0iEER6aalV1nN3NDQEsMEVCpmMU9WZERo
AQLZ/2oSaYARLa4qXBdu1/BmuG4j4GEZqmYgVrPMY2AXOz+pWE/mJrhhaWr0
EnPaFVydAV8zYkFMGgEAyHJSAalyPlxdYzv3EPKHRggwtgOdScUGnaJrpIQY
FIIlLL/ryCwGTpV7UAIbUdIsGcSpt/pwUzxV2uqlQnRkJQaZknQ8jRkBs9Jy
Yj1/PBSS2Agaht20bPu//uu/Ov/S4//+JVr7nz4GD3b+U76DfwfIg1TBPxMU
tT/rJ/tKb91/v299JYqG/iyCiWtm+d3aaVbMsu6/Fa/A4blylgeB4BW80Hdv
X7HQm2W7MYuFwD91+zt9lp6Cg1/9yoNO/5mZxTv41bPcf/sPQH68Mx93o6+A
nPQ8Wkbuw3+13kPLZl6BcLDxKaCDEzRsiNxE7IOFCJ/cGetZZciad91BOBK6
RNoBGmPT6bT3Lke121relBQypcOxdTTVtGLnaWM6EM2PSAbbjpBb1OxiEJqm
lnZHyge5zCFu7mzk7hRu5uCzsjamVUs2PVdZ6cxmWVzX1zFC/WLbwg7ElIx8
p8LAaJKurA7eX0awXfaN4QNmSIVW19NFvRXTrMJbYdKdu3m5a44ScPy28lWl
UHhu4ekw17NVB2g4tMt4cjkncSKIFSvkQcCxz11LcqdzpgyVQaA8DbmO2pzh
dBbETlJYN6yERESS49D5+ekTioZkpObvXmzDd7L2FiN/BDK5KpIwcpuJmZ1Y
pIbAE7dZzLz/5z02+vZQvP85uknjBKWrTgfFQZatfeceHkHrS1awjOfzqcDn
6d+qIt9g4bLNVfiZo42vihKl0JdZjmJOgnoJcPuE/K6sq1kjjPg/+qAzt+7k
igdRq7caKxSHropkiZZ9OEZdS5qje1xPDsManm3T8G1bC4YXOxrKFSJMsiUR
NIn3QInQjEsCv2CUEyhBym/VJmU3pBIyVXlu01YnqYLMMd60iz0y6ip8UunO
tUaRfZP8jjpi4pqDvzIWDN2W/i1zjYuSbwz68NgQ4Hg2yBuzyr5Bhj6Adw48
BWM5kGYkbHgwlgVRL3yTjbzDx5bC4tGtsxQDSDGbwV759qYfWO9OSCdPb6aF
nSeeoNOTaCHPUaX42sHro1O8zK8P4F8ZjN7mOAr/7TQGHDweHR5Fr85Oj73H
y/G8bn38bO/NRXRhx45YQ0dowhxLtl3zW7PFtM7mU9YMyWDHyMhUjqbBK9W6
J3KbOlELNzHeNLKvERIkXdcyC2/sj0gJo0WJt89zMwk6GKuS4oP5ohUhjPuj
HRfkblFQEKGDPh/uKbYjoQNkNq/NFvkWoTUetpbNxT0DyB+XyRTtQqBuAbEg
ExEp8Nl0QSZ6nG2CRlWdytj6UYkC5R/NKnlqh7VrwGtY1HhWuopEbhh5FJGB
1uWS56jyALmVS16nOZp0CKX3dWQAa72o0AtjDTawAcRvNLIIpS98oHetPSir
DPoU5O8k8IXAa4MZ+TSia3gut89fxTXgLEUEmJ2GPFkM3bgEG87B28BZCOst
DAm1AM8lagOQumd/NJSOiKqSmmPBFktkOx0RQZpuvKYUEloSkYpnjoXeuANc
P59jTa3kjlrMJtUbcDfJVMbww3asT4+NJ81ID41iyYBFzYwspfEfYnLHg7W2
9tusmBohBk9A9+4L16pG+6SY8YTF7VFAXIWcVmpwB9j1VXR24cjAc6BJjhZ4
aENG2OBp+ioJNwjrU6Sq3zQOaAMps7wsxl4Vbb0hDKVtGQLhFwyx0zIE3mcM
/kCeEVDiqmVUpOLeqAaj+yqbesMTEW0hni1DI+UOFtwZ1Xxb6NuutYHgfVFz
tTXKF+ISQGKHFtwu74yuFdkTPV6BxPtYGYpq3q/lvnU6f0bKZBiONeWVaduJ
V/Es1VW2CP2zSAxlGWkeSFjyIA6mp/bQogTxsR8dxNbo89vKyvcxCImEm1ar
gcFhraANOgY5XbBcDaM/3sRoACYDHlHaNC4NjW9RK+TJqSgSu64LJ/it2gX0
ILijxxoVSuA3+lHug+uFaXl9jAEO041O5wTgEf4ePdrg48Ux/2MRlxiIk7NJ
Wa/+N3T14OuFfK984TGH6LAowDAolER0jd0sgB2hGWrFJTpVOK7KGjoP/TAm
FZDVB9OqFOOadh3/pet5onOPHs2BTJZZvZQQLTJqowIBBJqeAOR8DAMAepLe
hUhPO2tbP/xolu+BzMT+wUhHxTWFUAJT9bGDQlhYSiFQOpEqt/A2+/86nQO2
ucvLVynwxox2ObBm1VH0yPGhPgaErSvVTWGRerB0EHECdOMvvXN4vnc+RrrE
GpVrpn0ZPXJ8sDiiZV6k3aaJVfnRYE1hQhR5jGQkmF2wFqn0XnA/vjFT7pGO
WtQqTSBBxlvOL/N9FCJHvNrg+Rpm3RIuc29uLZKFw61tQI3jflRebcJ/TMiP
4841UsqUcaHbHjwpJpEwflRIjNnM/WxbFQUhII2BY1qklkMgrlnxDLX+BAmn
sdQ4AlqyCB+X0AnUDzyWbcQ8N/wIxT1eBqGLDkvsesRSNjxhXjXBNTrE34or
IwQ2z221dKADGPEAlXAWaa3k50vOzeE3SFZvcvjDSbs8fX7SRbSxr1e5z8hF
cUS+zQLnyN9pmUqgKw6HqDr1Qr/HyzF84fvGcOkcdRn46PEBOna+8W2H4wom
ztmwqK36PUnjQrw8wd3VtGDxFakB7fxW5e8knacU3wQa0RgQ3oZ/JGRhFV9x
gcGCXUflhokXGAsMi+Ut+UZJWnB45O2qydxVTBDksUFCR11QYKHBkFASkB4f
DnSSTufcZWOt2kWgnXCYPHrYEV0UfciqQMpRzaIBBaffpMnCKiaud79yZkZJ
cpGTzU48/lYe98yQKmq3ufD90cWOsTIQgCxlb4qMQ3DJ+oiZGZ8+cSBNmo81
AFsMrAaOjjylMZhE2tAx6S7WnZBMomodZ86OuSxn6Xwaj/kisL8cfd4mHQMj
bmuQmHvRKKGsHaDV+PvKR93Ym7gs4TxTRmWUgnEfKNH2UGmGs8fpZ8XtnbN3
DHFEC6VhnQpn0n49oXQXOae7+0lWIoNl+i7RGokTny3m+knGBveEluf8DGQ2
X/qwJXRGkwTIexPXo++eXgyMOO9RDC2FM8N2lA+kOMpjx1qJLE1uOcOQQw7E
6kGYj6G4Y1jr1UKiCzAIcBwjp0QQIvcpfR/4VSp8ny4a0m4jO4v8IQHbRO+F
9EnwVxm/P9YvXMcGPer+6MMlfkcGUxBzklTjtu3Is8YVya5zIJ0JhTwY9ykZ
YSvj7Wl3K+kFjV13EhnbjSfJccgCEdM4yG9avO/Hox/czJ7pkm1Exh8PiuYC
kYPpyJ9xwj/ShBpW6FATwg25bY7Hio4MKEKB4nmbJyuWqB1Ek42nfburpyYd
b8OKCpZp+aG0bDTXMI/vDi6UXMhNajrceGW64KYJH+RZ+W3S6l5wYSuBTGaO
fV3WK/IShEswq86Q99LUOoVENzl+otoLYgLknSZVELKEkiSs6MmT3ehnDl/6
ubPrZyrIIypvtkZYyTPRxqC/uUExQwZTaGizPz39Cqd5e3bEKoiZyyEhOIgH
NWeNP/6Er59b72Vbfkk/+h5dhUwp+e5skNeHr5i6bJ48cS+Jv9o95xd/RrNi
92UajRJ9gnGO6Lv/zBfTKQ5z6mhc/DgxYvw5yiZAA60gxD/T4uPkFklKRXcf
AMzJVwAqDzBmkpa12lf60YF+tmJ4aXTdBd04zUZg0YjyQ5FQTbIPdGigQSZF
2TNLdUZHGfPJk+ahP3miWHojySFujJ2SzABFXe9OgKfoXzVMgt3QdcMh5MTP
PnkC3O4ew6EkNkXZhpmP+0qXHbobH90vL7PkExB9FA1uimlCwaEeBPY8FHsA
EMQOImhVsoTqjmrO/bCZ7+HiqIdpLbkhogwb2YegpirgPaY/bckUWTl/W1pJ
ywIYlC2zPgiUbCFeR02sy5KzAp2cF10FgUVsRmuGUhMXczhXbrc85smTSQra
zhuz3sZ4vugrBFPFXBNWiJZHFoRQDgpDx5884ZTzh05TNZWOEMmPhPI94Exm
8QcRj86zv6e0MifU1SDXcfwhmy1mRues4GHcLLqpvSAMjSGnjcPgbqBVdefw
wELHi7Jkbd15kUZDEwTg7fHqYfbTSbyY1pE8ScHg2XQKlHtMLhWEbCNdgRn9
zwEq/Ey86ufw6H5mZcFEIwZH1xKEy6pSP2Lz85yfdC0wsR7OUhSnTkNtsxls
hM4mWFwtUFaVoZsTYrwgTRDP+zTNQXqEmZ+iAeGppLtusFpQ2dSIPCFzOWX5
a1Ksq+LpMG58+FeR2jCb8hWFSaI40PnYiaINEWA2dlmE6XbwSyPDwNcfqZLA
hosP+PDT28FTEjSfqkEI3qUnfbbR/uzTJheBlz/x7J5QA+//yNJLV0SXn/gp
l7baZQphN1/gcETVaBy12nfFIdUVr1JX/EBdcdr81NWXhY7R29ZY3+IV6DTD
7FwDte81sOMHaE/zGMzAt56qRoSfHWWqbUIz8VM2ldI79bSifzFblD4wSo3o
z7WDsN+L36l1CQwQ+Lj2VQpnqAEFN7qwatEz6X2Vye4agSxPDqBCSvBlIOVu
yFnoT/TKJ0FoZdYrkMpYwrpqwuyyMbIdi4w7p2vcQ/9IdGC4tp/pfY/UPcb7
ntDTuvDxx9nK+gNydinnYkkFawn2+vvsFL7fGW4Pnz/f3Oya3z2OCE8825bf
DH+DL7c2N6lAi0xjJXza1IeeqACSFA7r+kSBtGQ5JP0fM2utzbTTaTUv9KNR
MgONlZaD9lm0LRhTQovtQW0LKzLXAH9BqnGC84MM8XGZJuyy5Vz0BVVfcL16
Ep4ERAqhWJJj18+7N+Zwx5RizAMiwnK2FmVqAsvjVyTEwTgBjA8wjHj9ygsO
d4wlyjtYDyGzD9Zk0bixFTG0BAcTielrrX4YOkBHXAtz5Imane3kDkpCJifX
IyLfptEC4Dm1u/GZnzg7M7u5r1oD7J1dsjLXrsjZINE3p+cXKiIEdQvUoHXh
mH8pclJEplXmE4LqPQwnqA0H6uPrBSBmDytmULEB0pdFwlqqOUaQmSTJpu3F
Ku8aWq0JwGpg4VhMMVvwQdP7e/IH3zccYm9VLDWaDuaIfKOaRVjO7jJzn5kk
PR+k5gAjQwOtcY3MgRXKwmSq0+RE5yVxe+dyBdbad/xltAYWGyHa6DgmGlbt
7cYjBQv8beUGu3sDwq1hNczVsSno75wjRcnF39CvafLAJXQ6I28+mdMBLa1B
pzZRp5Lvm3nBpU0le/X8RsH+ZQsIAutYDyUvPs3/ij6yoaoo/5P/BOTiQDCz
GP4+IDVYHgUZkiQ4WT92mV1jpqJkub5FXzVPGVVLuJQf+MQ+fjwXB9xOfwcd
gFJti3LTQZtL6xilU1d95X+s7WtUXmWAt0C436XLHmPDPM5EqzXJr6L9jC2F
dGMhdCJRc/0b9iAtd1FOQ5IBVOyc0wQ8BysHWTV1+LuVT3ttVqif/p1lbwKi
DLAENndosipuuoGGX9TiUmt4gxvk7d5jin2pOY2w5RoHdhrfODNvN3QYQPkq
s5Ok0pKrYesMYFAh4xMsiq6X4UoUdeAaXW069siNsoUXjX6GgLeCtdm5Vp4i
pl3kPb7HeZPPWSsSartyGwOZi1KZ+RfiZGjd5aPzLznNFlx0vZieOWHl9QTY
BEOOi9kVOQhMwN1Yh67E8TI62e9Gp2dkF0T/3LS4zsZ2KGcppuYdoArGn8Ys
idgQhNkCQDzD0AGMHjakSeeTsjN2A9v97f7AbgF9yS3s3xMnKZGT6YIz9C5H
VJOnD21SG/a3kKbBjOGcGUW8c+IFbByOuqAQsJaJyBGAULKIxtfQDXNAXf6q
+EAuULrafzgevbF2erRuUX0FklE5iUWKIyFVsNZOcntn+TEP534+xfVd3MQ5
fMnhJfCBghowfyDLUeugTIIP8gnuxmGOHvc4eR3fpn/kupbwQ1XM0vZfAO9X
/AKUx32s1j86FnSTxuG3YnALAiCAzWmg47tueL1ctQPTt3ozjVZx5tMYkw08
f9TzWPEbj/H/r/gfIG9qQEHRFP/lkDgtAISjb2Ce5Ht0xZhqhxI+bc9TJ6Ug
JsnilsVLcJEXIsNRSTZ/z1ysuAE439SXFKlnne82KZKSMHWjm0ojb0/O3755
c3p2cbB/+erw6OLgLErLsij7YfWcODHR5gHi6xlS/IDa+0wwesB09IFXAP+A
6x7jeWGgnPAVk9eidsWZPIC/cp4AM0VinUz+iXmKuf19Nk3Q/KUkjejAkw2M
jMEqdnhyIgrJuH9Py8IEQZmnKnGc8rovitWrxogyDer+56+ZKW1FtGQplLCQ
iDgn9ntC/IAz6lgZcI73UX2Dbn60C/tVECTxL6L8sWQp9SA4/IIi4Tn2woav
o4cJl+CeP1caNIAN8SpF8GD64TdCPoLfJeRCA/2qVIVmjQGl5RmMNJlZeFMM
bagtG04K+smVhwNfgGu7bteU0c5C6m/TqkxS5VNgM53XRVXvRjOQYcXg3oe1
ddy0xt0oTIrsjKhasGhHu9HLFEAAu1v+4ebqu3F2mv3h8O3fDwcn2WHV78NS
yXyOui6auEdj0Hkxwle4Nxm1XOP6sG/N66rAWrsVCMj4kCnVK8qys3jZKv6y
0WKwGu4EBitRdGnqzeFOo3JIu6ldLO30W2hK92yejpV8Yx6Y/FwTpWe7dCzP
P9m1NsyrrcbV1slQPLQDMZLZYQoRxnBfp2cKNYviOIGYHj8yt4IHn3yrqTwu
9Dc+dc2T7v3iNzAn1T2uorze+ETPO9tUocauj42IOEQM2NMDNWWBcfK6UMfu
hs/MTXFafQDzRdCAjL8KxvQ2B+RIceyRxhzyPWWHj0U4fjsvNFOQA9DaxGsb
pCvxEZRhvrS80Uv4ztBGFwOFRKHKKpWWIes9JZ0JYLbse4u6O8Tajf9d5Bms
UXLeNaaseJfmtiqAVSg1yIkIh1rFhFY3k9aD/GexKdSrUr1tcad1mspqg9xu
4JITE/ku0Q8AN9MS2ht9WU4un0+24uHVYPwi2U53Js/ir6+ew+fNdDAZxltX
2+MNRYCgYgEJKZq8SXvlEj6cyzfc3GSzsbc+Y8FDsx6tIlzww5bmlDaQ+gON
0jzvMGPJYe/25PicQZrzzp/CLC3Sym659tWKc+EEoEkrNi9yi8/IASlHF8gV
my+i7eFQap+iOEeF2qO90dHRy9HeHy/fnpwdjPZej14eHbRMYLIMr6QAF+/V
iJm06ftM8/3B2eGrw70ROhQuX4E8d7C/Yj9mbIxxIvPLmvEvjs4vtW5l+3i/
rfChaIy0eMLx0Bz9jaFnd4y8d3B2was+uDw8+X50dLjfabONMx4IrZIEX6zF
64clObH5lOPlY/Qg2iO7vsrjFr0CHF8TfHWYhPFSTHtsAJm1xbjvMYI7TxFC
SpEo1L5G53uHh6AjzkGjXMwAk8eOgInle6voZjnHVLZHvcddwEeUCCmD6NHl
Yy1VMgXgPNp93NUNziSYA4tlwxcwzXBnJxS2GT4Ny7MDfn6CYglNFCH7PFiD
q1DrTjEfDk05c06yuHSvowQZMvh9mzvFWqoxnXMdQk/M/Wz2dhApLRka7tNG
iKFjmkcFN63v5VRgCpWuKtVilYaleAGsFV6pVmYTWeLkbwviGByjSSuw5UJo
DSfmzzAY8xUlETrVRbxgZ5PVonSbDX2i+GOmvMmJ5GUhFjnhLC1BrC5etMex
gtjPbQuad4Dtqe27eZhRdY3vxB5TG6duODvsqlo9DnY09VoEZ+4hlq3VKhpT
M8iw6e649wqM2+KzltASZ9g4kF/Lyu2chfW0rDBO+8+bgCzxUOF6W3HwQcu9
MxK2Gfvq+yJaaae+KIwHHi+z9A6NVvkbikOquros6y6F9ajQ8qMtEVbw4fJr
kLhejIdpbzvZmfRQFuuhMNaz0thOIoqsz+82KPX5fgOweMr7ZmWGmQRpukr8
RQ9tVrDsfo66+usrzpaqOuroCiVZlLC1sUF+NNlDNeXPj0V6wJxOZBCHCzWi
bVrCAu8V7OdiksLN4ssdLzyVJwO1duSFtnQ6/t90FdtjKIA/qWRrpG9jUra1
KjOS9JlfkrVVBTzPIt6PViTNq8E6DhxgPo1qdHCg7hukkoj1ifQCDvzAV0m2
9exUmkvei44XNQb0oFROkqDW/nAkdFc6w2rnx6M90zgl7VUgIsJHbAEQB9A9
T9Po40e1UPRIhE00Y+XTJyGZppPE9QK7WY1TdMr4Q7XEwBxlk5RybZlWSnmc
PzEBdSJj0IiLZJVsCVlwvEJ2TYAMZjOpzs4/mSAl1hPai7JJEVF8+35oeZfJ
8fNsioTcF64ObIJ22nbrFcGzeX+fo8lchGqx1VZW87o9iRHnH3fX6QVKH1Ai
WaMPtMjzWL3hIXoAvOeFXD15MoX7d2iszHe/PoOTJNMYlivyTdQGJgzphnR8
bn5qzXmyb9JAcHWn9Q0N8po+Mu6bV/lLUN1SUDdEH2tKQ+fOch6UYGPs77QS
C6k97DRXceiPKepB7efEYYNa/eqXDkTpX5h+PdaKlM3I2ZgViRNcH1eBM+DJ
k5ibDamoJOEfJ4vZVVpSvIs0I7I2Ixw5DPwAmOURliD3F/kgcNVFHU/DIBRC
IfyBt4vFBMZpSFgYEYfbN21v04pw4XNkFsNtQLyFqOr41tfJ3S99HSXx0r6y
tXmPd7Y29SXEKhcJH6oJNKmFYLEhFoz1Ei59XcaWWCxy/c3sYg9xf63lAJ+K
bpybwlQGsWG8QLL0ihOjG5FDFhpIauzzZEXE2iTOmKEgL0xqpQi/GZ3+8S7p
/f8TuRujrD0CGg75bHd7uDt4blxKhhy5WRnmWruCK90l+GKws/18aARWuSUY
hT3cHnhff40AGmwOt7a9rwHV4fvtreFg0xOWmUC1zbjVNt1Oy1zDlomGz71Z
GjQK17JjpWbGI8+7JSdmbkLHzED43gLhbXMa7MIKkRte2fQl5EDKOrBWLxQb
ztI8fR9PsTKuEw5PMhaV3Ygbca/kBnEiK8KwVlu5VMzuPeOWlUIs7oAFButw
CpckRFCzRi6eh4HZPU8qEW+Q5SDa/IV4BtbO963CfqnGyWI69ePk3V6XtmxE
UPAqTm5JiM0L7MeHVEKsnN5OpLZAi6TpgERGlspDawRYrurAzQAsDDWSOISj
5NB7OpgjMVvhi2qpyeLVF7Z/cHRwcRB6wwLDh1NqG/FK3rlDNv4VhOLQBRDm
Jq93AmyKRuSUud79b0GzPfGYfnO/aZJvoAQ7RAn0no+k+Gc7NEztDzx7uAYl
BXk0+lWpotRax9sUCe69mmbXN7VGYoBq9roxEIUlUqe/3oSfFkcxURC4QQF6
ccKLFLKlrsRYOSMKLiQn3rldPJwa3mpmr9xZ2/thyXCagcXRraaQrRd0rFsp
USAQRRGte4C39XRpaq56m3FrnsVY/rt+X5TvIsynz6nx71JqsJhJkgxEJ3Rv
Jnq3gyGxphevgWbEXpNwHqdIlYInTa3cltM3BAVo/srTdxFvFSo0DkbaGV6B
qj7hXpkq1j9qL07FNWnq5TwbUwWdOJrAmkRQfyxmcz1Fe8gCHbU7qGsjgAHS
+aWBhCAuEJsCr/y4QSe9FA59Sur6GMJZebVarmChs9R1DIcWoJ7TEAtTgrCH
KCZ+cWQANoWpsFICV+c1SwsvsAZRhmIpN5khjUoc0mikYpBXjeOZFtcr51hX
ApGysNxOGFI81KkHQPunOAwb4xa0dfELi65oA+TlWeMFDxv7SG3huzBTzEo8
zrmqlEKibKR66Rd7b82nWof77ZXxtYp/tTpGZH0vgL6PjBqqCJz657/04Nse
VZnvubKamTyI0lhlzOEiNrpgm4NI9xFLKGASU1UH+E7VmlMbxO5jEBfh4sJ5
jqDwoMwzJ+mgGcnrVo0N3etWLRUfp23xqP2bp15OQ1Fexzn1e7hCglzDyZRS
rWkPmw3nkc1hDUN03TYWpTv++jL/Xmh5w3XWYpLTKgxhPwGn+kbLW1oBVFDp
fQZir3Z3kvI6Xk0v0yFgDPNxfGlbte1bLwJgTQ58kPFO9j+b9M4TtFYIdWew
5W7xfcmQ9gKEaecH8ofuXcNmnWBUcy/Ym6INEqRUoNNOTNKraAAa/JQQ02ZV
WSNVYv3rsTrUqQqD23bU6kb40wH9JLjeHo3vReLTamzSc1uWJKFIWP8fhjxE
Vz/IHaZE66uVzel2toZDzFxZ0YqjNrHTQCu4r0ZPmm2s7K/hvROHbTRMGhdZ
blabdEwB/bG1MiNIU7i16kKm1HMaQpsSHcJpGvCYTkXhGZOLi977E37yXqJv
Gm+wK4zPgD567xzap6P4SpspUnV1JCeKox5BIVPkgUHlB1jZJhrYr6OMOBKe
UssY1Z1tsIDc1sICjZlt4/z4039qs4IzvS7soj9ruz08QVhqfTU5IS9aRjGZ
XPkRkD9YgQClWkMy2kZprNqME4BdprHQd0vB5iazQMI5G6QFCclnnFess7Vf
ZK+yC+/YnJbsE4UCTMtHOwYpLZonhyuQZDwqWdajQpg0hhyIjqC6gAzDNwmI
9QyZrReMITmlhE3UYcA8hTJCMc5sNB1Or8ACeAQ5p33lp84IKtqc4vK60cHJ
94f70oabdNP985Me5dxTUU/zWqO15vYzppQr8aMMccBKVTbNptHMghLewxbR
On7PnjDNDTeciYZ3vQHNDHF5mENmRbQh1+JtizlUBDVVgfDAgQi1hh9epRo6
reWbp9kkVf3cxXdBf1vWWNQKroAQUeEFFDrKomprgu02EvArYkuJXVtG3ECP
HcCG1x5r+XGSveXtn218kCNY/kM5dCB4atr/2DFHUO6hPzKlCXHvc01w9KTe
1jy9RtIkCklctZ1rv3btVUw/SN8l3bPkZNoCV6ShCTURIGGZXQLv1bS4Okwc
6FIkH9X2k7bF9EgT/Kp6gPgpFUWom9DKLl8wiCvx+dKFabq1sotX8HpLt643
ukCRz9nqy3miprdyKFqbOEi/RAg17MCOEpJ0bdIbTUcUFFOlmlRbtzs5LqMq
iFniDJbto7cV+dowvP5SIp9XeRk4x/Hh8QF3VetI6XLQuGdcmvwfKRyuhoHD
nAnLuXqxwgC72deUpVaYVkVuCmg/EtsFDUEl48XAX9EKeukH6mZsOoy7JFBw
2bTprZzSOJ79xCLGuFzO6+K6jOc32K8tu86pRpAXe9MPwlqstozZJ4bOUQm8
FpAQYrqZrG47Fb9cs1uPmbIDvfGaRZa5cnbyjbOKdZWYSdWHowzgZcUNGA+u
j1uvroWMY7Np516LqWUNuTdJ5w7VBxSumsSfaCPaZ+DAkTiZHoK61MpR4tEc
9DM+wTHvP9OxTwO0bL+Ri1zmd1ncV9EesEVuTSgtEB3mRm64+P1K5maw1GVu
3RX7rBZZrYYIYjGv1TRFXajUJeaeJTx05vTs4ubPUQRfq5EL25FFMZXhsXCz
dBOePJhM0MaZu/fHCaZTpNDe1+tuudmuB1cgWxHSLVv5MtzonnffvHSgR/t/
PDx2ryB3UIWfsOEMNfWGryIu16DdQaRjCDzgdHyUyk/iT3TIRoD48BbQXzTT
i8OgTHtZ/jc5AURGVBK9UwiqgecpUq+CAiYsqjBwyYABty3oYOlRD5dEcMcn
qj7pZBZXTtsp4/HEunXujP6l1/DDFixd5NSBzwEJrq5E5btSiCVhxwPAEg8J
5DnX1iftjJIFVoZ3mpLQGTbQoq9NX7EGfCiOW8X9QfJ4S8ErmeimqGr8lfMK
5u0PHb4xuh3pXEVZt0WiyNMUNJpTfFNf246yLSPclWv5eNC+2iug256mjTro
Xsc+u5zo41ei5rsK0r0tp0TLk1W9/hqxjMzleNGzeq5RF55GTWqrDQlTc2ix
mCbsCb3bGEoxRBRAywlB9PEeth/tooJdYm1/QTElaUy3mJP0Txsd6xQzqhbT
mhtbivEyKOWnUUlPnsRmRIDHivFoLcEQjgmnq7lJEjPsPCmFsOsp2wguppUH
BcoBtJ1jfPMZaXM4s2l13jCEuWe4yhzjH+dnGl9QKm0N1xNvXNpLsmuQCbnD
FJsB8B2xON8gT0j2dJA28408477cJn2zyYIg7eoCvuHZt+ff+HX1LEZz62wS
MPjAQuJg8fVhJoiQlsk096Rl8rRPy+DxumwD4puLM5Tbi5KdomOdqgVUqGYF
K/O6+bIyEZFpDJ079vLFVb6ychh6iPNihgFI58uqTmcRB5jeuRzyxJbLtk0d
np9GW4Nnz3oDTu/sDSN5mhHkrqE5mG/P3KzVdc9krRzDqDZzeyWNRQLbmyo8
EHPw5oZoI7f7C7ITnCVkJNGjtH/d70Yb8OPtoL+18Zihmc1v0jJEPPqSpD4u
LOk8+lLbTYTox+9gHoPkwGKl9EyiljEf4rCqFmkrMu41kyYyepjPqC2p4n1c
qXYpxBJ/PecSR/ecQwoi3X8SIq3MGYLMl6b00+QzDwvunU96wQW0/OXNKyRP
WPwdMZsuJRseWb0LieHXw83n4unCYdFKdo9hrRPjnmMn77JZ27ikF3iqgszS
VkB+6+tnMlxcjttGG53ttQ3GK5iteGn/GF+TAjzrV/D19vMXtILgpOUNsYVJ
kTcRQrDLJd1+21fdKU/BOuFt6iczVS7LXodVyri/AFJh0buQZoxc6QPLFZTm
4nOGVChoj86PnMytRZWa8JpG5pEpIurJr20W/gcJsO35thw5XlNeTIvLYI2P
S63vVt3CaKgYD0B30nQ2qLWKqlYnVWSekAoB1v/RWuD3wf6Hz0/XtxtMiTXK
y3zZpC3g6lyLZsvzWQystSqiSVyqmdVYOIL+62vAHrQz5xLY5PnrYwFbJ8We
qxDGKx2PklfR+NleFT2j0AFKJxW6p1yn6y/2QdrsL12z74j8RzgIV2aYXdy0
d5qX8gKyYr84hQRnc14JvZompia/fObUDolN4T96Ffx/Xm+4SLdKYVDxKsQ8
kXLblqiJLGf30lwpmcXXd4xJuzl4WNlCV4N4cZVS7RxRZHLAsxH/uupmkumF
mmBKCV3jwcOXG1sO5+Y2mpgfq4OYifer/IGTtjTtdKbEXxsTEjk58U023nxU
nVz8Y+b6MxG6kV7pDTCjVGbqhYrXmfxrtudsNzCQrbHdm+Y1+AZuQo2IXslJ
dJOwWaEgG4CbYDH6Qdufao9I7ebt1+7lDqfUIqy1DaqEqUhSk5p2/MhPW2/P
JtKHAf4tafd3RdKvimvcjdxYegm451YVu1JWsesXydKQtI5k9nOTikbgvFdI
wHT6MFk5qJVxOQBTfs3q/lzAb5MK+HEfCUmix8pyf3Ra15i2GE6RN6+/jn2U
0+1tihTlEdCXl/HVeDDccp41efrmcSlXZxKbtH0QloIjgf9btxidLQZgSDW+
/MnLY6oLtyCe6cnhDm2uxLdubTzbv6N1fC4hENTCU/BpThR36xhubj/X+gBS
IhZmPU5TMqhdgI5elsV7PQSBQcuStSqjaEhIDtxVEqNbASp/yXeAxgzUDpjW
sVBuaEvsGL5wU7wEQpRd8uPG72bVNWCEu9Dfm4qIUijUq2aoAHglNXiJ6QYQ
iX7X3P7v3UKHOshF4Q3RvteW985tlV/zcuMsW95DFuEvOgYaPByAmDWOEGiR
giv6F+zT0jaGkN3e4b43Uisg/fNBT5fx0nm5g0u6gFSb+Ol8CgTc3iusrlWl
dKqLetJ7bn9RzPZzBq2T0Z1h4PwROas+SuvfopRNdQgZbhh7PdiMZ30Xr7Pq
AL3wAF9QL4BT4e2YxNMq9Z65KBf5WCqc0K8emjrlPqT/kyVRRFUHL5ASDvuD
TUMN0dCH+ZOYgalf1VTYEu9Hv0mJOF5ize8N8xfmbHbcDmG3bqVPPfXZh0G/
SZnMwp/3dwa47v5wJ1j60MnXxIZZbeRbrVWahElWJvnhcnRwfjnceXb53d7x
5fnr0dbzbf+5l9ymCB5xd2GKvFhCKNYQqvgJ0rRpqvYumzW+Q9uC+TKoj6JM
3Si867m6Ee/+aZzddNHyubttl7WWv38N1MDh71+GD4PmsL3zzOBskCzNc297
czPyijrq4+xn8XBMOTVmmVZm+0tZOZpVBt9aPUXmWMPMnV/cBEajaTnTMAAw
f9r51tWCPELXIn3J1+tkMHnEkcQ0AooFQliSec4IIt07YTL8EjBRhbMNJFuf
B5LtncFakGz3v+4PVoLkAhW2a9Q1MKS2dCDirMJTDsOL9dxHbvMCKXXew0Pn
Jtxf8LNi3g/FAnUVFE9QgcWOW3MDRCPsfbRC1+pL8qldcLOvrsJ+t8yz+2wb
VgRiHfP57c0XHoVv51MV6P890O3uxax2Qj7LzMrQeqXsWorCaZi2IreVTDOz
MCKjdtK2xHyFCrMJKdNHM0nfM5rqDZqdC63eLKPbSEjXDmo9wU6OXmPB2jmB
UvMwMdv1y4rRqqWI66r8MrfFTbhpLt0vu3ehxPOsNGi3Wk5BAhTXfm2q/jiN
d0ZOqgJ197HBg7qSRjt07zE2USVsnx0lyV2TwKP3mcR/jN0WZFPgrtf08a6p
xAhxj9n4ScBgb0r2VFmwPciZgMkPgSHRbXYUPYLX3K7Aj/XgjXmdkysw5JnA
QBI4jRjnS2NASt9rnzUxA+nrmmbiHs2vshFZ9lSLMtkeWryw6oZiXa7I+CqG
sda98OM14YBUR03SDyt9zWj34iNXJ4Kkm2OPDKkkRyOgesJOCGr5BnSQyAWc
ukR4HkoTKbTBczJuGCI85zpiulea1trTXZT8NUHsY8asuJVQsxGrJQ7xQvfT
tYk2+m2l2ZhXSzfg2r/RUR2X16mp1Gu6o0acxuM7oJyYdw6Cc2vMrkg3dXx9
02W/0XCGVxgOvKsVH3g0s1XPn0Ay1pMnSAa4OoMbNs3lAEWj4B5izDyrfnRS
5D3O742n3yDUshzQQsV8Jj+cW0qjn9ny7Sbim/I4sc4HlamhMmNO0XhJwiZn
AI7MQQ/RhT8nBo3Phdhx/urKzWhGh7jlMWFaGpnIHqOM2YWZTY32FLvLRUvM
CtetxKbPrloM1cBA+oRx7PCufYNdnrafLEwP6ynT2yx934/+ZJ8zVINdSGLy
prju1pINfRim5dCCI7OJvrR02SPbpSUUzgkTm83SBN1EVOxjBTi+ct21Bgmp
tBfNS/O8cYUOLiDiyhz3WDhnGNNge/SRsiK00o+ccOa221N355qV+/GuLpUo
ZrNFzjEdTDEqqs1jRRSHhUqmilcjwZHMWqpEeiQMiUjlNWL1vQPiQqCqCzch
75a88XYRkOoFkG8BGzLFRGLUp0L1FUwmuuPQ4OZilZN/QvHbF83EdWFfdfwu
jR4xpelKH4eug/HdKK3H/ccyRhD0yU4T0+ODryW348XFmkvNIjrlZPl9lxAs
Rrrk0G6Tzys6I4DxUVtueYVrepOWPetbbXNmttBrpNBl6oPbPRi8paYDXpv0
SRSTCYRlp1ynQZqdJYQX2izACDNWtqTYVuLY8er3JTOXUyslxxTernhIoBhG
JrJCgz7H8gCFMaRMb7RKkJkDBmA5At+dc94Wi4/8NYxCrb48YZX2jix6/dZN
9FRta3PiFfUlchEDDXOsg1GqftAEhc2/rGsakw4+iepc2GLdtaaT/uuab5pv
G3dV433HkCEGgx3XhtIwF+wE5oI2+4npYJewbMgF3nydHv//J7fYHMi8HjhH
vu4hMqBBt8rHizi3hWz5hG1vPn41o0pzVSZuS79hTpKsAb3s8Kn6SZowNHr5
X3rYwqt3ji02PL/BTn9obQMbtEKpuLfm1NTi9xQ7IK45OMcCFVNOSvoQ91rj
RFhK9g5lv6GlsUy7Bss5iYSuGIsJKP3LtSVanmRj6joxkZwNOSOTPS/6glMG
jOJrQoURCDMWOkLEeJlymaymTinPANEGZkiN7KfMvzBFM0vFFy4sCoegPrr0
rFkzsYabbEKOdRCEtX5PW14MW6N4B3Zo4h032fWNlM3DQbC9B+Et6lK3BUjn
i5xZDeVqUTS/BA7I2XbxUdmiWVtRZtcoUUwJYgrcAe1xiyfWggdhEyYeyt6D
lRfg6Zai8ppnBhsePu3r+fMmYSlZWVFp81vJ2FJK3tgBPD4Aroe1aOwXfW0p
xBB+n1KtKCphAIpg4s82kNkkgYPP7o4pt1jxxI9DIfiuSBad4ry26hKnPVYN
S1egTdJquSWZzy6w45hP8bDzVuO64YRYWL6UGmYxV7WclyANj2sN8qfMD4qP
M3WXXBFgMuEUCS2SwLwImztaDTQQqFCSEk3d9D5NJZ3WVzptNbgKE7dMQqaR
FutQ1PKHRckwBdGCZ3AzL41oJkUWNAjcMLenxMC8b5Q5PeZUOivXSA6wGVP0
f6pyWRPqOEyzT43C4iDfRzNkCQY6kTTVNGE7G47IzBv1fvTENAIyniWwW6wF
wGPN2p4N02gpk6PIJ9OMU4dcmk1Lb0r6bajhWxO4TiqeKUpqcLemgOWkBSDK
2Hpsivvw90xRXkOQ+XqCkMutAKk0inxievNYrBSZljfHQ5lMqeAG6lEu4nJq
sUe8WQowFDHz9kooakmTugq4Rd20UurZ9owg5UILjMFKrpShJNGj1ZwFPTKY
jrCirQN3oL4CPcYpTmhqi+rx3X0kXeleLdcdf79Kb+LbrCg16ViroFEt5S5V
j7yi858snLDik8Kna9YN4KE8Gsbyomn+Nn0es1rL9pJdha8w6Wcj+Gs2r5ek
Wz517Oq70c8fP/2MT9gj425v9Lhafb07wvIevinyMj7SVQlO/jCcDP/mGYwv
YBt3LA7oYFrYH+prsPOcUG8cV241TNNc0gamMpG0Eo8gv/IT3xVgKJxvQ1CC
SfGKzTqFmh9bO9GjMi8wArVMqEqS/T2NjjLUkjsdWDNH+mWzOXYIntL3ahNA
dxP3KnCgq5I1Hb33C7NOlolirQKIfbs08rCg4iGpbS+FW8A5eNpGI1DTVdGK
jOPgqOGWYgFK4qBcurKNEVOXACVz3gAIwKImI7ZQjkcTT3y6EfJGsidXX4mx
e3ov/YCnwOXz2Ho7KaxsSA4J83JWSTUV/so0QF/MEyBmTpYA9qJ6HMKBZYEj
2SabIgm/qoXJjIeLjHHVvISrBWeXD7FQxrhkAcbbtpb5tHXUUZTY05q1nm13
JtVXWsWW0pAClXJMVQanJ2bISUXnM3UdpRi+t0QHp9t+xkyzMqNaqiyFAZoD
WzRU0Mz1SGtmxLl2jvRs0o/9+FTPzynFgsREyq1MGa1H4pr4BQWev7hCybEB
rkZ5Uny+QvklNNlBqyY7aFchxfhO0N1bVDXWefvlLQ/+51lKdqPbrFxw5dKx
E3myQjM/ZlFa4iOJUqLyYNJDfjXYNsSkBpB/PPjLxcHZyejoJ1CRhA1qHKfd
TPfuS/IA44ctwvFF7B9izT9X7tRMBVqXelVE7Biwllvyr1hmZ2y7v6SS/Prj
cmD4dKB90Jpn5uextAMDpCZ2odwhIapPIpANtax+rMKgH4BBkGlIY0LKi6DC
wkPh9cm2x2qX50BpiSmFcoVcp+IcxsxcoJcCzeiikmt/VGt2JIGz1se0RAmb
aSgZ1RTKsD4dk0TJb3/PMYdNbYIYsbaIM4D4+PE3Z6/2XgwGXJh1fWM5emto
39mSLmwgLZYFpguJA4dq2miTClUaP5BvrLEqEDa94bfs8NuUgPpnzyhBe5S4
yiApshv4EsNKM3mKdjfz7sT0xHBXfZXmoIaSLQQVIm0YQuE3Wpkb8FThx4DH
hPMz56w6nREWOVtxWHwSKBXDey0Qcc8JRwbuKTDZGW4/w2p8tiyi/5zC7vn2
NqcPt44tFYnUDeWmfFccuIcmxpJ7Bbv54DG30OA6P+fpdNLjaA1/BEdrvbJx
kdT9iUrrEMrbvn2VSnbpB7x9WU3V9I0+gDUArX+5oPw9Lz+/SqdyjWRiyUlW
xecKzaRzbEONZs2VKJ5kFZnCxs7YVfQuL95TQwTYyfs0fqdlm8pillVYYsgr
AX/MrRTDiAdCWWmzSBiLycKk5n53cLEb7aMTm4h9UowXM9Yx6zLDNG06ar+7
K3r5Ts8vgsbZtto8+teDspjwCvdQ2Q3aEZjXpBA5a7gntk8NMys/kI+9jiIQ
SwZaa4V6rfxZUQoBcN2AvG7QFWzW+qM8Sffh8VVR8sPNIn9axI9lcjs3l5uk
tGxJk04MnNlKyzjNtKFc1bxZTcaOqRE1N+3W41B4Tpacxcy7jMZKlg1iFM1j
zqTSoWkUjXoHqXOvJUKC+SghkHT/QklRFXWZxOg6XgMalDcp/1XaGBHCDT98
2DXoajvb9LXsmM9isUrnNr4hxSNI1exH+4V0fa7L5TekbrMOalqlaGiEzxtx
tB0cTapOyWjH8VLyOIFUFFzDzPj/tGyI9JywYPHEiKRIK1mSjeUU/uuQEulc
0TAreGtu8vS+md7ErfDiokcoBPVAVgLVESgL/TWeFoBzj1EfbY9scan3lV2f
W6WToPGG5pC0T5QI7BFU0SMApHfQXdP5RVR5vJm87OrxSsZovpYTYEvaBy6c
h+2tkN0Vk0mfzG3IxTg8TvafMVIdxx+y2WIWbek5SioC/HQobbJAno2X2EVt
02uSiC1neQZl8Fla7kZDZ1B5cyeyr6DaAgBJQDH8G9pNqA7NZq8xeJP7AVHQ
m+t1NBc/MMePJn9bVAoQK/trrwYTTnSM3edp9JWG20WVugFI86KYCnYDOmKN
Oe3Sw42D59Q+zxJajSpD+62ium3zJbKYK111JSbTkYh4okqshZLQbYQpp2LP
avOzRPMxcXmXpvNePKUyHukMQ2LGzBGcfYrRME5uUSyomImrl5MEYX8mhKrT
2ZdDmeB6Nr+G73XpEtzkkARfTlzREcavEO0kUVP2M7DMd+qU8Ny9GUX9rbjQ
5K/oRwexbUTj1kZl31nl8goYPKUgTcdV7ABoxUGsR10tTamAsfxfHSrzMiuo
k7LUoS6NyGWcg4+5ECc5FXAHxXShsb65BalwNdf7EI9V0jjHblW9cVaOQYQy
DoboEQxBHjr0hL/L5o4h0R4VNbhCYRKt3TLkYz74t7ktfqKBbXLmlhFwpySU
KO3Dj5QMdoV4doOmRI59dYY333SCCXIMbGV57bEk1bAJ7K+UFQThgYF+GFNI
ka4XhBzSm/R9Zh4m/pSMt6i5NBMbWOqh9+FYSZBhmuwUnHZ6Y7uKJIru0lJ7
ApIISUiONI4+H1GYHIamDiK3uPW9XkeQrBS6ZxhsR+FZsvoWbvjGUc5CinC+
zMegZeZYRS0QejkwTAkst370ozRXrEnbfXGd1yb1RmLnUEGkJ0Y4tOQUpXTg
HdNpOvVu4oTiAyjK3LnzQreNiz5TcYYrmWKwoYgg9YKujKkkr1P7vYgxMxgQ
DgZjWz7VKZUn26jqYQIMuyBQOWGjqhmlqOWpquyUpyWtKNNXgSWdiAhCxcuo
WZh0R6RQ1hkJelQ9Cm53smD5Pl1dv9+EvIYrkgZRdgjDMqkbHHVkM7KUwAUB
6OyNvaWm3YBxHbDresLYolY4dLZIWLuBccWSScvV5JrHpu+ekp/GNgjBrNwt
O0DVcg46MApPRjojCR+tojoY9wREagqw4GgL+YWRlk4YiI1zP5wFTiQkFR67
9SJFsDgzkXalWo6/OejFJoqQqZmcccNW7aaAYdZU+oOQp4lUHK5UplMOP87F
jU/BRnOMHy8WfmNuZq9eVLIJSzCLoKjZD1y3zVlrko6zikexKxO0FtMVnsA0
06r9pHUjt2erHPUNxcmmeN+mJq/sCP3sJobXSiL8vVY+1hJ6eCunWBtQwrop
EIT0OJpO2f+96JLO6XhLXXkL71dD3cTjlTT8zOViE4nUqKg9ma6aJpkVJbaQ
VEGXHp26m0M1kcqJnddlGs+k/vT4ZpG/I74gVmyhZ2KSmS6tmZRjMeghb+Cq
qbNQx8SypHAjwPReMQFBhiXP2jOaID+X9rjcrgfvhWrrAJW5lOJBC6xbik6M
qBm8OXLYnKC0ypvNn18xtrWYtprBfRQQgr+rfIACep4AdwMqM0J2zi0OXdHi
OJBpKRkyJtcziFcZBqaAFh6DmB1P8euSK7GbPuJ4Khx5bdoyImsuOAT9u9TU
MU9QJsquFmoAIaMYNaRE5Y+dF2oJV5G6sl5bt3PhN+6KCC2wwnGlIZm2Teky
tVXTHMMU3VO/UbSJ9Km4QL3te+XIvAoYxwgZAzeakZe9Eg89JqNI4BAZeJpw
rW7Ishw1Otwu2ao1LshSQakmGnu5IhjH+JuBoMBBxnlaLKpQBCWtSMWygEVH
H7+qVGAbe7984qwwv2giOfbcXseNEo6A/K1GwNCHjnQYwQXStIxnQ0wkIJVT
jnDHXMfNtmFpMzxrxfWgJjRrv86CvCTNM8fuELwYm/tC90RaOtegw+XVbnRO
BISMfbqYb+RHJ1dR6lLpdXRCKLA6YDFnZlAWNQc+UtNTbtjap6tJ3Wcujs5J
7OdeArAPFBfCxWJqR0Y5BVpHFBV84+vRM8ZhXx+P9mwLAdjLiGM2gyG1tL/p
Lsp1iMdACatvItM5gEZOqTSte8OltqfBE8sRrOIPD4/rsMcqC3LSqha39R4D
ctwONnxT+DmJZnqjg0tMWUOCVah0HYMqt7+h2Bnu1IXoiWZacbsY4OnV+QzH
i2h26DtvdBKhYL+g9nmZJmwO4FgXssitQnTjYfEcI86VwhLbWd6DGXqzLEFh
llrgvNNwbSPwKaH0mIrvEGFZE3t+ELIvqCBbdhtM7ztvXhfvMfC5K24PEuic
Z23PCqQJSETPDvZOj48PTvYP9iPcguSByirbnJEqoqA5IRPQ0QkduD2xkI6w
AWRqUuoxiQrj+W+ZaFN+BspLGIKYVl5FSkeo1h452XSpmZBOf5DwhG2ymSg2
ExCMRNLcd9TZNuFrH5to+bZglaMUmZmCYYxZDwO1rr0Hucu3CMBq8m729KBp
4CqnuWdVqxu2QJbbrxdTnHHpO42V+Xy3/+aMxWKFqLYCMwYFyt7I0VoLDAJt
9Nk4beHMI0ZUuGn0QQmCloGkoL6bGA0pLCZUxaJkCyS7gzHkryLFo5UJrZJ/
CfJniJwECP9lU4sVc+15QgQ8PTgTQ7JTqNxrKEzAa+VL0v/bC37zX/ze3HNH
9HEah5NaEr7oy5NnAqDogKFGDxzHiCooJ6C1lpJc1YlBCsOYuBdKZKCWTWeO
HYFFSgVlm8ZptcrSQDOj1jOYXeBalPTsBPWQ3RV5BjhGiLTIF9XCxqui5ozU
QPvpoQtW92hQhr61OiWJEGbtFMXfijqPGsZl7HqGysnjfuR4wmh/B0gdxtzj
C8MNrV7M+ODhgbW0Y06pyLGyIg9Wxp4Jas47TnOl3Xqme1RscIeVsU9SRrt2
4rFgCIw2tjhnEK8vIagO/VpnwPJZD0Yjy0J6YjlO6NK7nZokBUs9tfpy4vIq
029c9uG3cDJJqc0xNJSAbXsooGHYjr9FeotjYWtpvDOLp0iXU6PZSUsaYGnj
UDZWbuLc0SxHWxrxE7QfTCkh3vABQ/4ClrXSQgmMdoZKNpFLdI1VcA1dQ7sj
LkmyNJbmth3bbC4HXiDHbXtT5Kw4asM5xtjMZHsZiWppOrkz+JWjBLaUFayE
Q66596PjHzAsqukMdImAsolakHiWxgiBitw4o5M2L03053Q67f2RQifenh16
7EMin5xIB1Uj/aSn9zjEOzME11Ch0JZng51Pn+AA8GuS1j/sRrM67lFJuU5n
j/ORpB/UFN2JhwcXr+DSuaq+WcBu5K0HDRnoVN2loOw4p6/OJOvJkTt2o5On
I+OoYlnz3IsfkI6IsndMEEBgZZUj3WK4X5nSXaUcVWESSwqPrjHCeWP96NWG
9Vlb0GXic9Vec+yeoBd2Iwpri6IeGuZAmJ7zZlpiMBDi2PDq+XDnBb1wpgHv
DZDZ0TFQozl6M2jDjv5i+67RTyxk5GqqGumfqDDxxMWVwfCZNs21kPRLjHy5
EwpKl9z/bPiFXQmVasJPws3b6pzceTI6NgcNN8cWT5PbzDcobnLvKaSiycr1
t5QwkWnvPYUtw9Cc5Q3l6TlNSoOH77sFFjWa49viIkFhkX80/gblSb4cAod1
Tz4fgzVBqeV0WkqmGPOwo4Xc96Q4TrqF1nD8dLOSyj+LypxTm98vTmRo2M84
IXp+N1qJ3doeyAraTg+XO09FRscCu82hsS/PU+qUhTKX1Cyh7gL3HRdFvOa4
tjHPQ8ctx23kVnrYP3hUkrOaqw2EsnuO+utRjy+MmP64n4+ZHkfzILcf9r1Q
d9/9TwQfWTOw1k4VZa6+B1/VkasWacpvd6C06B990BxIiuGiX+6Q7ZjuAYfH
6idBfPxI8kSPwhRpmV9iq71ej4ITUQ1xVhV9/MqdTbQNLuaTfZAM80okHI6Q
XYjD1O7Sl38qNy63rZLogf84GWB9vDctbsPyGTSTrdQqKWIbB2dnp2eXe6f7
By2tH177/Rl5sYnFv7AmN4XtbW9uRi/jxJbi7kWHJ9+Pjg73L88O/vT2AOPJ
j43e7SRdk/lJbF9yGlxKoe8MsTc6Ono52vvj5duzI2TB1haGuGb1ebQaIYTQ
6IywIXfSTYpttnrR3ujN6OXh0eHFD5fHh+fHo4u91yZUGW0BjjJc1LYeFUbR
oQ/QWc75xei7g93oNE85Dah0Y7TZpUBRgTgOWSvcl0d7F4enJ6velpi01a8f
n+4fvjrcG60bpFmUwRvq5JR3cK5Hc7AP6qbUt9DSi7mbQyZ7ooIm1rOOetnh
0cXB2aUsbjd6lVH9ND+AEN3gy7ymBAkJdpS1OOgzwAA84wUkSeztxeuDkwvZ
K6318IyWWqzznagpysMfeA+HGjlutMR7iypXSLIuB69kWsRCV7iFWuhVlsA7
ZCo++O7w/OKMFwejH+LSyF7rDYxKCULf8XBSeC5bJXCR+6cgaJxcnpxeXAKa
n/4Zx1EbSvAmsw895qTAAMeKcVsuiDeKd1EkH5zuBWZ9e3vDAgQ17A8Ou7E3
HPLV6dsThrxnFqeUdCdXzdLlw31v/Bcm6JNO9ujsYLT/wyVPc3Dm7pidpBid
5Zq8YdlIkKxbkM/XW+fR4fHhBYw52nuNA2p8d246ifosgSsD+Gc8HAIWirJA
xO+APIa45rcn52/fvDk9g8tyyVi/KzVCFOM1VCiXGrLihpHb59ETCg0RomJp
2wmtffTy6IAbVrMRnuP0MDbJA8iEo1qc2BJnqO8PzgyRuHwFYmwDGySRAZcD
COr1eeTESxwPW0DYa+e9T4GsyIgQcOf68N7B2QVPfGBpgvcedVb22pC61w5b
yVJWmHcoL6KLosBw+KWS64qQFGehQ8fV4SMzfKTVb/ONZg5QALBFUzTeO3Pt
ABc7VJ+jZJEQ92V+xjnEl8Q9sYGgKYVVOQknmg0U1giXCbbU8+UGHDfpyeE5
4sF+kISFmylKdkFKPlkzgY1CPfY0Yk3LDLxC/34orsw1osAEuKmN2c3B0uIU
7IsYc4xyNU5zWEgh0otRG+fxTLiABBFnlb6PQREYY2Bnm6Azg9ya+NpEXwsb
p6vNBVWauQmk+somtnHu7XcHF9HTvjXsPjVW2/v0/2AjUkuOLsk5D86FDjp0
UI658atayczFWsqSvh1IDxOleKY/Snr3s08/us9cZsknaQ3C1futnRTTtDco
VY6z390YC6d7CJ+D29WDJQJ6nbqX/WQSuGPT2uZH08TMlDnoYhMStZo5L03S
enxjy5LQy6ZOVtdJGqc/nBYzbouI8L+Np9Lrx84T1j/xJrIVKJyCDW71hZ9M
FjqDkl2FFk6z+INo4efSH+nZcLANorH2bWBX4TH1UMEeT74k7fvB3W42jQP+
Ag1tvNCcXY1tqt5dos4qzdoEh03rK7ilIuEBCBmXHfze6m9KbYkNZVUWNouS
2k7c1PW82n36lO+6WW+e1tqID+bYaIHXUOHVisSMw/RTiKyrUHVj/hB0c5DK
LEZ9X46eRVVFuI9SPJ6loC2W843wtL93ua5yyZbWhEgbg/Nugu+eJWBMByJi
+dKXiGLW6Mtycvlh+fevn7/Y0IU+mPCtG7QR87Gy/sog2iPjQXLXpEcSyL3b
clvwwyWC8XJzcyDLcwkk9aPbcB9iuNjmN9y5S3CbF9RsKrPpNpVpNFba6W0O
Wh77tW+KOnZT90asvD2fS+y/wB1yCWoLY7wXu2scnXd4d7ygJUjC60mFmQ5t
ag3I19MUkyHEp/QrXdT1jcYCLP7lLUQ3bQvR6NfpIBqt6xLmlQkGQKTfMqbY
LlWN+jh+OzBvhKvi6tuWRlfNIVzivbp3E7YXgHemqHdQl6LVXZtWrV1Z5wh/
j85BXrgJ+zg5o7Sv/1PQjWmws/VMT+PzWi6+AQSmWqUYforBQjcpV8n/0zbG
GMEW+/1fq/di9Gu0BmQSurajo2005bVnDI7Kvfz/vQusYcpHUab/utnfWV1r
rRMUSmrSMlLU9qWy1/8cWrbz34SWYZZd8S3uEMTAvpg4/qnE7IfTt9Hr0fcH
0Z9PT6L/NeiCkID/+81vfrOGrL3PUK34dlpgMOLS7OOXUrDncDnvTRXQHhVS
hbzI0wZVoAfvoArDTdJSBlv9Fy9CulAXNZqne1PA1Nrs9YtQhv95xQG1pCYR
CnHMrS0QaB24xi0qYYatViLje6CMzEWzAZMUJ5lKqCIn6mmpvZaMr8/Sp2d1
/OV0aW64GujSHhDEuhMYi9RcdKeKMKUhWlQEr/1soCbs3FOf1oNoV6jNBHAP
q9zo1q4RyPS6bVW8sRrymit2b/1vnVbH8HmwXjfwFLbPVqgaALwXCO8AYovu
5elbriLGvYBJ7eL05S+qdwXAvY/mZV+5v+71BkRxjAGwVS7v2+y5eTt+mdhi
V/+Fuz0PPTxr7+B8OauuLwfDrW3T63tlA+fh6gbOg8+UZqgn7dKvX3qHKCNY
uq5NM1++/wk9mvfNWswDn9WcGZM6fp2+zJ8Jhl/Wl/m7Ml2ia5naXmqP5gd0
Zx7uDna8hst3w3DrWw0qeCAY2ev5RYC4cwcu7fQHa4D4tqL6+uTBakEn+vd+
Ev/5Eo5ihp59Y2YOdBtmkb/j690jsuJe8t8bii7ujM3t519GUW6SRkdQ9EtI
8jRcXvIu2+69/Hz38Xv8su19nm1ZOa2hZd43a3qX217ZozGiC+DvtVSHpdpN
tFEKQ8jfSdlBJvbSB9Am6BQTDuWg5B4q629csRUhEZZnKcgTjAnq1AeGk1XI
fpRpsRN2PXOx5U7nrz/+9UevDDEX9OHmXOS3xgyNgwQz/v76019/oq53ZTyp
e0l6neZ5XBY948LtbW4+eQJPmIp/t1qGuNP5f9b7XxUYMgEA

-->

</rfc>

