RFC 2156

MIXER (Mime Internet X.400 Enhanced Relay): Mapping between X.400 and RFC 822/MIME

📅 published January 1998, from ietf

MIXER (Mime Internet X.400 Enhanced Relay): Mapping between X.400 and RFC 822/MIME 💌

okay bestie, the title block tea ☕ This is RFC 2156, written by S. Kille of Isode Ltd. 🎀 It's a Standards Track doc from the Network Working Group, dated January 1998 🦋. It obsoletes RFC 987, 1026, 1138, 1148, 1327 and 1495 (so those are retired, bye 👋), and it updates RFC 822 🌈.

Status of this Memo 📜

This document specifies an Internet standards track protocol for the Internet community, and requests discussion and suggestions for improvements. Please refer to the current edition of the "Internet Official Protocol Standards" (STD 1) for the standardization state and status of this protocol. Distribution of this memo is unlimited.

Copyright (C) The Internet Society (1998). All Rights Reserved.

Table of Contents 🧚

1          - Overview ......................................    3
1.1        - X.400 .........................................    3
1.2        - RFC 822 and MIME ..............................    3
1.3        - The need for conversion .......................    4
1.4        - General approach ..............................    4
1.5        - Gatewaying Model ..............................    5
1.6        - Support of X.400 (1984) .......................    8
1.7        - X.400 (1992) ..................................    8
1.8        - MIME ..........................................    8
1.9        - Body Parts ....................................    8
1.10       - Local and Global Scenarios ....................    9
1.11       - Compatibility with previous versions ..........   10
1.12       - Aspects not covered ...........................   10
1.13       - Subsetting ....................................   11
1.14       - Specification Language ........................   11
1.15       - Related Specifications ........................   11
1.16       - Document Structure ............................   12
1.17       - Acknowledgements ..............................   12
2          - Service Elements ..............................   13
2.1        - The Notion of Service Across a Gateway ........   13
2.2        - RFC 822 .......................................   15
2.3        - X.400 .........................................   18
3          - Basic Mappings ................................   27
3.1        - Notation ......................................   27
3.2        - ASCII and IA5 .................................   29
3.3        - Standard Types ................................   29
3.4        - Encoding ASCII in Printable String ............   33
3.5        - RFC 1522 ......................................   34
4          - Addressing and Message IDs ....................   35
4.1        - A textual representation of MTS.ORAddress .....   36
4.2        - Global Address Mapping ........................   43
4.3        - EBNF.822-address <-> MTS.ORAddress ............   46
4.4        - Repeated Mappings .............................   59
4.5        - Directory Names ...............................   62
4.6        - MTS Mappings ..................................   62
4.7        - IPMS Mappings .................................   67
5          - Detailed Mappings .............................   71
5.1        - RFC 822 -> X.400: Detailed Mappings ...........   71
5.2        - Return of Contents ............................   86
5.3        - X.400 -> RFC 822: Detailed Mappings ...........   86
Appendix A - Mappings Specific to SMTP .....................  114
1          - Probes ........................................  114
2          - Long Lines ....................................  114
3          - SMTP Extensions ...............................  114
3.1        - SMTP Extension mapping to X.400 ...............  114
3.2        - X.400 Mapping to SMTP Extensions ..............  115
Appendix B - Mapping with X.400(1984) ......................  116
Appendix C - RFC 822 Extensions for X.400 access ...........  118
Appendix D - Object Identifier Assignment ..................  119
Appendix E - BNF Summary ...................................  120
Appendix F - Text format for MCGAM distribution ............  127
1          - Text Formats ..................................  127
2          - Mechanisms to register and to distribute
             MCGAMs ........................................  127
3          - Syntax Definitions ............................  128
4          - Table Lookups .................................  129
5          - Domain -> OR Address MCGAM format .............  129
6          - OR Address -> Domain MCGAM format .............  129
7          - Domain -> OR Address of Preferred Gateway
             table .........................................  130
8          - OR Addresss -> domain of Preferred Gateway
             table .........................................  130
Appendix G - Conformance ...................................  131
Appendix H - Change History: RFC 987, 1026, 1138, 1148
             ...............................................  133
1          - Introduction ..................................  133
2          - Service Elements ..............................  133
3          - Basic Mappings ................................  133
4          - Addressing ....................................  134
5          - Detailed Mappings .............................  134
6          - Appendices ....................................  134
Appendix I - Change History: RFC 1148 to RFC 1327 ..........  135
1          - General .......................................  135
2          - Basic Mappings ................................  135
3          - Addressing ....................................  135
4          - Detailed Mappings .............................  135
5          - Appendices ....................................  136
Appendix J - Change History: RFC 1327 to this Document
             ...............................................  137
1          - General .......................................  137
2          - Service Elements ..............................  137
3          - Basic Mappings ................................  137
4          - Addressing ....................................  137
5          - Detailed Mappings .............................  138
6          - Appendices ....................................  138
Appendix L - ASN.1 Summary .................................  139
Security Considerations ....................................  141
Author's Address ...........................................  141
References .................................................  141
Full Copyright Statement ...................................  144

1. Overview ✨

1.1. X.400 💌

okay so this doc is mainly about the ITU-T 1988 and 1992 X.400 Series Recommendations, which are also ISO IEC 10021 International Standard 🎀 We just call that whole thing "X.400" for short. If we mean the 1984 Recommendations, the doc says so explicitly, and any mapping for stuff that's in the 1992 version but not the 1988 one gets flagged too 👀 X.400 defines an Interpersonal Messaging System (IPMS), which runs on a store and forward Message Transfer System. This doc is only about the IPMS, not the wider X.400 world, so EDI as defined in X.435 is not part of this tea 🙅‍♀️

1.2. RFC 822 and MIME 🦋

RFC 822 started out as a messaging standard on the DARPA (the US Defense Advanced Research Projects Agency) Internet 🇺🇸 It describes an end to end message format made of a header and an unstructured text body. MIME (Multipurpose Internet Mail Extensions) adds a structured message body format that works with RFC 822 🧩 In this doc, "RFC 822" means the combo of MIME and RFC 822 together, so that's the vibe. RFC 822 and MIME get used with a bunch of different message transfer protocol environments, and the core of MIXER is built to work with any of them ✨

One transfer protocol gets special attention: SMTP. On the Internet and other TCP/IP networks, RFC 822 is used with RFC 821, also known as Simple Mail Transfer Protocol (SMTP) [30], following the host requirements specification [10] 💅 MIXER's use with SMTP is defined in Appendix A, so go check it out 🌸

1.3. The need for conversion 🌈

Lots of people use RFC 822 based protocols for mail, and they're gonna want to talk to people using the IPMS on X.400 systems 💬 It's also needed when communities move from one technology to the other, because you need conversion for the switch to feel smooth 🫶 More than one gateway is expected, and this spec helps them all act consistently. Quick note: "gateway" here means a component that does the mapping between RFC 822 and X.400. That's normal lingo for mail implementors, but transport and network service folks use the word differently 🙃

Consistency between gateways is desirable to provide:

  1. Consistent service to users.
  2. The best service in cases where a message passes through multiple gateways.

1.4. General approach 🧠

There are a few basic principles behind the details of this spec. They're goals, though, and they aren't fully achieved in every part of the spec, so no pressure 😭

  1. The specification should be pragmatic. There should not be a requirement for complex mappings for "Academic" reasons. Complex mappings should not be required to support trivial additional functionality. 💅
  2. Subject to 1), functionality across a gateway should be as high as possible. 🔥
  3. It is always a bad idea to lose information as a result of any transformation. Hence, it is a bad idea for a gateway to discard information in the objects it processes. This includes requested services which cannot be fully mapped. 🙈
  4. Mail gateways operate at a level above the layer on which they perform mappings. This implies that the gateway shall not only be cognisant of the semantics of objects at the gateway level, but also be cognisant of higher level semantics. If meaningful transformation of the objects that the gateway operates on is to occur, then the gateway needs to understand more than the objects themselves. 🧚
  5. Subject to 1), the mapping should be reversible. That is, a double transformation should bring you back to where you started. 🔁

1.5. Gatewaying Model 🌸

1.5.1. X.400 📬✨

okay so X.400 defines the IPMS Abstract Service in X.420 , [11], and it comes with three basic services 💅:

  1. Origination
  2. Reception
  3. Management

bestie, Management is just a local interaction between the user and the IPMS, so it's not relevant to gatewaying 🙈. The first two services are all about originating and receiving two objects:

  1. IPM (Interpersonal Message) 💌. This one has two components: a heading and a body. The body is a sequence of body parts, which can be basic components (like IA5 text or G3 fax) or forwarded Interpersonal Messages. The heading is made of fields with end to end user information, like subject, primary recipients (To:), and importance 🎀.
  2. IPN (Inter Personal Notification) 🔔. This is a notification about receipt of a given IPM at the UA level.

The Origination service also lets you originate a probe 🔍, which is an object that tests whether a given IPM could be correctly received.

The Reception service also lets you receive Delivery Reports (DR) 📦, which show delivery success or failure.

These IPMS Services use the Message Transfer System (MTS) Abstract Service [12] 🚀. The MTS Abstract Service has three basic services:

  1. Submission (used by IPMS Origination)
  2. Delivery (used by IPMS Reception)
  3. Administration (used by IPMS Management)

Administration is a local issue, so it doesn't affect this standard 💖. Submission and delivery mostly relate to the MTS Message (Envelope and Content) 🦋, which carries an IPM or IPN (or other uninterpreted contents). The Envelope includes a message identifier, an originator, and a list of recipients. Submission also includes the probe service, which supports the MTS Probe. Delivery also includes Reports, which show whether a given MTS Message was delivered or not (or for a probe, whether delivery would have happened) 🌈.

The MTS is provided by MTAs, which talk to each other using the MTA (Message Transfer Agent) Service. That service defines the interaction between MTAs, along with the procedures for distributed operation. It handles transfer of MTS Messages, Probes, and Reports 🧚.


1.5.2. RFC 822 💕

RFC 822 is built on the assumption that there's an underlying service, which is called the 822-MTS service 🫶. The 822-MTS service has three basic functions:

  1. Identification of a list of recipients.
  2. Identification of an error return address.
  3. Transfer of an RFC 822 message.

It is possible to achieve 2) within the RFC 822 header 🍓.

This specification will be used most commonly with SMTP as the 822-MTS service ✨. The core MIXER specification is written so that it does not rely on non-basic 822-MTS services. Use of non-basic SMTP services is described in Appendix A. The core of this document is written using SMTP terminology for 822-MTS services 💜.

An RFC 822 message consists of a header, and content which is uninterpreted ASCII text. The header is divided into fields, which are the protocol elements. Most of these fields are analogous to IPM heading fields, although some are analogous to MTS Service Elements or MTA Service Elements 👑.

RFC 822 supports delivery status notifications by use of the NOTARY mechanisms [28] 🔔.


1.5.3. The Gateway 🌸

Given this functional description of the two services, we can now think about the functional nature of a gateway 🧠. It would be elegant to map the SMTP (822-MTS) service onto the MTS Service Elements and RFC 822 onto an IPM, but there isn't a clear match between these services 😭. Another elegant approach would be to treat this document as the definition of an X.400 Access Unit (AU). In this case the abstraction level is too high, and some necessary mapping function gets lost 💀. It's necessary to see that the IPM format definition, the IPMS Service Elements, the MTS Service Elements, and MTA Service Elements on one side are mapped into RFC 822 + SMTP on the other in a slightly tangled manner 🎀. The details of the tangle will be made clear in Chapter 5. Access to the MTA Service Elements is minimised 🦋.

The following basic mappings are defined. When going from RFC 822 to X.400, an RFC 822 message and the associated SMTP information is always mapped into an IPM (MTA, MTS, and IPMS Services), and a Delivery Status Notification is mapped onto a Report 💌. Going from X.400 to RFC 822, an RFC 822 message and the associated SMTP information may be derived from:

  1. An IPN (MTA, MTS, and IPMS services)
  2. An IPM (MTA, MTS, and IPMS services)

A Report (MTA, and MTS Services) is mapped onto a delivery status notification 📦.

Probes (MTA Service) shall be processed by the gateway, as discussed in Chapter 5. MTS Messages containing Content Types other than those defined by the IPMS are not mapped by the gateway, and shall be rejected at the gateway if no other gatewaying procedure is defined 🚫.

This specification is concerned with X.400 IPMS. Future specifications may define mappings for other X.400 content types 🌈.


1.5.4. Repeated Mappings 🔁

The main goal of this specification is to support single mappings, so that X.400 and RFC 822 users can communicate with maximum functionality 💖.

The mappings specified here are designed to work where a message goes back and forth between X.400 and RFC 822 multiple times. This is often essential, especially for distribution lists 📨. However, in general, this will lead to a level of service that is the lowest common denominator (roughly the services offered by RFC 822) 😅.

Some RFC 822 networks may want to use X.400 as an interconnection mechanism (typically for policy reasons), and this is fully supported 🫶.

Where an X.400 message transfers to RFC 822 and then back to X.400, there is no expectation that X.400 services without an equivalent service in standard RFC 822 will be preserved, although this may be possible in some cases 🧚.


1.6. Support of X.400 (1984) 🕰️

The MIXER definition is based on the initial specification of RFC 987 and its addendum RFC 1026, which defined a mapping between X.400(1984) and RFC 822. The core MIXER mapping is defined using the full 1988 version of X.400, not a 1984 compatible subset. New features of X.400(1988) can be used to provide a much cleaner mapping than the one defined in RFC 987. To interwork with 1984 systems, Appendix B shall be followed 💅.

If a message is being transferred to an X.400(1984) system by way of an X.400(1988) MTA, it will give a slightly better service to follow the rules of Appendix B than to downgrade without that knowledge 🎀. Downgrading specifications which supplement those specified in X.400 (X.419) are given in RFC 1328 [22] and RFC 1496 (HARPOON) [5] 🦋.


1.7. X.400 (1992) 🌷

X.400 (1992) features are not used by the core of this mapping, so there isn't an equivalent downgrade problem 💖.


1.8. MIME 💌

MIME format messages are generated by this mapping. As MIME messages are fully RFC 822 compliant, this won't cause problems with systems that aren't MIME capable ✨.


1.9. Body Parts 🧩

MIME and X.400 IPMS can both carry arbitrary body parts. MIME defines a mechanism for adding new body parts, and new body parts are registered with the IANA. X.400 defines a mechanism for adding new body parts, usually referred to as Body Part 15. Extensions are defined by Object Identifiers, so there is no requirement for a central body part registration authority 🔑. The Electronic Messaging Association (EMA) maintains a list of some commonly used body parts. The EMA has specified a mechanism to use the File Transfer Body Part (FTBP) as a more generic means to support message attachments. This approach is gaining widespread commercial support 🚀.

The mapping between X.400 and MIME body parts is defined in the companion MIXER specification, referenced here as RFC 2157 [8]. This document is an update of RFC 1494 [6] 🫶.

Editor's Note: References to 2157 will be resolved as these two documents are expected to progress in parallel 📝.

These two specifications together form the complete MIXER Mapping 👑.


1.10. Local and Global Scenarios 🌍

There are two basic scenarios for X.400/MIME interworking:

Global Scenario

There are two global mail networks (Internet/MIME and X.400), interconnected by multiple gateways. Objects may be transferred over multiple gateways, so it is important that gateways behave in a coherent fashion. MIXER is critical to support this scenario 🌐.

Local Scenario

A gateway is used to connect a closed community to a global mail network (this could be enforced by connectivity or gateway authorisation policy). This is a common commercial scenario. MIXER is useful to support this scenario, as it allows an industry standard provision of service, but this could be supported by something which was MIXER-like 🏢.

A solution for the global scenario will work for the local scenario. However, there are aspects of MIXER which have significant implementation or deployment effort (the global mapping is the major one, but there are other details too) which and are needed to support the global scenario, but are not needed in the local scenario 🧠.

Note that the local scenario may be the driving force for most deployments, and support of the global scenario may be an important secondary goal 💜.

There is also a transition effect. Gateways which are initially deployed in a strict local scenario situation start to find themselves in a global scenario. A common case is ADMD provided gateways, which are targeted strictly at the local scenario. In practice they soon start to operate in the global scenario, because of distribution lists and messages exchanged with X.400 users that are not customers of the ADMD. At this point, users are hurt by the restrictions of a local scenario gateway 😭.

Note that conformance to MIXER applies to an instantiation of a gateway, not just an implementation (although clearly it is critical that the implementation is capable of being operated in a conformant manner) 🎀.

MIXER's conformance target is the global scenario, and the specification of MIXER defines operation in this way 👑.


1.11. Compatibility with previous versions 🦋

The changes between this and older versions of the document are given in Appendices H, I and J. These are RFCs 987, 1026, 1138, 1148 and 1327. This document is a revision of RFC 1327 [21]. As far as possible, changes have been made in a compatible fashion 💖.

1.12. Aspects not covered

Okay so there have been a bunch of times previous versions of this doc got used in ways it was never meant for 🙈 This section is the "lol no, this is NOT what we're doing" spot. Specifically, this spec does not specify:

  • Extensions of RFC 822 to provide access to all X.400 services
  • X.400 user interface definition

These two are super coupled ngl. To map the X.400 services, this spec defines a bunch of extensions to RFC 822, and as a side effect the 822 user gets access to SOME X.400 services 👀. But the goal on the RFC 822 side is to keep current service working, and it's deliberate that not every X.400 service gets exposed. So if you're an X.400 implementor, using MIXER as your interface is a bad vibe, because too many X.400 things can't be reached through it. If you want a text interface, you'd want a spec aimed at X.400 itself, without the RFC 822 restrictions. Some optional, limited extensions in this area have proved useful, and they're defined in Appendix C 💅.

1.13. Subsetting

This proposal maps things in a way that keeps services working for existing RFC 822 communities 🫶 Implementations and specifications that subset this one are non-conformant and strongly discouraged. Don't be that person 💀

1.14. Specification Language

ISO and Internet standards have really clear rules about writing style 📚 This spec maps between ISO/ITU-T protocols and Internet protocols, so it uses ISO terminology for two reasons:

  1. This was done in previous versions.
  2. ISO language can be mechanically converted to Internet language, but not the other way round.

The key ISO rules are:

  1. All mandatory features SHALL clearly be indicated by imperative statements or the word "shall" or "shall not".
  2. Optional features SHALL be indicated by the word "may".
  3. The word "should" and the phrase "may not" SHALL NOT be used.

Sometimes the spec gives guidance on optional features using the word "recommended" or "not recommended". 🎀

To read this doc under Internet rules, swap every "shall" for "must" 🧚

Mappings between Mail-11 and X.400, and between Mail-11 and RFC 822, are described in RFC 2162. That one uses mappings related to the ones defined here [2] 🦋

1.16. Document Structure

This doc has five chapters 🌈

  1. Overview - this chapter.
  2. Service Elements - describes the (end user) services a gateway maps.
  3. Basic mappings - covers some basic notation used in Chapters 3-5, the mappings between character sets, and some fundamental protocol elements.
  4. Addressing - looks at the mapping between X.400 OR names and RFC 822 addresses, which is a fundamental gateway component.
  5. Detailed Mappings - describes the details of all the other mappings.

There are also ten appendices.

WARNING: THE REMAINDER OF THIS SPECIFICATION IS TECHNICALLY DETAILED. IT WILL NOT MAKE SENSE, EXCEPT IN THE CONTEXT OF RFC 822 AND X.400 (1988). DO NOT ATTEMPT TO READ THIS DOCUMENT UNLESS YOU ARE FAMILIAR WITH THESE SPECIFICATIONS. 😭

1.17. Acknowledgements

This work was substantially based on RFC 987 and RFC 1148, which had input from many people, who are credited in those documents 🙏

A bunch of comments on RFC 1148 led to RFC 1327. In particular, there were comments and suggestions from: Maurice Abraham (HP); Harald Alvestrand (Sintef); Peter Cowen (X-Tel); Jim Craigie (JNT); Ella Gardner (MITRE); Christian Huitema (Inria); Erik Huizer (SURFnet); Neil Jones (DEC); Ignacio Martinez (IRIS); Julian Onions (X-Tel); Simon Poole (SWITCH); Clive Roberts (Data General); Pete Vanderbilt (SUN); Alan Young (Concurrent).

RFC 1327 has been widely adopted, and a review team was formed. This comprised: Urs Eppenberger (SWITCH)(Chair); Claudio Allocchio (INFN); Harald Alvestrand (UNINETT); Dave Crocker (Brandenburg); Ned Freed (Innosoft); Erik Huizer (SURFnet); Steve Kille (Isode); Peter Sylvester (GC Tech).

Harald Alvestrand also supplied the tables mapping DSN status codes with X.400 codes. Ned Freed defined parts of the File Transfer Body Part mapping. ✨

Comments and input were also received from: Bengt Ackzell (Generic Systems); Samir Albadine (Transpac); Mark Boyes (DEC); Larry Campbell (Boston Software Works); Jacqui Caren (Cray); Allan Cargille (MCI); Kevin Carrosso (Innosoft); Charlie Combs (OIW); Jim Craigie (Net-Tel); Eamon Doyle (Isocor); Efifion Edem (SITA); Jyrki Heikkinen (ICL); Edward Hibbert (DCL); Jeroun Houttin (Terena); Kevin Jordan (CDS); Paul Kingsnorth (DEC); Carl-Uno Manros (Manros Consulting); Suzan Mendes (Telis); Robert Miles (Softswitch); Roger Mizumorri (Enterprise Solutions Ltd); Keith Moore (University of Tennessee); Ruth Moulton (Net-Tel) Michel Musy (Bull); Kenji Nonaka (NTT): The OIW MHSIG; Tom Oliphant (SWITCH); Julian Onions (NEXOR); Jacob Palme (KTH); Olivier Paridaens (ULB); Mary la Roche (Citicorp); John Setsaas (Maxware); Russell Sharpe (DCL); Patrick Soulier (CCETT); Eftimios Tsigros (Universite Libre de Bruxelles); Sean Turner (IECA); Mark Wahl (Isode); David Wilson (Isode); Bill Wohler (Worldtalk); Alan Young (Isode); Alain Zahm (Telis). 🫶

2. Service Elements ✨

This chapter looks at the services offered across a gateway built according to this spec 🎀 It shows the functionality such a gateway gives for communicating with users in the opposite domain. This chapter only considers service mappings for SINGLE transfers, not repeated mappings through multiple gateways.

2.1. The Notion of Service Across a Gateway

RFC 822 and X.400 both give end users a bunch of services 💖 This chapter describes how far each service can be supported across an X.400 <-> RFC 822 gateway. The cases considered are single transfers across such a gateway, although the problems of multiple crossings are noted where they matter.

2.1.1. Origination of Messages

When a user originates a message, a number of services are available. Some imply actions (like delivery to a recipient), and some are just insertion of known data (like a subject field). For each offered service, this chapter describes how far it's supported for a recipient accessed through a gateway. There are three levels of support:

  • Supported - the corresponding protocol elements map well, so the service can be fully provided ✅
  • Not Supported - the service can't be provided, because there's a complete mismatch 💀
  • Partial Support - the service can be partially fulfilled 🌸

In the first two cases, the service is simply marked "Supported" or "Not Supported". Some explanation MAY be given if there are extra implications or the (non) support isn't intuitive. For partial support, the level is summarised. Where partial support is good, it's described with a phrase like "Supported by use of.....". A common case is where the service is mapped onto a non-standard service on the other side of the gateway, which would've been supported if it were standard. In many cases, that's basically the same as support 🧚 For partial support, the mechanism is given too, so you get a feel for how much support there is. This isn't a replacement for Chapter 5, where the mapping is fully specified.

If a service is described as supported, this implies:

  • Semantic correspondence.
  • No (significant) loss of information.
  • Any actions required by the service element.

Example of a service getting full support: if an RFC 822 originator specifies a Subject: field, that's considered supported, because the X.400 recipient gets a subject indication 🍓

In many cases the required action is just to make the information available to the end user. In other cases, actions MAY imply generating a delivery report.

All RFC 822 services are supported or partially supported for origination. The implications of non-supported X.400 services are described under X.400.

2.1.2. Reception of Messages

For reception, this spec lists the service elements required to support this mapping. It's basically a heads-up on what a recipient might expect to see in a message that was remotely originated 👀

2.2. RFC 822

RFC 822 doesn't explicitly define service elements separate from protocol elements, which is a little plot twist 🙃 Still, all of the RFC 822 header fields, except for trace, can be regarded as corresponding to implicit RFC 822 service elements.

2.2.1. Origination in RFC 822

One mapping mechanism, used in several cases, is to map the RFC 822 header into a heading extension in the IPM (InterPersonal Message). This can be regarded as partial support, because it makes the information available to any X.400 implementations that care about these services. Communities that need significant RFC 822 interworking are RECOMMENDED to require that their X.400 User Agents can display these heading extensions 💅 Here's the list of service elements (headers):

  • Date: - Supported.
  • From: - Supported. For messages that also have a sender field, the mapping is to "Authorising Users Indication", which has subtly different semantics to the general RFC 822 usage of From: 🤔
  • Sender: - Supported.
  • Reply-To: - Supported.
  • To: - Supported.
  • Cc: - Supported.
  • Bcc: - Supported.
  • Message-Id: - Supported.
  • In-Reply-To: - Supported for a single reference. Where multiple references are given, partial support comes from mapping to "Cross Referencing Indication", which gives similar semantics.
  • References: - Supported.
  • Keywords: - Supported by use of a heading extension.
  • Subject: - Supported.
  • Comments: - Supported by use of a heading extension.
  • Encrypted: - Supported by use of a heading extension.
  • Content-Language: - Supported.
  • Resent-* - Supported by use of a heading extension. Addresses in these fields are mapped onto text, so they aren't accessible to the X.400 user as addresses. In principle, fuller support would be possible by mapping onto a forwarded IP Message, but that's not suggested 🙈
  • Other Fields - In particular X-* fields and "illegal" fields in common usage (e.g., "Fruit-of-the-day:") are supported by use of heading extensions 🍓

MIME introduces a number of headings too. Support for those is defined in RFC 2157 🌈

2.2.2. Reception by RFC 822 🎀

okay so this part is about an RFC 822 User Agent receiving a message that started out in an X.400 system and crossed a gateway to get to it 📬✨ the message can come with a bunch of standard services, aka headers, and they're all right here:

  • Date:
  • From:
  • Sender:
  • Reply-To:
  • To:
  • Cc:
  • Bcc:
  • Message-Id:
  • In-Reply-To:
  • References:
  • Subject:
  • Content-Type: (See RFC 2157)
  • Content-Transfer-Encoding: (See RFC 2157)
  • MIME-Version: (See RFC 2157)

there's also a second group of headers that might show up. these get explained in more detail in Chapter 5 (5.3.4, 5.3.6, 5.3.7) 🧚

  • Autoforwarded:
  • Autosubmitted:
  • X400-Content-Identifier:
  • Content-Language:
  • Conversion:
  • Conversion-With-Loss:
  • Delivery-Date:
  • Discarded-X400-IPMS-Extensions:
  • Discarded-X400-MTS-Extensions:
  • DL-Expansion-History:
  • Deferred-Delivery:
  • Expires:
  • Importance:
  • Incomplete-Copy:
  • Latest-Delivery-Time:
  • Message-Type:
  • Original-Encoded-Information-Types:
  • Originator-Return-Address:
  • Priority:
  • Reply-By:
  • Sensitivity:
  • Supersedes:
  • X400-Content-Type:
  • X400-MTS-Identifier:
  • X400-Originator:
  • X400-Received:
  • X400-Recipients:

2.3. X.400 💖

2.3.1. Origination in X.400 💅

okay this is the mapping direction going from X.400 over to RFC 822 🦋 when X.400 has a service that RFC 822 just doesn't support, new RFC 822 headers get defined and registered by publication in this standard. the idea is that co-operating RFC 822 systems can use them too, which is so smart ✨ when those new fields are in use and no system action is implied, the service counts as partially supported. Chapter 5 explains how to map X.400 services onto these new headers, and the gateway handles some of the other elements, since RFC 822 can't provide them on its own 🌸

some service elements are marked N/A (not applicable), and there are five cases, each with its own comment 🙈

N/A (local) these elements only apply to User Agent / Message Transfer Agent interaction, so they can't apply to RFC 822 recipients 💀

N/A (PDAU) these service elements only apply where the recipient is reached through a Physical Delivery Access Unit (PDAU), so the gateway doesn't need to map them 🍓

N/A (reception) these services only apply for reception 📥

N/A (prior) if requested, this service shall be performed prior to the gateway 🧚

N/A (MS) these services only apply to Message Store, which is a local service 🫶

and then there are some service elements that just aren't supported at all 😭 the new security services in particular don't get mapped onto RFC 822. unless it says otherwise, what happens to an unsupported element depends on the criticality marking the user supplied. if the element is marked critical for transfer or delivery, a non-delivery notification gets generated. otherwise the service request gets ignored 🔥

2.3.1.1. Basic Interpersonal Messaging Service 👑

these are the mandatory IPM services, listed in the same order they're given in Section 19.8 of X.400 / ISO/IEC 10021-1 🌈 Section 19.8 has cross references to short definitions of each one, so go peek if you want more.

Access management N/A (local).

Content Type Indication Supported by a new RFC 822 header (X400-Content-Type:).

Converted Indication Supported by a new RFC 822 header (X400-Received:).

Delivery Time Stamp Indication N/A (reception).

IP Message Identification Supported.

Message Identification Supported, by use of a new RFC 822 header (X400-MTS-Identifier). this new header is required, because X.400 has two message-ids and RFC 822 only has one (see IP Message Identification 🫠

Non-delivery Notification Not supported in all cases. Supported where the recipient system supports NOTARY DSNs. in general, all RFC 822 systems will return error reports by use of IP messages. for other service elements, this practical result can be treated as effective support of this service element 🧁

Original Encoded Information Types Indication Supported as a new RFC 822 header (Original-Encoded-Information-Types:).

Submission Time Stamp Indication Supported. ⏰

Typed Body Support is defined in RFC 2157. 📎

User Capabilities Registration N/A (local).

2.3.1.2. IPM Service Optional User Facilities 💖

okay so this bit covers the optional (user selectable) IPM services from Section 19.9 of X.400 / ISO/IEC 10021- 1, and we're going through them in the same order they're listed there 🎀 Section 19.9 has cross references to quick definitions of each one, so you can look them up if you're curious 🧚

N/A (PDAU) means not applicable for this one, bestie 🙈

Additional Physical Rendition N/A (PDAU).

Alternate Recipient Allowed Not supported 💀 RFC 822 has nothing that equals prohibiting alternate recipient assignment. An RFC 822 system is allowed to send an undeliverable message to a local postmaster, no permission needed. A MIXER gateway has two conformant options:

  • Option one: don't gateway a message that asks to prohibit alternate recipients, since there's no way to guarantee that control. This option technically supports the service, but it might cause an unacceptable number of message rejections 😭
  • Option two: gateway the message on the basis that RFC 822 has no alternate recipient service. RFC 1327 only allowed this option.

If option one turns out to work well in practice, it might be the only option in future versions of MIXER ✨

Authorising User's Indication Supported 💅

Auto-forwarded Indication Supported as a new RFC 822 header, Auto-Forwarded: 📨

Basic Physical Rendition N/A (PDAU).

Blind Copy Recipient Indication Supported 🫶

Body Part Encryption Indication Supported with a new RFC 822 header, Original-Encoded-Information-Types:. Ngl though, in most cases it won't be possible to map the body part in question 🥺

Content Confidentiality Not supported.

Content Integrity Not supported.

Conversion Prohibition Supported. The operation is defined in RFC 2157 🌸

Conversion Prohibition in Case of Loss of Information Supported. This one's also defined in RFC 2157 🌸

Counter Collection N/A (PDAU).

Counter Collection with Advice N/A (PDAU).

Cross Referencing Indication Supported ✨

Deferred Delivery N/A (prior). The MTS before the gateway always has to provide this service. A new RFC 822 header, Deferred-Delivery:, carries the information about this service over to the recipient 🦋

Deferred Delivery Cancellation N/A (local).

Delivery Notification Supported. The gateway does this part, but if the end system supports NOTARY, it can be done at the end system instead. Either way, the gateway sends a notification to the originator 🔥

Delivery via Bureaufax Service N/A (PDAU).

Designation of Recipient by Directory Name N/A (local).

Disclosure of Other Recipients Supported with a new RFC 822 header, X400-Recipients:. It's descriptive info for the RFC 822 recipient, and it can't be reverse mapped 👑

DL Expansion History Indication Supported with a new RFC 822 header, DL-Expansion-History: 🧚

DL Expansion Prohibited Here "distribution list" means an MTS supported distribution list, the way X.400 does it. This service doesn't exist in the RFC 822 world, even though RFC 822 does support distribution list functionality. There's no SMTP level control to stop distribution list expansion, so a MIXER gateway has two conformant options:

  • Option one: don't gateway a message that asks for DL expansion prohibition, since that control can't be guaranteed. This option supports the service, but it might cause an unacceptable level of message rejections.
  • Option two: gateway the message on the basis that RFC 822 has no distribution list service. RFC 1327 only allowed this option.

Same deal as before: if option one is shown to work operationally, it may be the only option in future versions of MIXER 💀

Express Mail Service N/A (PDAU).

Expiry Date Indication Supported as a new RFC 822 header, Expires:. Generally speaking, no automatic action can be expected from it ⏳

Explicit Conversion N/A (prior).

Forwarded IP Message Indication Supported ✨

Grade of Delivery Selection Not supported. RFC 822 has no equivalent service 😔

Importance Indication Supported as a new RFC 822 header, Importance: 🔥

Incomplete Copy Indication Supported as a new RFC 822 header, Incomplete-Copy: 🎀

Language Indication Supported as a new RFC 822 header, Content-Language: 🌈

Latest Delivery Designation Not supported. A new RFC 822 header, Latest-Delivery-Time:, is provided. The recipient can use it for general information, but the SMTP infrastructure won't act on it 🙈

Message Flow Confidentiality Not supported.

Message Origin Authentication N/A (reception).

Message Security Labelling Not supported.

Message Sequence Integrity Not supported.

Multi-Destination Delivery Supported. 💜

Multi-part Body Supported 🍓

Non Receipt Notification Request Not supported.

Non Repudiation of Delivery Not supported.

Non Repudiation of Origin N/A (reception).

Non Repudiation of Submission N/A (local).

Obsoleting Indication Supported as a new RFC 822 header, Supersedes: 🦋

Ordinary Mail N/A (PDAU).

Originator Indication Supported 💖

Originator Requested Alternate Recipient Not supported, but it's placed as a comment next to the address, in X400-Recipients: 💅

Physical Delivery Notification by MHS N/A (PDAU).

Physical Delivery Notification by PDS N/A (PDAU).

Physical Forwarding Allowed Supported by putting a comment in a new RFC 822 header, X400-Recipients:. The comment is associated with the recipient in question ✨

Physical Forwarding Prohibited Supported by putting a comment in a new RFC 822 header, X400-Recipients:. The comment is associated with the recipient in question ✨

Prevention of Non-delivery notification Supported where SMTP and NOTARY are available. In other cases it's formally supported, since RFC 822 can't generate delivery notifications. In practice, errors come back as IP Messages, so this service might look like it isn't supported at all (see Non-delivery Notification) 🙈

Primary and Copy Recipients Indication Supported 💜

Probe Supported at the gateway, meaning the gateway services the probe 🧚

Probe Origin Authentication N/A (reception).

Proof of Delivery Not supported.

Proof of Submission N/A (local).

Receipt Notification Request Indication Not supported.

Redirection Disallowed by Originator Redirection here means MTS supported redirection, the X.400 way. This service doesn't exist in the RFC 822 world. RFC 822 redirection (like aliasing) is treated as an informal redirection mechanism, which is outside the scope of this control. Messages go on to RFC 822 whether or not this service is requested. In practice, this control isn't supported 💀

Registered Mail N/A (PDAU).

Registered Mail to Addressee in Person N/A (PDAU).

Reply Request Indication Supported as a comment next to the address 💬

Replying IP Message Indication Supported 🫶

Report Origin Authentication N/A (reception).

Request for Forwarding Address N/A (PDAU).

Requested Delivery Method N/A (local). The request is dealt with at submission time. Any such request gets passed through the gateway as a comment associated with the recipient in question 📝

Return of Content Supported where SMTP and NOTARY are used. In principle, for other situations this is N/A, since non-delivery notifications aren't supported. In practice, most RFC 822 systems return part or all of the content along with the IP Message that signals the error (see Non-delivery Notification) 🌸

Sensitivity Indication Supported as a new RFC 822 header, Sensitivity: 🔒

Special Delivery N/A (PDAU).

Stored Message Deletion N/A (MS).

Stored Message Fetching N/A (MS).

Stored Message Listing N/A (MS).

Stored Message Summary N/A (MS).

Subject Indication Supported 🍓

Undeliverable Mail with Return of Physical Message N/A (PDAU).

Use of Distribution List In principle this only applies to X.400 supported distribution lists (see DL Expansion Prohibited). Theoretically the service is N/A (prior). In practice, because RFC 822 has informal lists, it can be regarded as supported 💅

Auto-Submitted Indication Supported 🦋


2.3.2. Reception by X.400 🎀

2.3.2.1. Standard Mandatory Services

The following standard IPM mandatory user facilities are required for reception of RFC 822 originated mail by an X.400 UA 📬

  • Content Type Indication
  • Delivery Time Stamp Indication
  • IP Message Identification
  • Message Identification
  • Non-delivery Notification
  • Original Encoded Information Types Indication
  • Submission Time Stamp Indication
  • Typed Body

2.3.2.2. Standard Optional Services

The following standard IPM optional user facilities are required for reception of RFC 822 originated mail by an X.400 UA 🌈

  • Authorising User's Indication
  • Blind Copy Recipient Indication
  • Cross Referencing Indication
  • Originator Indication
  • Primary and Copy Recipients Indication
  • Replying IP Message Indication
  • Subject Indication

2.3.2.3. New Services

A new X.400 service, "RFC 822 Header Field", is defined using the extension facilities. It lets any RFC 822 header field be represented, and it can show up in RFC 822 originated messages that get received by an X.400 UA 🧚


3. Basic Mappings ✨

3.1. Notation

X.400 protocols are encoded in a structured way according to ASN.1, whereas RFC 822 is text encoded. To define a detailed mapping, you have to refer to detailed protocol elements in each format, and this section describes the notation that makes that possible 🧠

3.1.1. RFC 822 💖

Structured text is defined using the Extended Backus Naur Form (EBNF) from Section 2 of RFC 822 [16]. In the EBNF definitions used in this specification, the syntax rules from Appendix D of RFC 822 are assumed. When these EBNF tokens get referred to outside an EBNF definition, they're identified by the string 822. added to the front (e.g., 822.addr-spec). Extra syntax rules, to be used throughout this specification, are defined in this chapter 💅

The EBNF gets used in two ways:

  1. To describe components of RFC 822 messages (or of SMTP components). When these new EBNF tokens are referred to outside an EBNF definition, they're identified by the string EBNF. added to the front (e.g., EBNF.importance).
  2. To describe the structure of IA5 or ASCII information that isn't in an RFC 822 message.

For all new EBNF, tokens will either be self delimiting, or be delimited by self delimiting tokens. Comments and LWSP are not used as delimiters, except in the following cases, where LWSP may be inserted according to RFC 822 rules:

  • Around the ":" in all headers
  • EBNF.labelled-integer
  • EBNF.object-identifier
  • EBNF.encoded-info

RFC 822 folding rules are applied to all headers. Comments are never used in these new headers 🫧

This notation is also used in a modified form to refer to NOTARY EBNF [28]. For this EBNF, the keyword EBNF gets replaced with DSN, for example DSN.final-recipient-field fields 🌟

3.1.2. ASN.1 🎀

okay so an element gets referred to with this EBNF syntax 🧚 it's giving very organised, bestie:

element         = service "." definition *( "." definition )
service         = "IPMS" / "MTS" / "MTA"
definition      = identifier / context
identifier      = ALPHA *< ALPHA or DIGIT or "-" >
context         = "[" 1*DIGIT "]"

the EBNF.service keys are just shorthand for these service specs 💅

IPMS is IPMSInformationObjects, defined in Annex E of X.420 / ISO 10021-7.

MTS is MTSAbstractService, defined in Section 9 of X.411 / ISO 10021-4.

MTA is MTAAbstractService, defined in Section 13 of X.411 / ISO 10021-4.

FTBP is File Transfer Body Part, as defined in [27].

the first EBNF.identifier names a type or value key in the context of the defined service spec 🔑 the later ones name a value label or type inside the first identifier (that's a SET or SEQUENCE thing). EBNF.context is a context tag, and you use it when there's no label or type to uniquely identify a component. there's also a special EBNF.identifier keyword, "value", which denotes an element of a sequence ✨ for example, IPMS.Heading.subject defines the subject element of the IPMS heading. the same syntax also works for element values. like, MTS.EncodedInformationTypes.[0].g3Fax refers to a value of MTS.EncodedInformationTypes.[0] 🦋


3.2. ASCII and IA5 🌸

a gateway will interpret all IA5 as ASCII 🫶 so mapping between these forms is conceptual, not a real conversion. no drama!


3.3. Standard Types 💖

okay so there's a need to convert between ASCII text and some of the types defined in ASN.1 [14] ✨ for each case there's an EBNF syntax definition for use across this whole spec, and it leads to a mapping between ASN.1 and an EBNF construct. all EBNF syntax definitions of ASN.1 types are lower case, whereas ASN.1 types get referred to with the first letter capitalised 💅 except where noted, all mappings are SYMMETRICAL, periodt.

3.3.1. Boolean 🍓

boolean is encoded as:

boolean = "TRUE" / "FALSE"

3.3.2. NumericString 🌈

NumericString is encoded as:

numericstring = *(DIGIT / " ")

3.3.3. PrintableString 💜

PrintableString is a restricted IA5String, defined as:

printablestring  = *( ps-char )
ps-restricted-char      = 1DIGIT /  1ALPHA / " " / "'" / "+"
                   / "," / "-" / "." / "/" / ":" / "=" / "?"
ps-delim         = "(" / ")"
ps-char          = ps-delim / ps-restricted-char

this can be used to represent real printable strings in EBNF 🧁

3.3.4. T.61String 🦋

okay this one's a little extra. when T.61 strings are only used for conveying human-interpreted information, the goal of a mapping is to render the characters properly in the remote character set, rather than to maximise reversibility 👑 there are two options here, and BOTH are conformant to this spec:

  1. the mappings to IA5 defined in ITU-T Recommendation X.408 (1988) MAY be used [13]. these then get encoded in ASCII. this is the approach mandated in RFC 1327 ✨
  2. this mapping MAY be used if the characters aren't all in the ASCII repertoire, but they ARE all in an IANA-registered character set. use the encoding defined in RFC 1522 [9] to generate the appropriate encoded-words 🫶 if this mapping is used, the character set ISO-8859-1 SHALL be used if all of the characters needed are available in that repertoire. in other cases, the character set TELETEX SHALL be used. the details of this character set are defined in Appendix C of RFC 2157 🔥

there's also a need to represent Teletex Strings in ASCII, for some aspects of OR Address 💅 for those, the following encoding is used:

teletex-string   = *( ps-char / t61-encoded )
t61-encoded      = "{" 1* t61-encoded-char "}"
t61-encoded-char = 3DIGIT

characters in EBNF.ps-char are mapped simply 🌸 other octets, including control characters, get mapped using a quoting mechanism similar to the printable string one. each octet is represented as 3 decimal digits. for example, the Yen character (hex A5) is represented as {165}. so the three character string "a", yen character, "b" would be represented as either "a{165}b" 🧚

the use of escape sequences follows what's set down for ASN.1 in ISO 8825-1, with the additional specification that the default G1 page is ISO Latin 1 ✨ the page settings MAY be changed by escape sequences. changes of the settings hold within a pair of curly brackets ({}), and the settings revert to the default after the right bracket (}) (i.e., they do NOT carry forward to subsequent T.61 encoding). it's giving clean boundaries, no cap 🙈

there are a number of places where a string may have a Teletex and/or Printable String representation, and the following EBNF is used to represent this:

teletex-and-or-ps = [ printablestring ] [ "*" teletex-string ]

the natural mapping is restricted to EBNF.ps-char, so the full BNF is easier to parse 💖 an example is:

"yen*{165}"

3.3.5. UTCTime ⭐

both UTCTime and the RFC 822 822.date-time syntax contain: Year, Month, Day of Month, hour, minute, second (optional), and Timezone (technically a time differential in UTCTime) 🫶 822.date-time also has an optional day of the week, but that's redundant. apart from Year, you can make a symmetrical mapping between these constructs ✨

Note: in practice, a gateway will need to parse various illegal variants of 822.date-time. when 822.date-time can't be parsed, it is RECOMMENDED that the derived UTCTime is set to the value at the time of translation. such errors MAY be noted in an RFC 822 comment, to aid detection and correction. 😭

when mapping to X.400, the UTCTime format which specifies the timezone offset SHALL be used 🔥

when mapping to RFC 822, the 822.date-time format SHALL include a numeric timezone offset (e.g., -0500) 💅

when mapping time values, the timezone SHALL be preserved as specified. the date SHALL NOT be normalised to any other timezone 🌈 no sneaky timezone shifts, bestie!

RFC 822, as modified by RFC 1123, requires use of a four digit year. note that the original RFC 822 uses a two digit date, which is no longer legal, and UTCTime uses a two digit date too 🙈 to map a year from RFC 822 to X.400, just use the last two digits. to map a year from X.400 to RFC 822, assume the two digit year refers to a year in the 10 year epoch 1980-2079 🧚

3.3.6. Integer 💜

a basic ASN.1 Integer gets mapped onto EBNF.numericstring 🌸 in lots of cases, ASN.1 will enumerate Integer values or use ENUMERATED. there's an EBNF encoding called labelled-integer for this. when mapping from EBNF to ASN.1, only the integer value is mapped and the associated text is discarded. when mapping from ASN.1 to EBNF, a text label MAY be added. it is RECOMMENDED that this is done wherever possible, and that clear text labels are chosen 👑

a second encoding, labelled-integer-2, is provided ✨ it's used in DSNs, where the parsing rules treat the text as a comment. this definition was not present in RFC 1327.

labelled-integer ::= [ key-string ] "(" numericstring ")"

labelled-integer-2 ::= [ numericstring ] "(" key-string ")"

key-string      = *key-char
key-char        = <a-z, A-Z, 0-9, and "-">

3.3.7. Object Identifier 🦋

object identifiers are represented in a form similar to the one in ASN.1 🌈 the order is the same as for ASN.1 (big-endian). the numbers are mandatory, and they're used when mapping from ASCII to ASN.1. the key-strings are optional. when mapping from ASN.1 to ASCII, it is RECOMMENDED that as many strings as possible are generated, to facilitate user recognition 🫶

object-identifier  ::= oid-comp object-identifier
                | oid-comp

oid-comp ::= [ key-string ] "(" numericstring ")"

an example representation of an object identifier is:

joint-iso-ccitt(2) mhs (6) ipms (1) ep (11) ia5-text (0)

or

(2) (6) (1)(11)(0)

because of the brackets and the clash with the RFC 822 comment convention, MIXER is defined so that the EBNF.object-identifier definition is NOT used in structured fields 💀 keep it spicy but keep it clean.


3.4. Encoding ASCII in Printable String 🧚

some information in RFC 822 is represented in ASCII, and it needs to be mapped into X.400 elements encoded as printable string. so there's a need for a mechanism to represent ASCII encoded as PrintableString ✨

a structured subset of EBNF.printablestring is now defined, and it SHALL be used to encode ASCII in the PrintableString character set 💅

ps-encoded       = *( ps-restricted-char / ps-encoded-char )
ps-encoded-char  = "(a)"               ; (@)
                 / "(p)"               ; (%)
                 / "(b)"               ; (!)
                 / "(q)"               ; (")
                 / "(u)"               ; (_)
                 / "(l)"               ; "("
                 / "(r)"               ; ")"
                 / "(" 3DIGIT ")"

the 822.3DIGIT in EBNF.ps-encoded-char SHALL have range 0-127, and it's interpreted in decimal as the corresponding ASCII character 🔢 special encodings are given for: at sign (@), percent (%), exclamation mark/bang (!), double quote ("), underscore (_), left bracket ((), and right bracket ()). these characters, apart from the round brackets, are NOT included in PrintableString, but they're common in RFC 822 addresses 🙈 the abbreviations make it easier to specify RFC 822 addresses from an X.400 system. these special encodings SHALL be interpreted in a case insensitive manner, but they're always generated in lower case 🌸

a reversible mapping between PrintableString and ASCII can now be defined 🦋 but the reversibility means some values of printable string (the ones containing round braces) can't be generated from ASCII. so this mapping SHALL only be used where the printable strings were derived from ASCII (and so they'll have a restricted domain) 🔐 for example, in this spec it's only applied to a Domain Defined Attribute that was generated using this spec, so a value like "(" would never come up.

to encode ASCII as PrintableString, use the EBNF.ps-encoded syntax, with all EBNF.ps-restricted-char mapped directly. all other 822.CHAR get encoded as EBNF.ps-encoded-char 💖

to encode PrintableString as ASCII, parse the PrintableString as EBNF.ps-encoded, and then reverse the previous mapping. if the PrintableString can't be parsed, then the mapping is being applied to an inappropriate value, and an error SHALL be given to the procedure doing the mapping. in some cases, it MAY be preferable to pass the printable string through unaltered 😭

okay, some examples now. the arrows show the asymmetrical mappings, so watch those ✨

     PrintableString           ASCII

     'a demo.'         <->   'a demo.'
     foo(a)bar         <->   foo@bar
     (q)(u)(p)(q)      <->   "_%"
     (a)               <->   @
     (A)               ->    @
     (l)a(r)           <->   (a)
     (126)             <->   ~
     (                 ->    (
     (l)               <->   (

3.5. RFC 1522 🎀

okay so RFC 1522 is a lowkey genius little mechanism for sneaking other character set info into RFC 822 headers 🦋 A gateway MAY ignore that encoding and just treat the elements as ASCII, which is giving "low effort but still valid" 💅

A preferred approach is for the gateway to interpret the RFC 1522 encoding. This is not always straightforward though 😭 because:

  1. RFC 1522 permits an openly extensible character set choice, which MAY be broader than T.61. Main character energy, the set is basically open-ended 🌈
  2. It is not always possible to map all characters into the equivalent X.400 field. 💀

RFC 1522 is only applied to fields which are "for information only". A gateway which interprets header elements according to RFC 1522 MAY apply reasonable heuristics to minimise information loss ✨

Chapter 4 - Addressing and Message IDs 🧚

Addressing is the most complex part of the X.400 <-> RFC 822 gateway, so it gets its own chapter 👑 This chapter also covers message identifiers, because they're closely linked to addresses. As a side effect, it defines a textual representation of an X.400 OR Address. That representation is super similar to the X.400(92) one, because early versions of this spec were a major input to this work 🫶 This spec stays compatible with earlier versions. The X.400 address representation can be parsed but is not generated.

Initially we think about an address in the (human) mail user sense of "what is typed at the mailsystem to reference a mail user" 🙈 A basic RFC 822 address is defined by the EBNF EBNF.822-address:

         822-address     = [ route ] addr-spec

These definitions come straight from RFC 822. In SMTP (or another 822-MTS protocol), the originator and each recipient are each defined by a construct like this. In an RFC 822 header, EBNF.822-address gets wrapped in the 822-address syntax rule, and there MAY also be associated comments. None of this extra info has any semantics, except for the end user 🍓

The basic X.400 OR Address, which the MTS uses for routing, is defined by MTS.ORAddress. In IPMS, MTS.ORAddress gets wrapped inside IPMS.ORDescriptor 💜

The RFC 822 822.address maps to IPMS.ORDescriptor, and the RFC 822 EBNF.822-address maps to MTS.ORAddress ✨

Section 4.1 defines a textual representation of an OR Address, which the rest of this spec uses throughout. It's designed to represent an X.400 address in the LHS (left hand side), or local part, of an RFC 822 address. So this representation is basically the mechanism for putting X.400 addresses inside RFC 822 addresses 🦋

Section 4.2 describes the global equivalence mapping between parts of the X.400 and RFC 822 name spaces, and defines the concept of a MIXER Conformant Global Address Mapping (MCGAM). Gateways conforming to this specification SHALL support MCGAMs 🌸

Section 4.3 is the core part of this chapter, and it defines the mapping mechanism 🔥


4.1. A textual representation of MTS.ORAddress 💅

MTS.ORAddress is structured as an ordered set of attributes (type/value pairs). It's clearly necessary to be able to encode this in ASCII for gatewaying, so yes, we need it. All components SHALL be encoded, so that error messages are guaranteed to come back and third party replies get optimised 🎀

4.1.1. Basic OR Address Representation 🌈

An OR Address has a bunch of structured and unstructured attributes 😭 For each unstructured attribute, a key and an encoding are specified. For structured attributes, the X.400 attribute gets mapped onto one or more attribute value pairs. For domain defined attributes, each element of the sequence gets mapped onto a triple (a key and two values), with each value having the same encoding. The attributes are listed below, with the 1984 attributes given in the first part of the attribute key table. For each attribute there's a reference, made up of the relevant sections in X.402 / ISO 10021-2, plus the extension identifier for the 88 only attributes. Here's the attribute key table 👑

Attribute (Component)               Key         Enc    Ref     Id

84/88 Attributes

MTS.CountryName                      C                P     18.3.3
MTS.AdministrationDomainName         ADMD             P     18.3.1
MTS.PrivateDomainName                PRMD             P     18.3.21
MTS.NetworkAddress                   X121             N     18.3.7
MTS.TerminalIdentifier               T-ID             P     18.3.23
MTS.OrganizationName                 O                P/T   18.3.9
MTS.OrganizationalUnitNames.value    OU               P/T   18.3.10
MTS.NumericUserIdentifier            UA-ID            N     18.3.8
MTS.PersonalName                     PN               P/T   18.3.12
MTS.PersonalName.surname             S                P/T   18.3.12
MTS.PersonalName.given-name          G                P/T   18.3.12
MTS.PersonalName.initials            I                P/T   18.3.12
MTS.PersonalName
   .generation-qualifier             GQ               P/T   18.3.12
MTS.DomainDefineAttribute.value      DD               P/T   18.1
88 Attributes

MTS.CommonName                       CN               P/T   18.3.2    1
MTS.TeletexCommonName                CN               P/T   18.3.2    2
MTS.TeletexOrganizationName          O                P/T   18.3.9    3
MTS.TeletexPersonalName              PN               P/T   18.3.12   4
MTS.TeletexPersonalName.surname      S                P/T   18.3.12   4
MTS.TeletexPersonalName.given-name   G                P/T   18.3.12   4
MTS.TeletexPersonalName.initials     I                P/T   18.3.12   4
MTS.TeletexPersonalName
   .generation-qualifier             GQ               P/T   18.3.12   4
MTS.TeletexOrganizationalUnitNames
   .value                            OU               P/T   18.3.10   5
MTS.TeletexDomainDefinedAttribute
   .value                            DD               P/T   18.1      6
MTS.PDSName                          PD-SERVICE       P     18.3.11   7
MTS.PhysicalDeliveryCountryName      PD-C             P     18.3.13   8
MTS.PostalCode                       PD-CODE          P     18.3.19   9
MTS.PhysicalDeliveryOfficeName       PD-OFFICE        P/T   18.3.14   10
MTS.PhysicalDeliveryOfficeNumber     PD-OFFICE-NUM    P/T   18.3.15   11
MTS.ExtensionORAddressComponents     PD-EXT-ADDRESS   P/T   18.3.4    12
MTS.PhysicalDeliveryPersonName       PD-PN            P/T   18.3.17   13
MTS.PhysicalDeliveryOrganizationName PD-O             P/T   18.3.16   14
MTS.ExtensionPhysicalDelivery
   AddressComponents                 PD-EXT-DELIVERY  P/T   18.3.5    15
MTS.UnformattedPostalAddress         PD-ADDRESS       UPA   18.3.25   16
MTS.StreetAddress                    PD-STREET        P/T   18.3.22   17
MTS.PostOfficeBoxAddress             PD-BOX           P/T   18.3.18   18
MTS.PosteRestanteAddress             PD-RESTANTE      P/T   18.3.20   19
MTS.UniquePostalName                 PD-UNIQUE        P/T   18.3.26   20
MTS.LocalPostalAttributes            PD-LOCAL         P/T   18.3.6    21
MTS.ExtendedNetworkAddress
   .e163-4-address.number            NET-NUM          N     18.3.7    22
MTS.ExtendedNetworkAddress
   .e163-4-address.sub-address       NET-SUB          N     18.3.7    22
   .psap-address                     NET-PSAP         X     18.3.7    22
MTS.TerminalType                     T-TY             I     18.3.24   23

okay so these are the last keys in the table, bestie 💅 Next up is the little code that tells you how each value is spelled. Look at this lineup 👑

         Key         Encoding

         P     printablestring
         N     numericstring
         T     teletex-string
         P/T   teletex-and-or-ps
         UPA   upa-string
         I     labelled-integer
         X     presentation-address

The EBNF for presentation-address comes from RFC 1278 "A String Encoding of Presentation Address" [23] 🦋

Usually the EBNF encoding lines up directly with the ASN.1 encoding of the attribute, which is so clean 🫶 There are a few exceptions though. For Country, ADMD, and PRMD, the attribute can be either a PrintableString or a NumericString, and either form gets mapped into the EBNF ✨ When you're generating ASN.1, the NumericString encoding SHALL be used if the string contains digits and only digits. That's the rule, no cap 💖

P/T (teletex-and-or-ps) shows up a lot too. When a key maps to just one attribute, the choice shows up right in that attribute's encoding (attributes 10-21). Like this:

      /CN=yen*{165}/

Here's the deal with the 1984 attributes and common name: most of them have a printablestring version AND a teletex version. This pair gets squished into one component here, which makes the common cases super clean 🌸 If there's only a teletex attribute or teletex component, and it only has characters from the printable string set, then it SHALL be written in the EBNF as if it were a printable string. Same goes when both forms exist but they have the exact same printable string 🙈

The Unformatted Postal Address is a little more dramatic 💀 It maps onto a variant of the P/T thing, defined like this:

        upa-string = [ printable-upa ] [ "*" teletex-string ]
        printable-upa = printablestring *( "|" printablestring )

The teletex bit is optional and straightforward. Then you get an optional list of printable strings that get mapped in order, like:

      /PD-ADDRESS=The Dome|The Square|Richmond|England/

X.400 (1992) brought its own string representation of OR Addresses (see F.401, Annex B) with a bunch of keyword strings for attributes 🎀 Earlier versions of this spec were an input to that work, so lots of the keywords match. For better compatibility, the following alternative values SHALL be recognised when mapping from RFC 822 to X.400. They SHALL NOT be generated when mapping from X.400 to RFC 822, though 🙅‍♀️ Here's the table:

                        Keyword         Alternative

                    ADMD              A
                    PRMD              P
                    GQ                Q
                    X121              X.121
                    UA-ID             N-ID
                    PD-OFFICE-NUM     PD-OFFICE NUMBER
                    PD-OFFICE-NUM     PD-OFN
                    PD-EXT-ADDRESS    PD-EA
                    PD-EXT-DELIVERY   PD-ED
                    PD-OFFICE         PD-OF
                    PD-STREET         PD-S
                    PD-UNIQUE         PD-U
                    PD-LOCAL          PD-L
                    PD-RESTANTE       PD-R
                    PD-BOX            PD-B
                    PD-CODE           PD-PC
                    PD-SERVICE        PD-SN
                    DD                DDA
                    NET-NUM           E.164
                    NET-PSAP          PSAP
                    PD-ADDRESS        PD-A

When you map RFC 822 to X.400, the keywords in that table SHALL be recognized 🧚 The ordered keywords OU1, OU2, OU3, and OU4 SHALL be recognised too. If those show up, then no keyword OU SHALL be present, and they get treated as ordered values of OU. PD-A1 through PD-A6 get treated as ordered lines, and if they're there, they're stuck together with line feeds into one physical address. In that case, PD-ADDRESS (or PD-A) SHALL NOT be present 🤯 There are ordered keywords for domain defined attributes too: DD1, DD2, DD3, DD4,

If ISDN shows up, it MAY be read as an E.163/164 address, using local heuristics to parse the string. X.400 defines the key but doesn't say what the value means, so that's on you, bestie 💅

For T-TY (Terminal Type), the X.400 recommended values are the preferred ones, but other values are allowed too. The listed values are tlx (3), ttx (4), g3fax (5), g4fax (6), ia5 (7), and vtx (8) ✨


4.1.2. Encoding of Personal Name 🌈

Personal Name and Teletex Personal Name are a shared headache, so MIXER came up with an alternative to the EBNF.standard-type syntax 🦋 It uses the "human" conventions for names, and it's built for the common cases where:

  1. There is no generational qualifier
  2. Initials, if present, contain only letters
  3. Given Name, if present, does not contain full stop ("."), and is at least two characters long.
  4. Surname does not contain full stop in the first two characters.
  5. If Surname is the only component, it does not contain full stop.

Here's the EBNF:

      encoded-pn      = [ given "." ] *( initial "." ) surname

      given           = 2*<ps-char not including ".">

      initial         = ALPHA

      surname         = printablestring

It's used to map any string made only of printable string characters into an OR address personal name 💖 To go from a string to OR Address components, you parse the string using the EBNF. The given name and surname get assigned straight across, and all the EBNF.initial tokens are stuck together, no full stops, to make the initials component 🫶

If an OR address follows the restrictions above, the string gets built in the natural way, and the mapping is reversible. Example time:

      GivenName       = "Marshall"
      Surname         = "Rose"

      Maps with  "Marshall.Rose"

      Initials        = "MT"
      Surname         = "Rose"

      Maps with  "M.T.Rose"

      GivenName       = "Marshall"
      Initials        = "MT"
      Surname         = "Rose"

      Maps with  "Marshall.M.T.Rose"

X.400 suggests using Initials to encode all the initials except the surname (X.402 section 18.3.12), so this encoding feels natural when you've got either GivenName or Initials, but not both 🌸 Having both is still encodable though, so you're covered ✨


4.1.3. Standard Encoding of MTS.ORAddress 🎀

Now that we've got the structure, we can write an EBNF for an OR Address 💅 Output addresses follow EBNF.std-or-address, and the more flexible input format is EBNF.std-or-address-input. The input EBNF was added after RFC 1327, so it could formally include a bunch of heuristics 🧚 On input, the address element separator MAY be "/", ";", or a mix of both. The output format is what all the examples use, so that's your reference, bestie 🍓

         std-or-address  = 1*( "/" attribute "=" value ) "/"
         attribute       = standard-type
                         / "RFC-822"
                         / dd-key "." std-printablestring

         std-or-address-input =  [ sep pair ] sep  pair *( sep pair )
                                sep  [ pair sep ]

         sep             = "/" / ";"
         pair            = input-attribute "=" value
         input-attribute = attribute
                         / dd-key ":" std-printablestring

         standard-type   = key-string

         dd-key          = key-string

         value           = std-printablestring

         std-printablestring
                         = *( std-char / std-pair )

         std-char        = <"{", "}", "*", and any ps-char
                                         except "/" and "=" >
         std-pair        = "$" ps-char

For address generation, the standard-type can be any key from the key table in Section 4.1, except PN and DD 🌈 For address parsing, other key values from Section 4.1 are valid too. The EBNF turns into a set of attribute/value pairs, and each value gets read according to the encoding in the table 💖

If the standard-type is PN, the value gets read by EBNF.encoded-pn, and the MTS.PersonalName and/or MTS.TeletexPersonalName components get derived from that 🫶

If dd-key is the recognised Domain Defined string (DD) or one of the alternatives from Section 4.1, then the type and value are read according to the syntax implied by the encoding, and lined up with either the teletex or printable string form. Key and value SHALL have the same encoding 🙅‍♀️

If value is "RFC-822", the (printable string) Domain Defined Type of "RFC-822" is assumed. This is an optimised encoding of the domain defined type from this spec 🦋

The matching of all keywords SHALL be done in a case-independent manner. ✨

EBNF.std-or-address uses "/" and "=" as delimiters. Domain Defined Attributes and any value MAY contain those characters, though 😭 So there's a quoting mechanism: the non-printable string "$" lets you represent them safely 🔥

If an address of this syntax is parsed and there's a country value but no ADMD, the string SHALL be read as if an ADMD value of a single space had been given. Plot twist, but it's the rule 💀

4.2. Global Address Mapping ✨

Okay bestie, from a user's point of view the dream is a mapping that's totally symmetrical and global 💖 so addresses could be referenced transparently in the remote system, with the gateway choice left up to the Message Transfer Service 🧚. But there are two big reasons that's not happening 😭:

  1. The syntaxes are sufficiently different to make this impossible.
  2. There is insufficient administrative co-operation between the X.400 and RFC 822 name registration authorities for this to work.

So there's not a full global equivalence between X.400 and RFC 822 addressing 🦋. To meet user needs as much as possible, this specification provides for equivalence where there is sufficient co-operation 🫶. To be useful, this equivalence has to be recognised and interpreted in the same way by all gateways, so an asymmetrical mapping is defined, which can become symmetrical where there's appropriate administrative co-operation. Section 4.3 describes the asymetrical aspects. This section describes the mechanism for the administrative co-ordination needed for symmetrical mappings 💅.

To get a symmetrical mapping, we need an administrative equivalence between parts of the OR Address and Domain namespaces. Earlier versions of this specification did this with a global set of mappings. MIXER defines the concept of a MIXER Conformant Global Address Mapping (MCGAM), and the acronym is defined so it's very clear what's being referenced 🎀.

The X.400 and Internet Mail address spaces are both hierarchical 🌳. It's possible to define an equivalence between two points in the hierarchies, so that addresses below that point can be derived algorithmically. An MCGAM is a mapping from a point in one hierarchy to a point in the other hierarchy. An "MGGAM pair" is a pair of symmetrical mappings between two points. To define an MCGAM, the following apply:

  1. The authority defining the MCGAM shall have responsibility for BOTH of the namespaces between which the MCGAM is defined.
  2. The authority defining the MCGAM is responsible to ensure that addresses allocated below the two equivalence points conform to the rules set out below.
  3. The authority defining the MCGAM is responsible to ensure that addresses which are generated according to the MCGAM are routed correctly.

In general, MCGAMs will be independent 🌸. In some cases a set of MCGAMs may be related (for example, where one MCGAM defines a mapping for an organization and a second MCGAM defines an exception for a subtree within that organization). In this case, the related set of MCGAMs shall be treated as a single MCGAM for distribution purposes.

The existence of an MCGAM does not imply routability and access for all users. Not every address that maps is reachable, bestie 🙈

The authority defining an MCGAM may simply use this mapping locally. This will often be the case in a "local scenario" gateway. Because of third party addressing, a MIXER gateway will work best with the maximum number of MCGAMs 📬. So there are three mechanisms defined to enable publication and exchange of MCGAMs:

  1. Distribution of text tables. This is described in Appendix F of this specification.
  2. Distribution by Domain Name Service. This is described in RFC 2163 [3].
  3. Distribution by X.500 Directory Service. This is defined in RFC 2164 [26].

The following sections define how the MCGAM namespace equivalence is modelled ✨. The Internet Domain Namespace defines a simple hierarchy. For the purposes of this mapping, only parts of the namespace where domains conform to the EBNF domain-syntax are allowed:

domain-syntax   = alphanum [ *alphanumhyphen alphanum ]
alphanum        = <ALPHA or DIGIT>
alphanumhyphen  = <ALPHA or DIGIT or HYPHEN>

Even though RFC 822 allows for a more general syntax, this restricted one is used in MIXER because it's the one the various domain service administrations chose. In practice it reflects all RFC 822 usage, so it's giving completely accurate vibes 💜.

The following OR Address attributes are considered a hierarchy, and may be specified by the domain. They are (in order of the hierarchy defined by MIXER):

Country, ADMD, PRMD, Organization, Organizational Units

There may be up to four ordered Organizational Units 🌈. This hierarchy reflects most usage of X.400, although X.400 may be used in other ways. In particular, it covers the Mnemonic OR Address using a 1984 compatible encoding. This is seen as the dominant form of OR Address, so MCGAMs may only be used when this hierarchy applies 👑.

An equivalence mapping is defined between two nodes in the respective hierarchies. For example:

=> "AC.UK" might be mapped with
   PRMD="UK.AC", ADMD="GOLD 400", C="GB"

The mapping shows that management of these points in the respective hierarchies is the same (or co-operates very closely) 🤝. The equivalence means the namespaces below this equivalence point map 1:1, except where the mapping is overridden by further equivalence mappings lower down the hierarchy. This equivalence may be achieved in three ways:

  1. All of the nodes below this point are RFC 822, and the MIXER mapping defines the X.400 addresses for these nodes.
  2. All of the nodes below this point are X.400, and the MIXER mapping defines the RFC 822 addresses for these nodes.
  3. There are X.400 and RFC 822 nodes below this point, and addressing is managed in a manner which ensures the equivalence. The rules to achieve this are defined by MIXER.

Each of these ways gives a framework for MCGAM definition 🦋.

When an MCGAM is defined, a systematic mapping for the inferior nodes in the two hierarchies follows. This is a 1:1 mapping between the nodes in the subtrees. For example, given the MCGAM pair defined above:

the domain "R-D.Salford.AC.UK" algorithmically maps with
OU="R-D", O="Salford", PRMD="UK.AC", ADMD="GOLD 400", C="GB"

Note that when an equivalence is defined, it can be re-defined for lower points in the hierarchy. However, it is not possible to declare contained subtrees to be un-mappable 🙅‍♀️.

The equivalence mapping also provides a mechanism to deal with missing elements in the X.400 hierarchy. The most common one is the PRMD, which is the only element that may be omitted when conforming to recent versions of X.400 🧩. A domain may be associated with an omitted attribute in conjunction with several present ones. When performing the algorithmic insertion of components lower in the hierarchy, the omitted value shall be skipped. For example:

If there is an MCGAM pair between domain HNE.EGM and "O=HNE",
"ADMD=ECQ", "C=TC", and omitted PRMD

then

"ZI.HNE.EGM" is algorithmically mapped with "OU=I", "O=HNE",
"ADMD=ECQ", "C=TC"

Attributes may have null values, and this is treated separately from omitted attributes. It's not ideal to make this distinction, but it's useful in practice 💀.

4.2.1. Directory and Nameserver Mappings

When a set of MCGAMs is supported by X.500 or DNS, there is the possibility that results will be indeterminate due to timeout 😩. Lookup shall be repeated until a value is determined, in order to maintain consistent gateway operation.

Where the mapping relates to an envelope address, the gateway shall non-deliver messages according to the associated MTA's normal timeout policy. Where the mapping relates to addresses in the message header, there shall be a timeout in the range of 1-4 hours, or shorter if this is required to maintain quality of service constraints. If a mapping cannot be done in this time, address encapsulation shall be used ⏰.

4.3. EBNF.822-address <-> MTS.ORAddress

This section defines the basic address mapping. 🌷

4.3.1. X.400 encoded in RFC 822 ✨

Okay bestie, this part is all about squishing an X.400 address into an RFC 822 address 🎀 The std-or-address syntax is what packs OR Address info into the 822.local-part of an EBNF.822-address. If there's an applicable equivalence mapping, more OR Address info can hook onto the 822.domain part too 🦋 But that can't work in every case, because of character set drama and because some X.400 OR Addresses use different attribute types 😭

The only way to fit the full PrintableString character set into a domain is the 822.domain-ref syntax (aka 822.atom) 💀 and that's likely to cause problems on lots of systems. In practice, domains end up with a smaller character set than RFC 822 allows, thanks to domain conventions and policy [10] and the EBNF definition in SMTP 🌸

A generic 822.address is a 822.local-part plus a sequence of 822.domains, like <@domain1,@domain2:user@domain3> 🧚 Every domain EXCEPT the one tied to the local-part (that's domain3 here) is just routing inside the RFC 822 world, and the gateway won't interpret it. Those domains may have helped identify the gateway from within the RFC 822 world, though.

The 822.domain tied to the 822.local-part is how you identify the gateway from inside the RFC 822 world 📮 This final 822.domain MAY be used to work out some OR Address attributes, as long as that doesn't clash with its first job. Usually, RFC 822 routing to gateways is set up so the 822.domain does both jobs at once 🍓

No applicable equivalence mapping? No problem 🙈 The whole X.400 address goes in the 822.local-part, and the 822.domain just names the gateway the message is heading to. An RFC 822 user MAY use this trick for any X.400 address whose equivalence mapping they don't know.

Got an applicable MCGAM? Then as many attributes as possible go in the 822.domain, and whatever's left goes on the LHS using the EBNF.std-or-address syntax. For example:

      /I=J/S=Linnimouth/GQ=5/@Marketing.Widget.COM

which encodes the MTS.ORAddress made of:

         MTS.CountryName                       = "TC"
         MTS.AdministrationDomainName          = "BTT"
         MTS.OrganizationName                  = "Widget"
         MTS.OrganizationalUnitNames.value     = "Marketing"
         MTS.PersonalName.surname              = "Linnimouth"
         MTS.PersonalName.initials             = "J"
         MTS.PersonalName.generation-qualifier = "5"

based on an MCGAM pair between:

         Domain: Widget.COM
         OR Address: O="Widget", ADMD="BTT", C="TC"

Given that OR address, the equivalence mapping gives us the domain Widget.COM, and then the next component gets worked out algorithmically to make Marketing.Widget.COM 🧮 The leftover attributes go on the LHS in 822.local-part.

There's also a shortcut for the common stuff 🌈 for when the only LHS attributes are (non-Teletex) Personal Name attributes that follow the rules in 4.1.2. To do this, the 822.local-part SHALL be encoded as EBNF.encoded-pn. Using the example above but with no GenerationQualifier in the OR Address, it would map to the RFC 822 address J.Linnimouth@Marketing.Widget.COM 💖

From the RFC 822 Message Transfer System's point of view, the domain part routes the message the normal way 🚚 The usual domain mechanisms pick the right gateways for the matching OR Address space. And whoever manages the equivalence mapping is responsible for setting up routing so the message can actually get delivered 👑


4.3.2. RFC 822 encoded in X.400 ✨

Last section we went from X.400 to RFC 822. If that mapping was symmetrical and based on the equivalence mapping, it also shows how RFC 822 gets encoded in X.400 🔄 But that equivalence can't cover every RFC 822 address, sorry bestie 🫶

The general case uses domain defined attributes 🎀 There's a (Printable String) Domain defined type called "RFC-822". Its attribute value is an ASCII string encoded per Section 3.3.3 of this specification, and that string gets interpreted following RFC 822 and RFC 1123 [10,16]. Domains SHALL always be fully qualified.

Other OR Address attributes do the job of setting the context the OR Address gets interpreted in 🧭 That could be a Management Domain, or some bit of one that points at a gateway MTA. For example:

         C               = "GB"
         ADMD            = "GOLD 400"
         PRMD            = "UK.AC"
         O               = "UCL"
         OU              = "CS"
         "RFC-822"      =  "Jimmy(a)WIDGET-LABS.CO.UK"

OR

         C               = "TC"
         ADMD            = "Wizz.mail"
         PRMD            = "42"
         "rfc-822"       = "postel(a)venera.isi.edu"

Heads up: in each case "@" gets written as "(a)" because that's the PrintableString encoding 👀 In the second example, the "RFC-822" domain defined attribute is understood everywhere inside the (Private) Management Domain. In the first one, you need more attributes inside the Management Domain to find the gateway. So this scheme works with all sorts of Management Domain co-operation levels 🌻

Limits, bestie 📏 A domain defined attribute value maxes out at 128 characters, and an OR Address can have a maximum of four domain defined attributes. If the printable string from the RFC 822 address goes over 128 characters, extra domain defined attributes kick in so you can encode up to 512 characters 💜 Each one SHALL be filled completely before the next one is started. The (Printable String) DDA keywords are: RFC822C1; RFC822C2; RFC822C3. Longer addresses cannot be encoded 😭

MIXER has a way to represent RFC 822 addresses in printable string domain defined attributes 🦋 Teletex domain defined attributes with a key of RFC-822, RFC822C1; RFC822C2; RFC822C3 SHALL NOT be generated, and that's for backwards compatibility 🕰️

Receiving these attributes the way defined below is mandatory 🧡 That leaves room for future versions of MIXER to generate teletex domain defined attributes. When all the values of these teletex domain defined attributes are printable string characters, they SHALL be interpreted the same way as the printable string domain defined attributes. If that's not the case, the printable string encoding translation SHALL be omitted. If both teletex and printable string attributes show up, it's only valid if they represent exactly the same RFC 822 address 💅


4.3.3. Component Ordering ✨

Mostly, the order of OR Address components doesn't matter for these mappings 🙌 BUT Organizational Units (printable string and teletex forms) and Domain Defined Attributes are specified as SEQUENCEs in MTS.ORAddress, so their order may be significant. This spec has to account for that. It's aiming for:

  1. To allow consistent mapping into the domain hierarchy
  2. To ensure preservation of order over multiple mappings.

There are three spots where an order gets specified 📍

  1. The text encoding (std-or-address) of MTS.ORAddress as used in the local-part of an RFC 822 address. An order is needed for those components which may have multiple values (Organizational Unit, and Domain Defined Attributes). When generating an 822.std-or-address, components of a given type SHALL be in hierarchical order with the most significant component on the RHS (right hand side or domain part). If there is an Organization Attribute, it SHALL be to the right of any Organizational Unit attributes. These requirements are for the following reasons:
    • Alignment to the hierarchy of other components in RFC 822 addresses (thus, Organizational Units will appear in the same order, whether encoded on the RHS or LHS).
    • Backwards compatibility with RFC 987/1026.
    • To ensure that gateways generate consistent addresses. This is both to help end users, and to generate identical message ids.

Further, it is RECOMMENDED that all other attributes are generated according to this ordering, so that all attributes so encoded follow a consistent hierarchy. When generating 822.msg-id, this order SHALL be followed.

  1. For the Organizational Units (OU) in MTS.ORAddress, the first OU in the SEQUENCE is the most significant, as specified in X.400.
  2. For the Domain Defined Attributes in MTS.ORAddress, the first Domain Defined Attribute in the SEQUENCE is the most significant.

Note that although this ordering is mandatory for this mapping, MIXER does not give additional implications on the ordering significance within X.400. 💜

4.3.4. RFC 822 -> X.400 Basic Address Mapping ✨

Okay bestie, so there are two basic cases here 🎀:

  1. X.400 addresses that got encoded inside RFC 822. This also covers RFC 822 addresses that have reversible encodings.
  2. "Genuine" RFC 822 addresses 🦋

The mapping shall go by first assuming case 1). It's giving detective energy 🕵️‍♀️

STAGE I.

  1. If the 822-address is not in the form local-part "@" domain, take the domain that will be routed on and apply step 2 of stage 1 to get a (possibly null) set of attributes. Then go to stage II 💅

The gateway may shorten a source route address to this form by removing everything except the last domain. Ngl, by the design intentions of RFC 822 this would be a wrong move 🙈 (fyi an address like local%part@domain is not a source route). BUT in most cases it gives the end user a better experience, and it matches the Internet Host Requirements. It's a reflection of how RFC 822 systems often misuse source routing even though the Host Requirements [10] talk about it. Either approach works, and so does the middle option of only stripping domain references that point at the local gateway. All of these are conformant to this spec 🌈

  1. If the 822.local-part uses the 822.quoted-string encoding, remove that quoting. If the unquoted 822.local-part has leading space, trailing space, or two adjacent spaces, go to stage II 🫶
  2. If the unquoted 822.local-part has any characters that are not in PrintableString, "{", "}", "*", or "$", go to stage II 🙅‍♀️
  3. Parse the (unquoted) 822.local-part according to the EBNF EBNF.std-or-address-input. Checking of upper bounds shall not happen at this point. If that parse fails, parse the local-part according to the EBNF EBNF.encoded-pn. If that also fails, go to stage II. If it works, the result is a set of type/value pairs ✨
  4. Attach the EBNF.attribute-value syntax (decided by the identified type) to each value, and check that it conforms. If it doesn't, go to stage II 🎀
  5. If the set of attributes forms a valid X.400 address according to X.402, go to step 9. Every form of X.400 address is allowed at this point. Steps 7-8 fill in default attributes for certain types of OR Address 💖
  6. If the set of attributes can't form a mnemonic form of X.400 address, even after adding attributes that can be derived from the EBNF.domain (C, ADMD, PRMD, O, OU), go to stage II 😭
  7. Try to parse EBNF.domain as:

*( domain-syntax "." ) known-domain

Here EBNF.known-domain is the longest possible match in the set of MCGAMs the gateway is using (described in Section 4.2). EBNF.domain-syntax is the restricted domain syntax defined in Section 4.2, and every domain component has to conform to it for the parse to work. If this fails, go to stage II 🧚

For each component, systematically assign the attribute implied by each EBNF.domain-syntax component, in the order: C, ADMD, PRMD, O, OU. Note that if the MCGAM being used identifies an "omitted attribute", then that attribute shall be left out of the systematic assignment. If a new component goes over an upper bound (ADMD: 16; PRMD: 16; O: 64; OU: 32), or it would lead to more than four OUs, then go to stage II with the attributes you've derived so far 💀

The attributes derived in this step (called RHS attributes) get merged with the ones derived from the LHS (step 6). Sometimes not all of the RHS attributes get used. All of the LHS attributes always get used. C will never be in the LHS attributes. If ADMD is in the LHS attributes, only C is taken from the RHS attributes. If PRMD is in the LHS attributes, C and ADMD are taken from the RHS attributes. If O is on the LHS, then C, ADMD, and PRMD (if present) are taken from the RHS attributes. In all other cases, all RHS attributes are taken 🌸

  1. Make sure the set of attributes conforms both to the MTS.ORAddress specification and to the restrictions on this set given in X.400, and that no upper bounds are exceeded for any attribute. If not, go to stage II 👑
  2. Build the OR Address from this information 🎉

STAGE II.

This only happens if the RFC 822 EBNF.822-address is not a valid X.400 encoding. That means the address either points at a recipient on an RFC 822 system, or the encoding of the address is invalid. Either way, these addresses shall be encoded in an X.400 OR Address using a domain defined attribute 🦋

  1. Convert the EBNF.822-address to PrintableString, as specified in Chapter 3.
  2. Generate the "RFC-822" domain defined attribute from this string.
  3. Build the rest of the OR Address in the way described below.

It's not always possible to encode the domain defined attribute because of length restrictions. If the limit is exceeded by a mapping at the MTS level, then the gateway shall reject the message in question. If this happens at the IPMS level, then the outcome depends on the policy being used for IPMS encoding, which is discussed in Section 5.1.3 🙃

Use Stage I, step 8 to generate a set of attributes for building the rest of the address. The administrative equivalence of the mappings will make sure routing through X.400 to a gateway back to RFC 822 works correctly 💜

If Stage I, step 8 doesn't generate a set of attributes, or the address it generates is unroutable, the rest of the OR address is generated like this. The rest of the OR address basically identifies a source route to a gateway from the X.400 side. There are three cases, and each one is handled differently:

SMTP Return Address This shall be set up so that errors come back through the same gateway. So the OR Address of the local gateway shall be used 🔁

IPMS Addresses These are optimised for replying. In general the message may end up anywhere in the X.400 world, so this optimisation picks a gateway that suits the RFC 822 address being converted. The 822.domain the address would be routed to is used to choose an appropriate gateway ✨

In this case it may be useful to use a non-local gateway, which will optimise the reply address. This information may be looked up in gateway tables, in a way that's equivalent to the MCGAM lookup. Because the lookup is so similar, the three MCGAM lookup mechanisms (table, X.500, DNS) are also available for looking this information up. This information is local, and a gateway may insert any appropriate (gateway) OR Address. The longest possible match on the 822.domain decides which gateway gets used. This mechanism is used for any part of the X.400 namespace where it's desirable to name a preferred X.400 gateway in order to optimise routing 🌈

If no mapping is found for the 822.domain, a default value (typically the local gateway's) is used. It is never appropriate to ignore the locally used MCGAMs 🙅‍♀️

SMTP Recipient In principle the RFC 822 and X.400 worlds are fully connected, so there's no technical reason for this situation to happen. In practice it does happen 😭 In some cases, routing may be configured to use X.400 to connect an RFC 822 island to the Internet. The fact that this part of the domain space is to be routed by X.400 rather than staying inside the RFC 822 world shall be configured privately into the gateway in question. X.400 routing shall not use the presence of the RFC-822 DDA to do X.400 routing. The OR address shall then be generated in the same way as for an IPMS address, using the locally available MCGAMs. This case is the reason the global domain to gateway mapping matters, because using that mapping leads to a remote X.400 address, which X.400 routing procedures can route. The information in this mapping shall not be used as the basis for deciding to convert a message from RFC 822 to X.400 🧚

Three examples are given, and none of them has applicable MCGAMs. Ready? 🎀

Example 1: (Address not in "localpart" "@" "domainpart")

@relay.co.uk:userb@host2

         maps to

c=gb; a= ; p=uk.ac; o=mr; dd.rfc-822=(a)relay.co.uk:userb(a)host2;

Example 2: (Address with non printablestring characters)

Tom_Harris@cs.widget.com

         maps to

c=us; a=MCI; P=relay; dd.rfc-822=Tom(u)Harris(a)cs.widget.com;

Example 3: (Address with an entry for alter.net into the OR Address of Preferred Gateway table, pointing to c=gb; A=BTglobal; P=relay)

postmaster@UK.alter.net

         maps to

c=gb; a=BTglobal; P=relay; dd.rfc-822=postmaster(a)UK.alter.net;

4.3.4.1. Heuristic for mapping RFC 822 to X.400 🔮

This heuristic is about the ordering of address components, and it can be used when mapping from RFC 822 to X.400. The attributes might come in inverted or mixed order, so the following heuristic may be applied:

If there is an Organization attribute to the left of any Org Unit attribute, assume that the hierarchy is inverted. This is to make things easier when a user has typed the attributes in reverse hierarchical order. To do this, the gateway shall first map according to the order defined in 4.3.3. If this mapping produces an address that X.400 address verification shows to be invalid, this heuristic may be applied as an alternative to rejecting the address outright. 💅

4.3.5. X.400 -> RFC 822 Basic Address Mapping ✨

Okay so there are two basic cases 💅

  1. RFC 822 addresses encoded in X.400.
  2. "Genuine" X.400 addresses. This MAY include symmetrically encoded RFC 822 addresses.

So when an MTS Recipient OR Address gets interpreted, gatewaying will be selected if there's a single "RFC-822" domain defined attribute present 👀. If that's the case, use mapping A. Otherwise, use mapping B 🎀.

RFC 1327 said this SHALL only be done when the gateway identified is local or otherwise known 🧐. It also called this approach a pragmatic option. Experience has shown it's effective in practice, despite the theoretical problems 💜.

If a gateway wants to map things in a similar way to RFC 1327, but doesn't want this global interpretation (for example, to support an RFC 822 local system that doesn't use global addressing), then it MAY choose a private domain defined attribute, different to "RFC-822". An RFC 1327 gateway might be configurable to work this way 🌸.

Mapping A

  1. Map the domain defined attribute value to ASCII, as defined in Chapter 3, and drop all other attributes.

Mapping B

This is used for X.400 addresses which do not use the explicit RFC 822 encoding 🦋.

  1. For all string encoded attributes, remove any leading or trailing spaces, and replace adjacent spaces with a single space.

The only attribute which is permitted to have zero length is the ADMD. This SHALL be mapped onto a single space.

These transformations are for lookup only. If an EBNF.std-or-address mapping is used as in 4), then the original values SHALL be used.

  1. The numeric country codes MAY be mapped to the two letter values (as defined in ISO 3166). Global mappings are usually only defined in terms of the ISO 3166 codes 🌍.
  2. Noting the hierarchy specified in 4.3.1 and including omitted attributes, determine the maximum set of attributes which have an associated domain specification in the local set of MCGAMs. If no match is found, allocate the domain as described below, and go to step 5. The default domain to be used is the specification of the local gateway. A gateway MAY use other domains according to private mapping tables or heuristics. For example, it MAY choose a domain which it knows to provide a free gateway service to the mapped address 🎁.

In cases where the address refers to an X.400 UA, it is important that the generated domain will correctly route to a gateway. In general, this is achieved by carefully co-ordinating RFC 822 routing with the definition of the MCGAMs, as there is no easy way for the gateway to make this check 😭. One rule that SHALL be used is that domains with only one component will not route to a gateway. If the generated domain does not route correctly, the address is treated as if no match is found.

The gateway MAY also make use of a mapping equivalent to the MCGAM mapping to determine the domain to use. This mapping is done from the OR Address hierarchy. It isn't a global mapping. It's a routing style mapping from the OR Address space, so a best choice domain can be inserted 🧚. This mapping is supported by the three MCGAM lookup mechanisms.

  1. The mapping identified in 3) gives a domain and an OR address prefix. Follow the hierarchy: C, ADMD, PRMD, O, OU. For each successive component below the OR address prefix, which conforms to the syntax EBNF.domain-syntax (as defined in 4.3.1), allocate the next subdomain. At least one attribute of the X.400 address SHALL NOT be mapped onto subdomain, as 822.local-part cannot be null. If there are omitted attributes in the OR address prefix, these will have correctly and uniquely mapped to a domain component. Where there is an attribute omitted below the prefix, all attributes remaining in the OR address SHALL be encoded on the LHS. This is to ensure a reversible mapping. For example, if there is an address /S=XX/O=YY/ADMD=A/C=NN/ and a mapping for /ADMD=A/C=NN/ is used, then /S=XX/O=YY/ is encoded on the LHS 🧩.
  2. If the address contains any attribute not used in mnemonic form, then all of the attributes in the address SHALL be encoded on the LHS in EBNF.std-or-address syntax, as described below.

For addresses of mnemonic form, if the remaining components are personal-name components, conforming to the restrictions of 4.2.1, then EBNF.encoded-pn is derived to form 822.local-part. In other cases, the remaining components are simply encoded as 822.local-part using the EBNF.std-or-address syntax. If necessary, the 822.quoted-string encoding is used. Here are some examples of legal quoting: "a b".c@x; "a b.c"@x. Either form MAY be generated. Generating the latter style is strongly RECOMMENDED 💖.

Four examples are given 🎀.

Example 1: (Address with missing X.400 elements and no specific
mapping rule for "o=sales; a=Master400; C=it", where a mapping exists
for a=master400; C=it;)

S=Support; O=sales;  A=Master400; C=it;

       maps to

/S=Support/o=sales/@Master400.it
Example 2: (Address with illegal characters in RFC822 generated
domain if default hierarchical translation (specific mapping rule is
existing for c=fr; a=atlas; p=autoroutes) is used)

S=renseignements; O=Region Parisienne; P=autoroutes; A=atlas; C=fr;

       maps to

"/S=renseignements/o=Region Parisienne/"@autoroutes.fr
Example 3:  (Address containing elements not mappable into RFC822
local part)

S=Rossi; DD.cap=20100; DD.ph1=Via Larga 11; DDA.city=Milano;
A=PtPostel; C=it;

       maps to

"/DD.cap=20100/DD.ph1=Via Larga
11/DD.city=Milano/S=Rossi/"@ptpostel.it
Example 4:   (Address with an entry for A=ATT; C=us; into the domain
of Preferred Gateway table, pointing to attmail.com)

G=Andy; S=Wharol; O=MMNY; A=ATT; C=us;

      maps to

/G=Andy/S=Wharol/O=MMNY@attmail.com

4.4. Repeated Mappings 🔁

There are two types of repeated mapping:

  1. A recursive mapping, where the repeat is within one gateway.
  2. A source route, where the repetition occurs across multiple gateways.

4.4.1. Recursive Mappings

It's possible to supply an address that's recursive at a single gateway. For example:

              C          = "XX"
              ADMD       = "YY"
              O          = "ZZ"
              "RFC-822"  = "Smith(a)ZZ.YY.XX"

This gets mapped first to an RFC 822 address, and then back to the X.400 address:

              C          = "XX"
              ADMD       = "YY"
              O          = "ZZ"
              Surname    = "Smith"

In some situations this type of recursion MAY be frequent 👀. Where it happens, it's important that no unnecessary protocol conversion occurs. That keeps service loss to a minimum 🫶.

4.4.2. Source Routes

The mappings defined are symmetrical and reversible across a single gateway ✨. The symmetry is especially useful for (mail exploder type) distribution list expansion. For example, an X.400 user sends to a list on an RFC 822 system that they belong to. The received message will have the originator and any 3rd party X.400 OR Addresses in the correct format (rather than doubly encoded). In cases (X.400 or RFC 822) where there's common agreement on gateway identification, this will apply to multiple gateways 🌈.

When a message traverses multiple gateways, the mapping will always be reversible, so a reply can be generated that correctly reverses the path. In many cases the mapping will also be symmetrical, which will look clean to the end user 💅. For example, if countries "AB" and "XY" have RFC 822 networks but are interconnected by X.400, the following MAY happen. The originator specifies:

          Joe.Soap@Widget.PTT.XY

This gets routed to a gateway, which generates:

          C               = "XY"
          ADMD            = "PTT"
          PRMD            = "Griddle MHS Providers"
          Organization    = "Widget Corporation"
          Surname         = "Soap"
          Given Name      = "Joe"

This is then routed to another gateway, where the mapping is reversed to give:

          Joe.Soap@Widget.PTT.XY

Here, using the gateway is totally transparent 🦋.

Mappings will only be symmetrical where mapping equivalences are defined. In other cases the reversibility matters more, because RFC 822 and X.400 services are (far too often) partitioned 😤.

The syntax MAY be used to source route. THIS IS STRONGLY DISCOURAGED 🚫. For example:

      X.400 -> RFC 822  -> X.400

      C             = "UK"
      ADMD          = "Gold 400"
      PRMD          = "UK.AC"
      "RFC-822"     = "/PN=Duval/DD.Title=Manager/(a)Inria.ATLAS.FR"

This will be sent to an arbitrary UK Academic Community gateway by X.400. Then it will be sent by JNT Mail to another gateway determined by the domain Inria.ATLAS.FR (FR.ATLAS.Inria). That gateway will then derive the X.400 OR Address:

      C             = "FR"
      ADMD          = "ATLAS"
      PRMD          = "Inria"
      PN.S          = "Duval"
      "Title"       = "Manager"

Similarly:

RFC 822 -> X.400 -> RFC 822

"/RFC-822=jj(a)seismo.css.gov/PRMD=AC/ADMD=BT/C=GB/"@monet.berkeley.edu

This will be sent to monet.berkeley.edu by RFC 822, then to the AC PRMD by X.400, and then to jj@seismo.css.gov by RFC 822 🧚.


4.5. Directory Names 📇

Directory Names are an optional part of OR Name, alongside OR Address. The RFC 822 addresses are mapped onto the OR Address component. Since there's no functional mapping for the Directory Name on the RFC 822 side, a textual mapping is used. There is no requirement for reversibility in terms of the goals of this specification. There MAY be some loss of functionality for third party recipients where only a directory name is given, but that seems better than the big extra complexity of adding a full mapping for Directory Names 🙈.

The Directory Name SHALL be represented within an RFC 822 comment using the compatible formats of RFC 1484 or RFC 1485. It is RECOMMENDED that the directory string format of RFC 1485 is used [24]. The User Friendly Name form of RFC 1484 MAY be used [25] 🎀.


4.6. MTS Mappings 💌

The basic mappings at the MTS level are:

   1) SMTP originator ->
                 MTS.PerMessageSubmissionFields.originator-name
      MTS.OtherMessageDeliveryFields.originator-name ->
                 SMTP originator

   2) SMTP recipient ->
                 MTS.PerRecipientMessageSubmissionFields
      MTS.OtherMessageDeliveryFields.this-recipient-name ->
                 SMTP recipient

SMTP recipients and return addresses are encoded as EBNF.822-address 📮.

The MTS Originator is always encoded as MTS.OriginatorName, which maps onto MTS.ORAddressAndOptionalDirectoryName, which in turn maps onto MTS.ORName 🧁.

4.6.1. RFC 822 -> X.400 MTS Mappings

okay so this is the direction where an SMTP message heads into the X.400 world 💌✨. For the originator, you use the basic ORAddress mapping to generate MTS.PerMessageSubmissionFields.originator-name (MTS.ORName), and you do it without a DirectoryName 🙅‍♀️.

For recipients, every component of MTS.PerRecipientMessageSubmissionFields gets set up like this:

  • recipient-name: derived from the SMTP recipient using the basic ORAddress mapping 📬
  • originator-report-request: this MAY be set to "delivery-report", or set according to the SMTP extensions in Appendix A 🔔
  • explicit-conversion: this optional component gets omitted, because this service isn't needed 🙈
  • extensions: the default value (no extensions) is used 💤

4.6.2. X.400 -> RFC 822 MTS Mappings

the main job here is to generate the SMTP originator and recipients 🎀. But the X.400 side has info that just doesn't have an SMTP equivalent, so we add new RFC 822 fields for the MTS Originator and Recipients to carry it. Whatever gets dropped at the SMTP level lives in those fields instead. And sometimes a (positive) delivery report gets generated too 📨✨.

4.6.2.1. SMTP Mappings

use the basic ORAddress mapping to build the SMTP originator (return address) from MTS.OtherMessageDeliveryFields.originator-name (MTS.ORName) 💌. If MTS.ORName.directory-name is present, it gets discarded. (Heads up, it'll still be shown to the user, as described in 4.6.2.2 👀.)

The mapping uses the MTA level information and maps each value of MTA.PerRecipientMessageTransferFields.recipient-name, where the responsibility bit is set, onto an SMTP recipient 🎯.

Note: The SMTP recipient is conceptually generated from MTS.OtherMessageDeliveryFields.this-recipient-name. You do this by taking MTS.OtherMessageDeliveryFields.this-recipient-name and generating an SMTP recipient with the basic ORAddress mapping, discarding MTS.ORName.directory-name if present. BUT if you followed this model exactly, there would be no way to have multiple SMTP recipients on one message. That's unacceptable 😤, so layering gets violated.

4.6.2.2. Generation of RFC 822 Headers

not all per-recipient info can survive the trip at the SMTP level 😭. So two new RFC 822 headers get created to carry it to the RFC 822 recipient: "X400-Originator:" and "X400-Recipients:" 🌸.

The "X400-Originator:" field gets set to the same value as the SMTP originator 💅. On top of that, if MTS.OtherMessageDeliveryFields.originator-name (MTS.ORName) has MTS.ORName.directory-name, then that Directory Name SHALL be represented in an 822.comment 🧚.

Recipient names, taken from each value of MTS.OtherMessageDeliveryFields.this-recipient-name and MTS.OtherMessageDeliveryFields.other-recipient-names, are made available to the RFC 822 user through the "X400-Recipients:" field 💜. Taking recipients at the MTS level means disclosure of recipients gets handled correctly, which is very mature of it 🫶. The catch is that it clashes with wanting to optimise mail transfer 😩. There's no problem when disclosure of recipients is allowed. There's also no problem if there's only one RFC 822 recipient, since the "X400-Recipients" field only gets one address then.

The problem is when there are multiple RFC 822 recipients AND disclosure of recipients is prohibited 🚫. In that case, discard the per-recipient information.

If any MTS.ORName.directory-name is present, it SHALL be represented in an 822.comment 🌈.

If MTS.OtherMessageDeliveryFields.orignally-intended-recipient-name is present, then there has been a redirection, or a distribution list expansion 🔀. Distribution list expansion is a per-message option, and its info is represented by the "DL-Expansion-History:" field described in Section 5.3.6. Other information gets represented in an 822.comment attached to MTS.OtherMessageDeliveryFields.this-recipient-name. The message MAY be delivered to different RFC 822 recipients, so several addresses in the "X400-Recipients:" field may have comments like this. The non-commented recipient is the RFC 822 recipient ✨. The EBNF of the comment is defined by redirect-comment:

      redirect-comment  = redirect-first *( redirect-subsequent )

      redirect-first = "Originally To:"  mailbox  "Redirected on"
         date-time "To:"  redirection-reason

      redirect-subsequent = mailbox  "Redirected Again on"
         date-time "To:"  redirection-reason

      redirection-history-item = "intended recipient" mailbox
         "redirected to"  redirection-reason
         "on" date-time

      redirection-reason =
         "Recipient Assigned Alternate Recipient"
         / "Originator Requested Alternate Recipient"
         / "Recipient MD Assigned Alternate Recipient"
         / "Directory Look Up"
         / "Alias"

It's derived from MTA.PerRecipientMessageTransferFields.extension.redirection-history 🔍. The values come from the X.400(92) Implementor's guide (Version 13, July 1995). The first three values are in X.400(88). The fourth value is in X.400(92), but it's named "recipient-directory-substitution-alternate-recipient" 🤓. Here's an example with two redirects:

X400-Recipients: postmaster@widget.com (Originally To:
          sales-manager@sales.widget.com
      Redirected on Thu, 30 May 91 14:39:40 +0100
          To: Originator Requested Alternate Recipient
          postmaster@sales.widget.com
      Redirected Again on Thu, 30 May 91 14:41:20 +0100
          To: Recipient MD Assigned Alternate Recipient)

Also, the following per-recipient services from MTS.OtherMessageDeliveryFields.extensions get represented in comments if they're used 💁‍♀️. None of these services can be provided on RFC 822 networks, so in general they're informative strings attached to other MTS recipients. Some have defined string values. For the rest, the string value SHALL be chosen by the implementor. And if the parameter has a default value, no comment SHALL be inserted when the parameter has that default value 🙅‍♀️.

  • requested-delivery-method
  • physical-forwarding-prohibited: "(Physical Forwarding Prohibited)" 🚚
  • physical-forwarding-address-request: "(Physical Forwarding Address Requested)" 📦
  • physical-delivery-modes
  • registered-mail-type
  • recipient-number-for-advice
  • physical-rendition-attributes
  • physical-delivery-report-request: "(Physical Delivery Report Requested)" 📋
  • proof-of-delivery-request: "(Proof of Delivery Requested)" ✅

4.6.2.3. Delivery Report Generation

if SMTP is used, the behaviour is specified in Appendix A 📮. In other cases, if MTA.PerRecipientMessageTransferFields.per-recipient-indicators requires a positive delivery notification, the gateway SHALL generate it. Supplementary Information SHALL be set to indicate that the report is gateway generated, and this info SHALL include the name of the gateway that generated the report 🫡.

4.6.3. Message IDs (MTS)

there's a mapping from 822.msg-id to MTS.MTSIdentifier ✨. The reverse mapping isn't needed, because MTS.MTSIdentifier always gets mapped onto new RFC 822 fields. The value of MTS.MTSIdentifier.local-part helps with correlating gateway errors 🔎.

To map from 822.msg-id, apply the standard mapping to 822.msg-id to generate an MTS.ORAddress. The Country, ADMD, and PRMD components of that get used to build MTS.MTSIdentifier.global-domain-identifier. MTS.MTSIdentifier.local-identifier is set to the 822.msg-id, including the braces "<" and ">" 🌷. If this string is longer than MTS.ub-local-id-length (32), it gets truncated to that length ✂️.

The reverse mapping isn't used in this specification. It would apply where MTS.MTSIdentifier.local-identifier is of syntax 822.msg-id, and it algorithmically identifies MTS.MTSIdentifier 🧠.

4.7. IPMS Mappings

all RFC 822 addresses are assumed to use the 822.mailbox syntax 💅. This includes all 822.comments associated with the lexical tokens of the 822.mailbox. In the IPMS, OR Names are encoded as MTS.ORName. This is used within the IPMS.ORDescriptor, IPMS.RecipientSpecifier, and IPMS.IPMIdentifier. An asymmetrical mapping is defined between these components 🔄.

4.7.1. RFC 822 -> X.400

this is how you derive IPMS.ORDescriptor from an RFC 822 address 🎀.

  1. Take the address and extract an EBNF.822-address. Any source routing SHALL be removed. This can be derived trivially from either the 822.addr-spec or 822.route-addr syntax. It gets mapped to MTS.ORName as described above, and used as IMPS.ORDescriptor.formal-name 🗺️.
  2. A string SHALL be built consisting of (if present):
    • The 822.phrase component, if the 822.address is an 822.phrase 822.route-addr construct.
    • Any 822.comments, in order, retaining the parentheses.

This string is then encoded into T.61 using a human oriented mapping (as described in Section 3.5) 💭. If the string is not null, it gets assigned to IPMS.ORDescriptor.free-form-name 💖.

  1. IPMS.ORDescriptor.telephone-number is omitted 📵.

If IPMS.ORDescriptor is being used in IPMS.RecipientSpecifier, then IPMS.RecipientSpecifier.reply-request and IPMS.RecipientSpecifier.notification-requests are set to default values (false and none) 🙌.

If the 822.group construct is present, any included 822.mailbox is encoded as above to generate a separate IPMS.ORDescriptor. The 822.group is mapped to T.61 (as described in Section 3.5), and an IPMS.ORDescriptor with only a free-form-name component built from it gets created 🌈.

4.7.2. X.400 -> RFC 822 🎀

Okay bestie, time to map an X.400 IPMS.ORDescriptor back into an RFC 822 address 💌 In the basic case, where IPMS.ORDescriptor.formal-name is present, you do this:

1. Encode IPMS.ORDescriptor.formal-name (MTS.ORName) as EBNF.822-address.

2a. If IPMS.ORDescriptor.free-form-name is present, convert it to ASCII or T.61 (Section 3.5), and use this as the 822.phrase component of 822.mailbox using the 822.phrase 822.route-addr construct.

2b. If IPMS.ORDescriptor.free-form-name is absent. If EBNF.822-address is parsed as 822.addr-spec use this as the encoding of 822.mailbox. If EBNF.822-address is parsed as 822.route 822.addr-spec, then an 822.phrase taken from 822.local-part is added. ✨

3 If IPMS.ORDescriptor.telephone-number is present, this is placed in an 822.comment, with the string "Tel ". The normal international form of number is used. For example:

 (Tel +44-181-333-7777)

4. If IPMS.ORDescriptor.formal-name.directory-name is present, then a text representation is placed in a trailing 822.comment.

5. If IPMS.RecipientSpecifier.report-request has any non-default values, then an 822.comment "(Receipt Notification Requested)", and/or "(Non Receipt Notification Requested)", and/or "(IPM Return Requested)" may be appended to the address. "(Receipt Notification Requested)" may be used to infer "(Non Receipt Notification Requested)". The effort of correlating P1 and P2 information is too great to justify the gateway sending Receipt Notifications. 🙈

Okay, real talk on this one. In RFC 1327, inclusion of these comments was mandatory. Experience has shown that the clutter and confusion caused to RFC 822 users does not justify the information conveyed. Implementors are recommended to not include these comments. Unless an application is found where retention of these comments is desirable, they will be dropped from the next version. 💀

6. If IPMS.RecipientSpecifier.reply-request is True, an 822.comment "(Reply requested)" is appended to the address.

If IPMS.ORDescriptor.formal-name is absent, IPMS.ORDescriptor.free-form-name is converted to ASCII (see section 3.5), and used as 822.phrase within the RFC 822 822.group syntax. For example:

Free Form Name ":" ";"

Steps 3-6 are then followed. 🦋


4.7.3. IP Message IDs 🧚

There is a need to map both ways between 822.msg-id and IPMS.IPMIdentifier. This allows for X.400 Receipt Notifications, Replies, and Cross References to reference an RFC 822 Message ID, which is preferable to a gateway generated ID. A reversible and symmetrical mapping is defined. This provides fully reversible mappings when messages pass multiple times across the X.400/RFC 822 boundary. This is so important, the whole thing depends on it.

An important issue with messages identifiers is mapping to the exact form, as many systems use these ids as uninterpreted keys. The use of table driven mappings is not always symmetrical, particularly in the light of alternative domain names, and alternative management domains. For this reason, a purely algorithmic mapping is used. A mapping which is simpler than that for addresses can be used for two reasons:

  • There is no major requirement to make message IDs "natural"
  • There is no issue about being able to reply to message IDs. (For addresses, creating a return path which works is more important than being symmetrical).

The mapping works by defining a way in which message IDs generated on one side of the gateway can be represented on the other side in a systematic manner. The mapping is defined so that the possibility of clashes is low enough to be treated as impossible. 🌈

4.7.3.1. 822.msg-id represented in X.400

IPMS.IPMIdentifier.user is omitted. The IPMS.IPMIdentifier.user-relative-identifier is set to a printable string encoding of the 822.msg-id with the angle braces ("<" and ">") removed. The upper bound on this component is 64. The options for handling this are discussed in Section 5.1.3.

4.7.3.2. IPMS.IPMIdentifier represented in RFC 822

The 822.domain of 822.msg-id is set to the value "MHS". The 822.local-part of 822.msg-id is constructed by building a string of syntax EBNF.id-loc from IPMS.IPMIdentifier.

id-loc ::= [ printablestring ] "*"  [ std-or-address ]

EBNF.printablestring is the IPMS.IPMIdentifier.user-relative-identifier, and EBNF.std-or-address being an encoding of the IPMS.IPMIdentifier.user derived according to this specification. 822.local-part is derived from EBNF.id-loc, if necessary using the 822.quoted-string encoding. For example:

<"147*/S=Dietrich/O=Siemens/ADMD=DBP/C=DE/"@MHS>

4.7.3.3. 822.msg-id -> IPMS.IPMIdentifier

If the 822.local-part can be parsed as:

[ printablestring ] "*"  [ std-or-address ]

and the 822.domain is "MHS", then this ID was X.400 generated. If EBNF.printablestring is present, the value is assigned to IPMS.IPMIdentifier.user-relative-identifier. If EBNF.std-or-address is present, the OR Address components derived from it are used to set IPMS.IPMIdentifier.user.

Otherwise, this is an RFC 822 generated ID. In this case, set IPMS.IPMIdentifier.user-relative-identifier to a printable string encoding of the 822.msg-id without the angle braces and omit IPMS.IPMID.user. 🍓

4.7.3.4. IPMS.IPMIdentifier -> 822.msg-id

If IPMS.IPMIdentifier.user is absent, and IPMS.IPMIdentifier.user-relative-identifier mapped to ASCII and angle braces added parses as 822.msg-id, then this is an RFC 822 generated ID.

Otherwise, the ID is X.400 generated. Use the IPMS.IPMIdentifier.user to generate an EBNF.std-or-address form string. Build the 822.local-part of the 822.msg-id with the syntax:

[ printablestring ] "*"  [ std-or-address ]

The printablestring is taken from IPMS.IPMIdentifier.user-relative-identifier. Use 822.quoted-string if necessary. The 822.msg-id is generated with this 822.local-part, and "MHS" as the 822.domain. 💜

4.7.3.5. Phrase form

In "In-Reply-To:" and "References:", the encoding 822.phrase may be used as an alternative to 822.msg-id. To map from 822.phrase to IPMS.IPMIdentifier, assign IPMS.IPMIdentifier.user-relative-identifier to the phrase. When mapping from IPMS.IPMIdentifier for "In-Reply-To:" and "References:", if IPMS.IPMIdentifier.user is absent and IPMS.IPMIdentifier.user-relative-identifier does not parse as 822.msg-id, generate an 822.phrase rather than adding the domain MHS. 🫶

4.7.3.6. RFC 987 backwards compatibility

The mapping defined here is different to that used in RFC 987, as the RFC 987 mapping lead to changed message IDs in many cases. Fixing the problems is preferable to retaining backwards compatibility. An implementation of this standard may recognise message IDs generated by RFC 987. This is not recommended.

RFC 987 generated encodings may be recognised as follows. When mapping from X.400 to RFC 822, if the IPMS.IPMIdentifier.user-relative-identifier is "RFC-822" the id is RFC 987 generated. When mapping from RFC 822 to X.400, if the 822.domain is not "MHS", and the 822.local-part can be parsed as:

[ printablestring ] "*"  [ std-or-address ]

then it is RFC 987 generated. In each of these cases, it is recommended to follow the RFC 987 rules. 👑


Chapter 5 - Detailed Mappings ✨

This chapter specifies detailed mappings for the functions outlined in Chapters 1 and 2. It makes extensive use of the notations and mappings defined in Chapters 3 and 4.

5.1. RFC 822 -> X.400: Detailed Mappings

The mapping of RFC 822/MIME messages to X.400 InterPersonal Messages is described in Sections 5.1.1 to 5.1.7. Mapping of NOTARY format delivery status notifications, which are all messages of type multipart/report and subtype delivery-status-notifications to X.400 delivery reports is covered in Section 5.1.8. 🌸

5.1.1. Basic Approach

A single IP Message is generated from an RFC 822 message. The RFC 822 headers are used to generate the IPMS.Heading.

Some RFC 822 fields cannot be mapped onto a standard IPM Heading field, and so an extended field is defined in Section 5.1.2. This is then used for fields which cannot be mapped onto existing services.

The message is submitted to the MTS, and the services required can be defined by specifying MTS.MessageSubmissionEnvelope. A few parameters of the MTA Abstract service are also specified, which are not in principle available to the MTS User. Use of these services allows RFC 822 MTA level parameters to be carried in the analogous X.400 service elements. The advantages of this mapping far outweigh the layering violation. 🔥

5.1.2. X.400 Extension Field

An IPMS Extension is defined:

rfc-822-field HEADING-EXTENSION
              VALUE RFC822FieldList
              ::= id-rfc-822-field-list


RFC822FieldList ::= SEQUENCE OF RFC822Field

RFC822Field ::= IA5String

The Object Identifier id-rfc-822-field-list is defined in Appendix D.

To encode any RFC 822 Header using this extension, an RFC822Field element is built using the 822.field omitting the trailing CRLF (e.g., "Fruit-Of-The-Day: Kiwi Fruit"). All fields shall be unfolded. There shall be no space before the ":". The reverse mapping builds the RFC 822 field in a straightforward manner. This RFC822Field is appended to the RFC822FieldList, which is added to the IPM Heading as an extension field. 🧚‍♀️✨

5.1.3. Generating the IPM ✨

okay so this is where the IPM gets built, bestie 🎀 The IPM (IPMS Service Request) is generated following the rules in this section. The IPMS.IPM.body is generated from the RFC 822 message body in the way described in Section 5.1.5.

If no specific 1988 features are used, the IPM comes out encoded as content type 2. If they are used, it's encoded as content type 22 instead. And content type 22 is always the case if extension heading fields get generated 💅

Now, upper bounds 🧐 The rule is to truncate fields to the upper bounds specified in X.400. This keeps things working for UAs that enforce upper bounds, but it can sometimes throw away useful info. It also hits some fields harder than others. Truncating an OR Address component that's used to route a reply is way more of a problem than truncating a Free Form Name 💀 And if the Free Form name does get truncated, it has to be done so that it doesn't break RFC 822 comments or RFC 1522 encoding.

Note: This approach removes a choice of options given in RFC 1327, based on operational experience.

The rest of this section is about IPMS.IPM.heading (IPMS.Heading) 🦋 The only mandatory component of IPMS.Heading is the IPMS.Heading.this-IPM (IPMS.IPMIdentifier), and the gateway generates a default for it. Except for "Received:", the values of multiple fields get merged. So if there are two "To:" fields, the mailboxes from both get merged into one list that's used for IPMS.Heading.primary-recipients. Here's how the standard RFC 822 headers map over:

  • Date: → Ignore (handled at MTS level) 🕰️
  • Received: → Ignore (handled at MTA level)
  • Message-Id: → Mapped to IPMS.Heading.this-IPM. For this one, and every other field containing 822.msg-id, the mappings from Chapter 4 are used for each 822.msg-id. 🆔
  • From: → If Sender: is present, this maps to IPMS.Heading.authorizing-users. If not, it maps to IPMS.Heading.originator. For this one, and any other components containing addresses, the mappings from Chapter 4 are used for each address. 💌
  • Sender: → Mapped to IPMS.Heading.originator. Ngl, this one's a bit messy, because X.400 doesn't have the same From/Sender distinction as RFC 822. So this mapping isn't always natural and can lead to unexpected results in some cases 🙈
  • Reply-To: → Mapped to IPMS.Heading.reply-recipients.
  • To: → Mapped to IPMS.Heading.primary-recipients.
  • Cc: → Mapped to IPMS.Heading.copy-recipients.
  • Bcc: → Mapped to IPMS.Heading.blind-copy-recipients if there's at least one BCC: recipient. If there are no recipients in this field, it either gets mapped to a zero length sequence, or it gets mapped to a single recipient that has a free form name "BCC" and no other addressing information. This alternate treatment is allowed because some X.400 systems can't handle a zero length sequence of addresses 😭
  • In-Reply-To: → If there's one value, it gets mapped to IPMS.Heading.replied-to-IPM, using the 822.phrase or 822.msg-id mapping as appropriate. If there are multiple values, that can't work, because the X.400 heading is single valued. So in that case no IPMS.Heading.replied-to-IPM is generated, and the values get mapped to IPMS.Heading.related-IPMs, along with any values from a "References:" field 🧩
  • References: → Mapped to IPMS.Heading.related-IPMs.
  • Keywords: → Mapped onto a heading extension. 🏷️
  • Subject: → Mapped to IPMS.Heading.subject. The field-body uses the human oriented mapping referenced in Section 3.3.4.
  • Comments: → Mapped onto a heading extension. 💬

This is a change from 1327. That one specified generating an IPMS.BodyPart of type IPMS.IA5TextBodyPart with IPMS.IA5TextBodyPart.parameters.repertoire set to the default (ia5), containing the values of the fields, preceded by the string "Comments: ", and that this body part should come before the other one. Experience has shown that this complexity isn't justified 🙄 The text is kept anyway, to make backwards compatibility easier.

  • Encrypted: → Mapped onto a heading extension. 🔐
  • Resent-* → Mapped onto a heading extension.

Note that it would be possible to use a ForwardedIPMessage for these fields. But the semantics are (arguably) slightly different, and it's probably not worth the effort 🤷‍♀️

  • Content-Language: → This field is defined in RFC 1766 [7]. Map the first two characters of each value onto the IPM Languages extension. If any comments or values longer than two characters occur, a header extension shall also be generated. 🌍
  • Other Fields → In particular X-* fields, and "illegal" fields in common usage (e.g., "Fruit-of-the-day:") are mapped onto a heading extension, unless they're covered by another section or appendix of this specification. The same treatment applies to RFC 822 fields whose content doesn't conform to RFC 822 (e.g., a Date: field with unparseable syntax). 🍓

The mapping for the following headings is defined in RFC 2157, so you'll need to go check there 🧚

MIME-Version: 5
Content-Transfer-Encoding:
Content-Type
Content-ID
Content-Description

5.1.4. Generating the IPM Body

Generation of the IPM Body is defined in RFC 2157. Go read that one, babe 📖

5.1.5. Mappings to the MTS Abstract Service 🚀

The MTS.MessageSubmissionEnvelope is made up of MTS.PerMessageSubmissionFields and MTS.PerRecipientMessageSubmissionFields. The mandatory parameters get defaulted like this:

  • MTS.PerMessageSubmissionFields.originator-name → This is always generated from SMTP, as defined in Chapter 4.
  • MTS.PerMessageSubmissionFields.content-type → Set to the value implied by the encoding of the IPM (2 or 22).
  • MTS.PerRecipientMessageSubmissionFields.recipient-name → These will always be supplied from SMTP, as defined in Chapter 4.

Optional components are omitted, and default components get defaulted. That means disclosure of recipients is prohibited and conversion is allowed. There are two exceptions to the defaulting. For MTS.PerMessageSubmissionFields.per-message-indicators, the following settings are made:

  • Alternate recipient is allowed, because it seems desirable to maximise the opportunity for (reliable) delivery. 📬

If SMTP is used, Appendix A shall be followed when setting these parameters.

The trace is set to indicate conversion (described below). The encoded information types in the trace are derived from the message generated by the gateway, and shall reflect all body parts (including those in enclosed messages). On top of that, it shall include the Encoded Information Type "eit-mixer", which is defined in Appendix D. The presence of that EIT tells the X.400 recipient that a MIXER conversion has happened ✨

MTS.PerMessageSubmissionFields.original-encoded-information-types will include all of the values used in the trace, unless RFC 2157 specifies otherwise.

Now, this type of conversion can stop the normal loop detection from working in certain circumstances, and it opens up the possibility of gateway loops 😱 So MIXER gateways shall count the number of MIXER conversions they make. If that count exceeds five in one direction, the message shall be treated as if a loop has been detected. Periodt 🔁

The MTS.PerMessageSubmissionFields.content-correlator is encoded as IA5String, and contains the Subject:, Message-ID:, Date:, and To: fields (if present), in that order. That includes the strings "Subject:", "Date:", "To:", and "Message-ID:", plus appropriate folding so the field reads nicely. It gets truncated to MTS.ub-content-correlator-length (512) characters. On top of that, if there's a "Subject:" field, the MTS.PerMessageSubmissionFields.content-identifier is set to a printable string representation of its contents. If that string is longer than MTS.ub-content-id-length (16), it gets truncated to 13 characters with "..." appended. Both get used, because the content correlator has a much larger upper bound, and the content id is available in X.400(1984) 🫶

5.1.6. Mappings to the MTA Abstract Service ✨

okay bestie, there are a few reasons we need to map straight onto the MTA Abstract Service 💅

  • so the MTS Message Identifier can be generated from the RFC 822 Message-ID:
  • so the submission date can be generated from the 822.Date
  • to prevent loss of trace information 🧾
  • to prevent RFC 822/X.400 looping caused by distribution lists or redirects 🔁

here are the mappings we're defining 🦋

Message-Id: if this is present and no Resent: fields are present, the MTA.PerMessageTransferFields.message-identifier MAY be generated from it, using the mappings described in Chapter 4 🎀

ngl this mapping arguably makes messages that don't conform to US GOSIP (1984 version only) 😭 which says:

6.7.e MPDU Identifier Validation

(1) Validation of the GlobalDomainIdentifier component of the MPDU
Identifier is performed on reception of a message (i.e. the result
of a TRANSFER.Indication).

(2) The country name should be known to the validating domain, and
depending on the country name, validation of the

ADMD name may also be possible.

(3) Additional validation of the GlobalDomainIdentifier is
performed against the corresponding first entry in the
TraceInformation. If inconsistencies are found during the
comparison, a non-delivery notice with the above defined reason
and diagnostic code is generated.

(4) A request will be generated to the CCITT for a more meaningful
diagnostic code (such as "InconsistentMPUTIdentifier").

this only applies to ADMDs, and it's in the 1984 version, not the 1988 version 🙈 conformance depends on how you interpret "inconsistency". the spec makes the most sensible choice, so it isn't changing in the update from RFC 1327 🫶

Date: (and Resent-Date:) if one or more Resent-Date: fields are present, the most recent Resent-Date: field SHALL be used instead of the Date: field in the following description 📅

the Date: field sets the first component of MTA.PerMessageTransferFields.trace-information (MTA.TraceInformationElement). the SMTP originator gets mapped into an MTS.ORAddress, and that's used to derive MTA.TraceInformationElement.global-domain-identifier. the optional components of MTA.TraceInformationElement.domain-supplied-information are omitted, and the mandatory components get set like this:

  • MTA.DomainSuppliedInformation.arrival-time: this is set to the date derived from Date: ⏰
  • MTA.DomainSuppliedInformation.routing-action: set to relayed.

the first element of MTA.PerMessageTransferFields.internal-trace-information is generated in an analogous manner, although it can be dropped later in certain circumstances (see the procedures for "Received:"). the MTA.InternalTraceInformationElement.mta-name is derived from the 822.domain in the 822 MTS Originator address 🧚

Received: all RFC 822 trace is used to derive MTA.PerMessageTransferFields.trace-information and MTA.PerMessageTransferFields.internal-trace-information 🔍 processing of Received: lines follows processing of Date:, and it's done from the bottom to the top of the RFC 822 header (i.e., in chronological order). when other trace elements (in particular X400-Received:) are processed, the relative ordering (top to bottom of the header) SHALL be retained correctly 💅

the initial element of MTA.PerMessageTransferFields.trace-information SHALL be generated from Date: as described above, unless the message has previously been in X.400. then it gets derived from the X.400 trace information 🌈

for each Received: field, the following processing SHALL be done:

  1. if the "by" part of the received is present and there's an available MCGAM that can map this domain, use it to derive an MTS.GlobalDomainIdentifier. otherwise, MTS.GlobalDomainIdentifier is set from local information.
  2. if this is different from the one in the last element of MTA.PerMessageTransferFields.trace-information (MTA.TraceInformationElement.global-domain-identifier), create a new MTA.TraceInformationElement, and optionally remove MTA.PerMessageTransferFields.internal-trace-information. requirements on trace stripping are discussed below.
  3. then add a new element (MTA.InternalTraceInformationElement) to MTA.PerMessageTransferFields.internal-trace-information, creating this if needed. this SHALL be done, even if nter-MD trace is created. the MTA.InternalTraceInformationElement.global-domain-identifier is set to the value derived. the MTA.InternalTraceInformationElement.mta-supplied-information (MTA.MTASuppliedInformation) is set like this:
    • MTA.MTASuppliedInformation.arrival-time: derived from the date of the Received: line 🕰️
    • MTA.MTASuppliedInformation.routing-action: set to relayed

the MTA.InternalTraceInformationElement.mta-name is taken from the "by" component of the Received: field, truncated to MTS.ub-mta-name-length (32). for example:

   Received: from computer-science.nottingham.ac.uk by
      vs6.Cs.Ucl.AC.UK via Janet with NIFTP  id aa03794;
      28 Mar 89 16:38 GMT

which generates the string vs6.Cs.Ucl.AC.UK 🎀

the gateway SHALL add in a single element of trace information, reflecting the gateway's local information and the time of conversion. the MTA.InternalTraceInformationElement.mta-supplied-information (MTA.MTASuppliedInformation) is set like this:

  • MTA.DomainSuppliedInformation.arrival-time: set to the time of conversion
  • MTA.DomainSuppliedInformation.routing-action: set to relayed
  • MTA.AdditionalAcctions.converted-encoded-information-types: set to the correct set of EITs for the message that the gateway generates

this trace element will therefore reflect gateway operation as a conversion 🔄

this trace generation will often lead to a lot of trace information that doesn't reflect X.400 transfers 📚 stripping some of this trace MAY be necessary in some operational environments. this stripping SHALL be considered a function of the associated X.400 MTA, and not of the MIXER gateway 🫶


5.1.7. Mapping New Fields

this spec defines a bunch of new fields for Reports, Notifications and IP Messages 🎀 a gateway conforming to this specification SHALL map all of these fields to X.400, except as defined below.

mapping two extended fields is super important, because it prevents looping 🔁 DL-Expansion-History: is mapped to MTA.PerMessageTransferFields.extensions.dl-expansion-history. X400-Received: SHALL be mapped to MTA.PerMessageTransferFields.trace-information and MTA.PerMessageTransferFields.internal-trace-information. when X400-Received: is present, the usual mapping of Date: to generate the first element of trace SHALL NOT be done. that's because the message came from X.400, so the first element of trace can be taken from the first X400-Received: 🧠

the following fields SHALL NOT be mapped, and SHALL be

  • Discarded-X400-MTS-Extensions:
  • Message-Type:
  • Discarded-X400-IPMS-Extensions:
  • X400-Content-Type:
  • X400-Originator:
  • X400-Recipients:
  • X400-MTS-Identifier: mapping this field would be useful in some circumstances, but very dangerous in others (e.g., following an internet list expansion). therefore it is not mapped. 💀

5.1.8. Mapping Delivery Status Notifications to X.400

5.1.8.1. Basic Model

internet mail delivery status notifications (DSN) get mapped to X.400 delivery reports 📬 with message mapping, information without a mapping is carried by an IPM Extension. that can't be done for delivery reports though 😤 so two mechanisms are used for information that doesn't have a direct mapping.

the first mechanism is to define extensions, which let all of the DSN information be carried in the delivery report. this isn't completely satisfactory, for two reasons:

  1. user defined extensions are supported by the ISO version of the standard, but not the CCITT one. therefore, implementation support for these extensions won't be universal.
  2. X.400 User Agent implementations won't in general recognise these extensions. therefore, even though the information is present, it'll often not be available to the user. this can be really problematic, since this information may be critical to diagnosing the reason for a failure 😭
so a second mechanism is defined. this SHALL always be used when the DSN contains non-delivery information, and MAY be used in other cases. the mechanism is to map the whole DSN (as if it were an ordinary multipart) into the return of content. the DSN information shows up as a text body part in the outer message, with the real returned content as an enclosed message. this mechanism makes sure information isn't lost at the gateway 🛡️

5.1.8.2. DSN Extensions

two X.400 MTS extensions are defined like this:

   dsn-header-list EXTENSION
      RFC822FieldList
      ::= id-dsn-header-list

   dsn-field-list EXTENSION
      RFC822FieldList
      ::= id-dsn-field-list

the Object Identifiers id-dsn-header-list and id-dsn-field-list are defined in Appendix D. Theses extensions are used the same way as the IPM extension rfc-822-field, described in Section 5.1.2 🌸 these extensions MAY only be used with ISO-10021, and not X.400 (which doesn't allow user extensions at the MTS level) 💜

5.1.8.3. DSN to Delivery Report Mapping

okay so some DSNs turn into Delivery Reports and some turn into IPMs 📬✨. What decides it is the value of the action field 💅. Mapping to an IPM is exactly like a normal IPM mapping 🎀. The choice between IPM and Delivery Report is made for each reported recipient 🦋. If that choice is different for different reported recipients, then both a Delivery Report and an IPM SHALL be generated 🔥.

Reports are not submitted in the X.400 model, so the report submission gets looked at in terms of the MTA Abstract Service 🧚. An MTA.Report gets constructed 🌸. The MTA.ReportTransferEnvelope.report-identifier comes from the Message-Id of the DSN (if there is one) 💜. If there isn't one, it's generated the way the MTA would generate one for a submitted message 🫶.

The DSN has an RFC 822 header 📨. Trace is mapped the same way it is for a message, into MTA.ReportTransferEnvelope.trace-information 🦋. All the other headers get used to create a dsn-header-list extension, which gets added to MTA.PerReportTransferFields.extensions 🌈. The DSN will have a single SMTP recipient 💖. That recipient is mapped to MTA.ReportTransferEnvelope.report-destination-name 🎀.

Next, the DSN is treated as a normal MIME message, and an X.400 IPM is generated ✨. That IPM is used as MTA.PerReportTransferFields.returned-content, and its type sets MTA.PerReportTransferFields.content-type 💅. The DSN body part is mapped as if it were IA5 text/plain 🌸.

The mandatory MTA.PerReportTransferFields.subject-identifier SHALL be generated from the DSN.per-message-field original-envelope-id, if that starts with the string "X400-MTS-Identifier: ". It's derived from the rest of the field, which is encoded as EBNF.mts-msg-id 🔥. In every other case, this field SHALL be generated by the MIXER Gateway 👑.

All the other mappings come from the DSN body part 🧚. A dsn-field-list extension gets created and added to MTA.ReportTransferFields.extensions, and this is called the per report extension list 💜. The DSN.per-message-fields are mapped like so:

  • original-envelope-id-field
  • reporting-mta-field
  • dsn-gateway-field
  • received-from-mta-field
  • arrival-date-field
  • extension-field
  • other

All of these fields get added to the per report extension list 🦋. Currently there are no other mappings defined 🙈.

Each reported recipient gets considered in turn, and a MTA.PerRecipientReportTransferFields is created for each one 🌈. Its parameters are defaulted as follows:

  • originally-specified-recipient-number: In general these aren't available, so they're assigned incrementally 🔢.
  • last-trace-information: The arrival-time is generated from DSN.arrival-date if that's present. If it isn't, it comes from the Date: of the DSN 🕰️. This is a structured field, and the Report element holds the key info on the recipient 💅. For a DeliveryReport, the type-ofMTS-user is defaulted to public and the message-deliery-time is set to the same as the arrival-time 🎀. For a NonDeliveryReport, the code mappings are defined in Section 5.1.8.4 ✨.

A dsn-field-list extension is created and added to MTA.PerRecipientTransferFields.extensions 🫶. This one is called the per recipient extension list 💖. The DSN.per-recipient-fields are mapped as follows:

  • original-recipient-field: Mapped to MTA.PerRecipientReportTransferFields.originally-intended-recipient-name 🦋.
  • final-recipient-field: Mapped to MTA.PerRecipientReportTransferFields.actual-recipient-name 🌸.
  • action-field: If this is set to "failed", a non-delivery report is generated. If it's set to "delivered", a delivery report is generated 🔥. Bit one or two of MTA.PerRecipientTransferFields.per-recipient-indicators is set accordingly 💜. This also controls the encoding of MTA.PerRecipientTransferFields.last-trace-information, and the selection of the report type 🧚.

For the other action-field values ("delayed", "relayed", "expanded"), an IPM is generated 📬. This lets the status info reach the X.400 user without the confusion of multiple delivery reports 🙈.

  • status-field: This gets added to the per report extension list 🎀. For non-delivery, it's also used to generate the reason and diagnostic codes inside MTA.PerRecipientReportTransferFields.last-trace 👑. The mappings are defined below ✨.
  • remote-mta-field
  • diagnostic-code-field
  • last-attempt-date-field
  • will-retry-until-field
  • extension-field
  • other

All of these fields get added to the per recipient extension list 💅.


5.1.8.4. Status Value Mappings

Status values get mapped to X.400 reason and diagnostic codes like this 🌈.

If a status value shows up that isn't in this table, the gateway MAY use the same mapping as for "X.n.0" (1/None or 0/None), or it MAY map to another, configurable code 🧚. Implementors are asked to forward new codes to the mixer list so they can be included in future versions of this standard 💖. So for instance, "5.2.37", which is currently undefined, would map onto the same thing as "5.2.0", namely 1/None 🌸.

DSN code  Meaning                               X400 code Meaning

X.0.0     Other status                          1/None

X.1.0     Other Address Status                  1/None
X.1.1     Bad mailbox address                   1/0     Unrecognized
X.1.2     Bad system address                    1/0     Unrecognized
X.1.3     Bad mailbox address syntax            1/0     Unrecognized
X.1.4     Mailbox address ambiguous             1/1
X.1.5     Only used for positive reports, not applicable
X.1.6     Destination mailbox has moved         1/43  New addr unknown
X.1.7     Bad sender's mailbox address syntax   1/11  Invalid arguments
X.1.8     Bad sender's system address           1/11  Invalid arguments

X.2.0     Other or undefined mailbox status     1/None
X.2.1     Mailbox disabled, not accepting       1/4   Recipient unavail
X.2.2     Mailbox full                          1/4
X.2.3     Message length exceeds admin limit.   1/7     Content too long
X.2.4     Mailing list expansion problem        1/30  DL expansion fail

X.3.0     Other or undefined system status      0/None
X.3.1     System full                           1/2     MTS congestion
X.3.2     System not accepting network messages 1/2     MTS congestion
X.3.3     System not capable of selected feat   1/18    Unsupp crit func
X.3.4     Message too big for system            1/7
X.3.5     System incorrectly configured      1/None

X.4.0     Other or undefined network or routing 0/None
X.4.1     No answer from host                   0/None
X.4.2     Bad connection                        0/None
X.4.3     Routing server failure                6/None  Dir op unsucc.
X.4.4.    Unable to route                       0/None
X.4.5     Network congestion                    1/2     MTS congest.
X.4.6     Routing loop detected                 1/3
X.4.7     Delivery time expired                 1/5

X.5.0     Other or undefined protocol status    1/None

X.5.1     Invalid command                       1/14    Protocol viol.
X.5.2     Syntax error                          1/14
X.5.3     Too many recipients                   1/16
X.5.4     Invalid command arguments             1/14
X.5.5     Wrong protocol version                1/18    Unsupp.crit.func
X.6.0     Other or undefined media error        2/None  Conv. not perf
X.6.1     Media not supported                   1/6     EIT unsupp.
X.6.2     Conversion required and prohibited    1/9
X.6.3     Conversion required but not supported 2/8
X.6.4     Conversion with loss performed        POSITIVE only
X.6.5     Conversion failed                  2/47   Unable to downgrade

X.7.0     Other or undefined security status    1/46
X.7.1     Delivery not authorized, message ref  1/29  No DL submit perm
X.7.2     Mailing list expansion prohibited     1/28
X.7.3     Security conversion req but not poss  1/46  Secure mess. error
X.7.4     Security features not supported       1/46
X.7.5     Cryptographic failure                 1/46
X.7.6     Cryptographic algorithm not supported 1/46
X.7.7     Message integrity failure             1/46

5.1.8.5. DSNs that originated in X.400

The mapping of X.400 delivery reports to DSNs will, in general, give enough info to make a useful reverse mapping 🔍. Messages often get mapped multiple times, usually because of forwarding and distribution lists 🔁. Multiple mappings for delivery reports are a good deal less common 💅. Because of that, the reverse mapping of the X.400 DSN extensions defined in MIXER is OPTIONAL 🌸.


5.2. Return of Contents

RFC 1327 offered two approaches for return of content 🎀. That's because this service is optional in X.400 but expected in RFC 822 🙈. MIXER keeps it simple: a gateway just requests the return of content service from X.400 💖.


5.3. X.400 -> RFC 822: Detailed Mappings

5.3.1. Basic Approach

A single RFC 822 message gets generated from the incoming IP Message, Report, or IP Notification 📨. All the IPMS.BodyParts get mapped onto one RFC 822 body 🧚. Other services get mapped onto RFC 822 header fields 🌈. If there's no appropriate existing field, new fields are defined for IPMS, MTS and MTA services ✨.

The gateway mechanisms correspond to MTS Delivery 🦋. Just like with submission, some parts also use the MTA (transfer) services 💜. In particular, there's an optimisation that allows for multiple SMTP recipients 🔥.

5.3.2. RFC 822 Settings

An RFC 822 Message has a bunch of mandatory fields in its header 📋. Some SMTP services mandate that an SMTP Originator be specified 👑. Even when it's optional, it's usually a good idea to specify a value 💅. The following defaults are defined, and they SHALL be used if the mappings specified don't derive a value 🫶:

  • SMTP Originator: If this isn't generated by the mapping (for example, for a Delivery Report), a value pointing at a gateway administrator SHALL be assigned 🎀.
  • Date:: A value will always be generated 🕰️.
  • From:: If this isn't generated by the mapping, it's set equal to the SMTP Originator. If the gateway generated it, an appropriate 822.phrase SHALL be added 🌸.
  • At least one recipient field: If no recipient fields are generated, a field "To: list:;" SHALL be added 💖.

This will make sure there's minimal RFC 822 compliance 🌈. When generating RFC 822 headers, folding MAY be used 🧚. It's RECOMMENDED to do this, following the guidelines of RFC 822 ✨.

5.3.3. Basic Mappings

5.3.3.1. Encoded Information Types

This mapping from MTS.EncodedInformationTypes is needed in several disconnected places, so here's the EBNF 🧩:

   encoded-info    = 1#encoded-type

   encoded-type    = built-in-eit / object-identifier
   built-in-eit    = "Undefined"         ; undefined (0)
                   / "Telex"             ; tLX (1)
                   / "IA5-Text"          ; iA5Text (2)
                   / "G3-Fax"            ; g3Fax (3)
                   / "TIF0"              ; tIF0 (4)
                   / "Teletex"           ; tTX (5)
                   / "Videotex"          ; videotex (6)
                   / "Voice"             ; voice (7)
                   / "SFD"               ; sFD (8)
                   / "TIF1"              ; tIF1 (9)

MTS.EncodedInformationTypes gets mapped onto EBNF.encoded-info 🦋. MTS.EncodedInformationTypes.non-basic-parameters is ignored 🙈. Built-in types get mapped onto fixed strings (compatible with X.400(1984) and RFC 987) 💜, and other types get mapped onto EBNF.object-identifier 🌸.

5.3.3.2. Global Domain Identifier 🌸

okay so the way we write down MTS.GlobalDomainIdentifier is this super simple EBNF bit 🫶

global-id = std-or-address

It gets encoded with the std-or-address syntax, and that covers all the attributes inside the Global Domain Identifier ✨

5.3.4. Mappings from the IP Message 💌

okay, now let's talk about mapping an IPM over to RFC 822 📬 An IPMS.IPM is made of an IPMS.IPM.heading and an IPMS.IPM.body. We do the heading first, and we're defining some EBNF for brand-new fields:

ipms-field = "Supersedes" ":" 1*msg-id
             / "Expires" ":" date-time
             / "Reply-By" ":" date-time
             / "Importance" ":" importance
             / "Sensitivity" ":" sensitivity
             / "Autoforwarded" ":" boolean
             / "Incomplete-Copy" ":"
             / "Content-Language" ":" 1#language
             / "Message-Type" ":" message-type
             / "Discarded-X400-IPMS-Extensions" ":" 1#object-identifier
             / "Autosubmitted" ":" autosubmitted


importance      = "low" / "normal" / "high"
sensitivity     = "Personal" / "Private" /
                  "Company-Confidential"

language        = 2*ALPHA [ "(" language-description ")" ]
     language-description = printable-string


message-type    = "Delivery Report"
                / "InterPersonal Notification"
                / "Multiple Part"

autosubmitted   = "not-auto-submitted"
                / "auto-generated"
                / "auto-replied"
                / "auto-forwarded"

The mappings and actions for the IPMS.Heading are next, one element at a time 🎀 Addresses and Message Identifiers get mapped according to Chapter 4, and everything else is either explained or pretty straightforward (algorithmic) 💅 Here's the tea on empty address fields: if a field with addresses has zero elements, it shall be discarded. The one exception is IPMS.Heading.blind-copy-recipients, which can be mapped onto BCC:, since that's the only RFC 822 field that's allowed to have zero recipients 🍓

IPMS.Heading.this-IPM 🦋 Mapped to "Message-ID:".

IPMS.Heading.originator 🧚 If IPMS.Heading.authorizing-users is present, this maps to Sender:. If not, it maps to "From:".

IPMS.Heading.authorizing-users 💜 Mapped to "From:".

IPMS.Heading.primary-recipients 🌈 Mapped to "To:".

IPMS.Heading.copy-recipients 🌸 Mapped to "Cc:".

IPMS.Heading.blind-copy-recipients 🙈 Mapped to "Bcc:".

IPMS.Heading.replied-to-ipm 🫶 Mapped to "In-Reply-To:".

IPMS.Heading.obsoleted-IPMs 👑 Mapped to the extended RFC 822 field "Supersedes:". This replaces the RFC 1327 field "Obsoletes:". Reverse mapping of the RFC 1327 field may be supported ✨

IPMS.Heading.related-IPMs 🎀 Mapped to "References:".

IPMS.Heading.subject 💖 Mapped to "Subject:". The contents get converted to ASCII or T.61 (as defined in Section 3.5). A CRLF will not be present in a valid X.400 field. Any CRLF that does show up is not mapped, but it's used as a point where the subject field gets folded, unless an RFC 1522 encoding is used 😭

IPMS.Heading.expiry-time ⏳ Mapped to the extended RFC 822 field "Expires:". This replaces the RFC 1327 field "Expiry-Date:". Reverse mapping of the RFC 1327 field may be supported 🌙

IPMS.Heading.reply-time 🍓 Mapped to the extended RFC 822 field "Reply-By:".

IPMS.Heading.reply-recipients 💅 Mapped to "Reply-To:".

IPMS.Heading.importance 🔥 Mapped to the extended RFC 822 field "Importance:".

IPMS.Heading.sensitivity 🫣 Mapped to the extended RFC 822 field "Sensitivity:".

IPMS.Heading.autoforwarded 🦋 Mapped to the extended RFC 822 field "Autoforwarded:".

The standard extensions (Annex H of X.420 / ISO 10021-7) get mapped like this 🧁

incomplete-copy 🌷 Mapped to the extended RFC 822 field "Incomplete-Copy:".

language 🌍 Mapped to the RFC 822 field "Content-Language:", which is defined in RFC 1766 [7]. This mapping may be made without loss of information ✨

auto-submitted 🤖 Mapped to the extended RFC 822 field "Autosubmitted:".

If the RFC 822 extended header is found, it shall be mapped onto an RFC 822 header, as described in Section 5.1.2 🎀

If a non-standard extension is found, it shall be discarded, unless the gateway understands the extension and can perform an appropriate mapping onto an RFC 822 header field. If extensions do get discarded, the list gets noted in the extended RFC 822 field "Discarded-X400-IPMS-Extensions:" 📝

5.3.4.1. Mapping the IPMS Body 📦

The mapping of the IPMS Body is defined in RFC 2157 💕

5.3.4.2. Example Message 📨

Here's an example message that shows off a bunch of these mappings at once 💖

Received: from mhs-relay.ac.uk by bells.cs.ucl.ac.uk via JANET with
          NIFTP id <7906-0@bells.cs.ucl.ac.uk>;
          Thu, 30 May 1991 18:24:55 +0100
X400-Received: by mta "mhs-relay.ac.uk" in /PRMD=uk.ac/ADMD= /C=gb/;
               Relayed; Thu, 30 May 1991 18:23:26 +0100
X400-Received: by /PRMD=HMG/ADMD=GOLD 400/C=GB/; Relayed;
               Thu, 30 May 1991 18:20:27 +0100
Message-Type: Multiple Part
Date: Thu, 30 May 1991 18:20:27 +0100
X400-Originator: Stephen.Harrison@gosip-uk.hmg.gold-400.gb
X400-MTS-Identifier:
     [/PRMD=HMG/ADMD=GOLD 400/C=GB/;PC1000-910530172027-57D8]
Original-Encoded-Information-Types: ia5
X400-Content-Type: P2-1984 (2)
X400-Content-Identifier: Email Problems
From: Stephen.Harrison@gosip-uk.hmg.gold-400.gb (Tel +44 71 217 3487)
Message-ID: <PC1000-910530172027-57D8*@MHS>
To: Jim Craigie <NTIN36@gec-b.rutherford.ac.uk>,
    Tony Bates <tony@ean-relay.ac.uk>,
    Steve Kille <S.Kille@cs.ucl.ac.uk>
Subject: Email Problems
Sender: Stephen.Harrison@gosip-uk.hmg.gold-400.gb
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary=boundary-1

--boundary-1
Content-Type: text/plain; charset=US-ASCII

Hope you gentlemen.......

Regards,

Stephen Harrison
UK GOSIP Project

--boundary-1
Content-Type: message/rfc822

From: Urs Eppenberger <Eppenberger@verw.switch.ch>
Message-ID:
<562*/S=Eppenberger/OU=verw/O=switch/PRMD=SWITCH/ADMD=ARCOM/C=CH/@MHS>
To: "Stephen.Harrison" <Stephen.Harrison@gosip-uk.hmg.gold-400.gb>
Cc: kimura@bsdarc.bsd.fc.nec.co.jp
Subject: Response to Email link
Content-Type: multipart/mixed; boundary=boundary-2


--boundary-2

Dear Mr Harrison......


--boundary-2--

--boundary-1--

5.3.5. Mappings from an IP Notification 🔔

Because of the service setting, IP Notifications usually won't need to be mapped by a MIXER gateway 🙌 Instead, a message gets generated with these fields:

From: 💌 Set to the IPMS.IPN.ipn-originator.

To: 📬 Set to the recipient from MTS.MessageSubmissionEnvelope. If there have been redirects, the original address shall be used.

Subject: 🏷️ Set to the string "X.400 Inter-Personal Notification" for a receipt notification, and to "X.400 Inter-Personal Notification (failure)" for a non-receipt notification.

Message-Type: 🧾 Set to "InterPersonal Notification".

References: 🔗 Set to IPMS.IPN.subject-ipm.

Discarded-X400-IPMS-Extensions: 🗑️ Used for any discarded IPN extensions.

The following EBNF is defined for the body of the message. This format exists so that all the information from an interpersonal notification is available to the end user in a uniform way 💜

      ipn-body-format = ipn-description <CRLF>
                      [ ipn-extra-information <CRLF> ]
                      [ ipn-content-return ]

      ipn-description = ipn-receipt / ipn-non-receipt

      ipn-receipt = "Your message to:" preferred-recipient <CRLF>
               "was received at" receipt-time <CRLF> <CRLF>
               "This notification was generated"
                acknowledgement-mode <CRLF>
               "The following extra information was given:" <CRLF>
                ipn-suppl <CRLF>

      ipn-non-receipt = "Your message to:"
                   preferred-recipient <CRLF>
                   ipn-reason

      ipn-reason = ipn-discarded / ipn-auto-forwarded

      ipn-discarded = "was discarded for the following reason:"
                       discard-reason <CRLF>

      ipn-auto-forwarded = "was automatically forwarded." <CRLF>
                           [ "The following comment was made:"
                           auto-comment ]


      ipn-extra-information =
             "The following information types were converted:"
              encoded-info

      ipn-content-return = "The Original Message is not available"
                           / "The Original Message follows:"

      preferred-recipient = mailbox
      receipt-time        = date-time
      auto-comment        = printablestring
      ipn-suppl           = printablestring
      discard-reason     = "Expired" / "Obsoleted" /
                  "User Subscription Terminated" / "IPM Deleted"

      acknowledgement-mode = "Manually" / "Automatically"

Next up, the mappings for the common fields of IPMS.IPN (IPMS.CommonFields) onto this structure and the message header 🧩

subject-ipm 📌 Mapped to "References:".

ipn-originator ✍️ Mapped to "From:".

ipn-preferred-recipient 🎯 Mapped to EBNF.preferred-recipient.

conversion-eits 🔄 Mapped to EBNF.encoded-info in EBNF.ipn-extra-information.

The mappings for the IPMS.IPN.non-receipt-fields (IPMS.NonReceiptFields) are next 🙅‍♀️

non-receipt-reason 🪧 Used to pick between EBNF.ipn-discarded and EBNF.ipn-auto-forwarded.

discard-reason 🗑️ Mapped to EBNF.discard-reason.

auto-forward-comment 💬 Mapped to EBNF.auto-comment.

returned-ipm 📎 This only applies to non-receipt notifications. EBNF.ipn-content-return shall always be omitted for receipt notifications, and always be present in non-receipt notifications. If it's present, the second option of EBNF.ipn-content-return is chosen and the message is included. In that case, the message is formatted as multipart/mixed, and the returned message is included as message/rfc822 after the text body part. Otherwise, the first option is chosen 🧐

And last but not least, the mappings for the IPMS.IPN.receipt-fields (IPMS.ReceiptFields) 🧾

receipt-time ⏰ Mapped to EBNF.receipt-time.

acknowledgement-mode 👍 Mapped to EBNF.acknowledgement-mode.

suppl-receipt-info ➕ Mapped to EBNF.ipn-suppl.

Here's an example notification so you can see how it all comes together 🥰

     From: Steve Kille <steve@cs.ucl.ac.uk>
     To: Julian Onions <jpo@computer-science.nottingham.ac.uk>
     Subject: X.400 Inter-personal Notification
     Message-Type: InterPersonal Notification
     References: <1229.614418325@UK.AC.NOTT.CS>
     Date: Wed, 21 Jun 89 08:45:25 +0100

     Your message to: Steve Kille <steve@cs.ucl.ac.uk>
     was automatically forwarded.
     The following comment was made:
        Sent on to a random destination

     The following information types were converted: g3fax

5.3.6. Mappings from the MTS Abstract Service ✨

okay so this section is where we map the MTS side of things 💅 It covers the MTS mappings for User Messages (IPM and IPN), and the mapping is defined by spelling out how MTS.MessageDeliveryEnvelope gets mapped. To make it work, RFC 822 gets a bunch of extensions 🎀

      mts-field = "X400-MTS-Identifier" ":" mts-msg-id
                / "X400-Originator" ":" mailbox
                / "X400-Recipients" ":" 1#mailbox
                / "Original-Encoded-Information-Types" ":"
                   encoded-info
                / "X400-Content-Type" ":" mts-content-type
                / "X400-Content-Identifier" ":" printablestring
                / "Priority" ":" priority
                / "Originator-Return-Address" ":" 1#mailbox
                / "DL-Expansion-History" ":" mailbox ";" date-time
                   ";"
                / "Conversion" ":" prohibition
                / "Conversion-With-Loss" ":" prohibition
                / "Delivery-Date" ":" date-time
                / "Discarded-X400-MTS-Extensions" ":"
                   1#( object-identifier / labelled-integer )


      prohibition     = "Prohibited" / "Allowed"
      mts-msg-id       = "[" global-id ";" *text "]"

      mts-content-type = "P2" /  labelled-integer
                       / object-identifier

      priority        = "normal" / "non-urgent" / "urgent"

So now we go element by element 🦋 If an action doesn't end up mapping an extended element, the criticality of that element still counts. If the element is marked as critical for transfer or for delivery, the gateway shall non deliver the message, because a critical extension can't be handled correctly. Real talk, that's a hard no 🙅‍♀️

  • MTS.MessageDeliveryEnvelope.message-delivery-identifier: this gets mapped to the extended RFC 822 field X400-MTS-Identifier: 🪪
  • MTS.MessageDeliveryEnvelope.message-delivery-time: discarded, because this time shows up in an appropriate trace element instead ⏰

Next up are the elements inside MTS.MessageDeliveryEnvelope.other-fields (MTS.OtherMessageDeliveryFields) 🌸

  • content-type: mapped to the extended RFC 822 field X400-Content-Type:. The string P2 is kept around for backwards compatibility with RFC 987. This shall not be generated, and either the EBNF.labelled-integer or EBNF.object-identifier encoding gets used instead.
  • originator-name: mapped to the SMTP originator, and also to the extended RFC 822 field X400-Originator:. This is covered in Section 4.6.2.
  • original-encoded-information-types: mapped to the extended RFC 822 field Original-Encoded-Information-Types: 📦
  • priority: mapped to the extended RFC 822 field Priority: 🚨
  • delivery-flags: if the conversion-prohibited bit is set, you add an extended RFC 822 field called Conversion: 🙅
  • this-recipient-name and other-recipient-names: these are handled in Section 4.6.2 💌
  • originally-intended-recipient-name: handled in Section 4.6.2 too 🫶
  • converted-encoded-information-types: discarded, since this info gets mapped into the trace 🗑️
  • message-submission-time: mapped to Date: 📅
  • content-identifier: mapped to the extended RFC 822 field X400-Content-Identifier:. In RFC 1327 this was Content-Identifier:, but it got renamed to avoid confusion with MIME defined fields. Gateways that reverse map may support the old field too 👀

If any extensions (MTS.MessageDeliveryEnvelope.other-fields.extensions) are there, and they're marked as critical for transfer or delivery, then the message shall be rejected. Those extensions get mapped like this 🎀

  • conversion-with-loss-prohibited: if it's set to MTS.ConversionWithLossProhibited.conversion-with-loss-prohibited, you add the extended RFC 822 field Conversion-With-Loss: 🙅‍♀️
  • requested-delivery-method: mapped to a comment, as described in Section 4.6.2.2 💬
  • originator-return-address: mapped to the extended RFC 822 field Originator-Return-Address: 💌

These next ones are only relevant for physical delivery, so they show up as comments in the X400-Recipients: field, as described in Section 4.6.2.2 📮

  • physical-forwarding-address-request
  • physical-delivery-modes
  • registered-mail-type
  • recipient-number-for-advice
  • physical-rendition-attributes
  • physical-delivery-report-request
  • physical-forwarding-prohibited

Then there's this group, which implies security services that just aren't around in the RFC 822 world 🔐 If they're marked as critical for transfer or delivery, the message shall be rejected. If not, they get discarded.

  • originator-certificate
  • message-token
  • content-confidentiality-algorithm-identifier
  • content-integrity-check
  • message-origin-authentication-check
  • message-security-label
  • proof-of-delivery-request

Last two in this list 🧚

  • redirection-history: described in Section 4.6.2 🔁
  • dl-expansion-history: each element gets mapped to an extended RFC 822 field DL-Expansion-History:. These fields shall be ordered in the message header, so the most recent expansion comes first, same order as the trace 📜

And if any MTS (or MTA) Extensions that aren't specified in X.400 show up, and they're marked as critical for transfer or delivery, the message shall be rejected. If they're not marked that way, they can safely be discarded 🗑️ The list of discarded fields shall be listed in the extended header Discarded-X400-MTS-Extensions: 💜

5.3.7. Mappings from the MTA Abstract Service 🌈

there are some mappings down at the MTA Abstract Service level that get done for IPM and IPN too 🫶 You can derive these from MTA.MessageTransferEnvelope. Why do we mess with layering here? Three main reasons 😭

  • Allowing multiple recipients to share a single RFC 822 message
  • Making the X.400 trace information available on the RFC 822 side
  • Making any information on deferred delivery available

The SMTP recipients are worked out from the full list of X.400 recipients. That's every member of MTA.MessageTransferEnvelope.per-recipient-fields getting passed through the gateway where the responsibility bit is set. Sometimes a different RFC 822 message would be calculated for each recipient, since each one can have different service requests 🔀 As talked about in 4.6.2.2, this spec lets you either generate multiple messages, or throw away the per-recipient info.

Here's the EBNF for the extended RFC 822 headers 📝

mta-field       = "X400-Received" ":" x400-trace
                / "Deferred-Delivery" ":" date-time
                / "Latest-Delivery-Time" ":" date-time

x400-trace       = "by" md-and-mta ";"
                 [ "deferred until" date-time ";" ]
                 [ "converted" "(" encoded-info ")" ";" ]
                 [ "attempted" md-or-mta ";"  ]
                    action-list
                 ";" arrival-time

md-and-mta       = [ "mta" mta "in" ]  global-id
mta              = word
arrival-time     = date-time

md-or-mta        = "MD" global-id
                 / "MTA" mta

Action-list      = 1#action
action           = "Redirected"
                 / "Expanded"
                 / "Relayed"
                 / "Rerouted"

Quick note on that: EBNF.mta is encoded as 822.word. If the character set can't be encoded as 822.atom, you use the 822.quoted-string encoding instead 🎀

If MTA.PerMessageTransferFields.deferred-delivery-time is there, it's used to generate a Deferred-Delivery: field ⏳ X.400 doesn't make this info available at the MTS level on delivery, because it needs the first MTA to provide that service. If the first MTA doesn't, the gateway can optionally implement the function itself: it may hold the message until the time in the protocol element. So the value is usually going to be in the past, which means this extended RFC 822 field is mostly there for info 🕰️

If MTA.PerMessageTransferFields.extensions.dl-expansion-prohibited is present and set to dl-expansion-probited, the gateway may reject that message, since it can't control distribution list expansion beyond the gateway 🚫 The service for this is described in Section 2.3.1.2. This approach wasn't specified in RFC 1327. If it turns out to be useful, it may get made mandatory in future versions of MIXER 🔮

If MTA.PerMessageTransferFields.extensions.recipient-reassignment-prohibited is present and set to recipeint-reassignment-probited, the gateway may reject that message for the same reason: it can't control distribution list expansion beyond the gateway 🙅 The service for this is in Section 2.3.1.2, and it wasn't in RFC 1327 either. If it's useful, it may become mandatory in future versions of MIXER 💅

Next, merge MTA.PerMessageTransferFields.trace-information and MTA.PerMessageTransferFields.internal-trace-information into one ordered trace list 🧩 If internal trace from other management domains hasn't been stripped, this can get messy and need some complex interleaving 🌀 Where an internal trace element and an external trace element are identical, except for the MTA in the internal trace, only the internal trace element shall be presented. Use that to generate a run of X400-Received: fields. The only difference between external and internal trace is the extra MTA info in the internal trace elements ✨

When generating an RFC 822 message, all the trace fields (X400-Received and Received) shall go at the very beginning of the header, before any other fields 🎀 The trace runs in chronological order, with the most recent element at the front of the message. The order comes from the order of the fields, not from timestamps in the trace, because there's no guarantee the clocks are synchronised ⏱️ A simple external trace example looks like this 👇

X400-Received: by /PRMD=UK.AC/ADMD=Gold 400/C=GB/ ; Relayed ;
        Tue, 20 Jun 89 19:25:11 +0100

And a more complex internal one 🧠

X400-Received: by mta "UK.AC.UCL.CS" in
       /PRMD=UK.AC/ADMD=Gold 400/C=GB/ ;
       deferred until  Tue, 20 Jun 89 14:24:22 +0100 ;
        converted (undefined, g3fax) ; attempted MD /ADMD=Foo/C=GB/ ;
        Relayed, Expanded, Redirected ; Tue, 20 Jun 89 19:25:11 +0100

The gateway itself adds a single line of trace info showing MIXER conversion, using a comment. For example 🦋

Received: from isode.com by isode.com
       (MIXER Conversion following RFC 1327);
       Thu, 2 Jan 1997 14:46:03 +0000

If SMTP is in use, Appendix A also needs to be followed, which covers the optional mappings to extension parameters 📬

5.3.8. Mappings from Report Delivery 📊

so yeah, only reports destined for the MTS user get mapped 💅 Some additional services are also taken from the MTA service. X.400 Delivery Reports get mapped onto Delivery Status Notifications, as defined by NOTARY [28] 🔔

5.3.8.1. MTS Mappings

Okay, here's the deal: a Delivery Report service is represented as MTS.ReportDeliveryEnvelope, which is made up of per-report-fields (MTS.PerReportDeliveryFields) and per-recipient-fields 🎀

Okay so this is the message the gateway actually sends back, and it's giving full MIME energy 💌 It's a multipart/report with report-type=delivery-status, and it gets built with these fields:

  • From: An administrator at the gateway system. 🎀
  • To: A mapping of the MTA.ReportTransferEnvelope.report-destination-name. This is also the SMTP recipient. 💖
  • Message-Type: Set to "Delivery Report". This is strictly redundant, but it's kept for backwards compatibility with RFC 1327. 🦋
  • Subject: The subject line follows this EBNF 👑
subject-line  = "Delivery-Report" "(" status ")"
                [ "for" destination ]

status        = "success" / "failure" / "success and failures"

destination   = mailbox / "MTA" word

The subject is supposed to tell you what kind of message it is and sum up what's inside, and that's the whole point 🌸 status gets set based on whether the recipients in the report are all successes, all failures, or a mix. If the report is about one recipient, you can use every option of status, which is super useful info for the person reading it 🧚 If the info varies between recipients, you can't use those options. destination shows which addresses the report is about. For a single address it's the mailbox, in its RFC 822 form. If every recipient in the report goes through the same MTA, that MTA's name goes in the word part. The MTA is worked out from the delivery report's trace 🔍

Now the body, which follows the NOTARY delivery status notification format. It's set up like it's coming from the gateway, and it has three body parts so the RFC 822 user always gets the same consistent info ✨

The first body part is plain ASCII text with two things in it:

  1. A few lines of keywords that identify the original message.
  2. A human summary of how each recipient in the report did.

The second body part is mandatory. It's the NOTARY delivery status notification, with the detailed info pulled from the report. Honestly this one can be the key to solving some obscure problem 😭

The third body part is optional and holds the returned message (return of content). It's really handy for the RFC 822 user because they can pull the original message out of it. For negative reports it shall be included if the original message is available. For positive reports, the headers from the message shall be included if the original message is available.

The first body part, the one with the user-friendly description, is text/plain. Its format is defined below as EBNF.dr-user-info:

dr-user-info = dr-summary <CRLF>
                dr-recipients <CRLF>
                dr-content-return

dr-content-return = "The Original Message is not available"
     / "The Original Message follows:"

dr-summary = "This report relates to your message:" <CRLF>
                content-correlator <CRLF> <CRLF>
             "of" date-time <CRLF> <CRLF>

dr-recipients = *(dr-recipient <CRLF> <CRLF>)

dr-recipient = dr-recip-success / dr-recip-failure
dr-recip-success =
                "Your message was successfully delivered to:"
                 mailbox "at" date-time


dr-recip-failure = "Your message was not delivered to:"
                        mailbox <CRLF>
                "for the following reason:" *word report-point
= [ "mta" mta-name "in" ] global-id content-correlator = *word
mta-name = word

EBNF.dr-summary 🍓 The content-correlator comes from the content correlator, or from the content identifier if there isn't a content correlator. The date-time comes from the trace, as described in Section 5.3.8.3. You can add LWSP to make the layout of the body part look nicer.

EBNF.dr-recipients 💅 There's one element for each recipient in the delivery report. In every case, mailbox comes from the RFC 822 form of the originally specified recipient. That's taken from the originally specified recipient element if it's there, or from the actual recipient if not. When reporting success, the message delivery time is used to derive date-time. When reporting failure, the info includes a human-readable interpretation of the X.400 diagnostic and reason codes, plus the supplementary information.

EBNF.dr-content-return 🫶 This is set depending on whether or not the content is being returned.

The EBNF of this body part is designed for English-speaking users, but the language of the strings in it can be changed 🌈

Here's the EBNF used in the delivery status notification:

   dr-per-message-fields =
      / "X400-Conversion-Date" ":" date-time
      / "X400-Subject-Submision-Identifier" ":"
                                mts-msg-id
      / "X400-Content-Identifier" ":" printablestring
      / "X400-Content-Type" ":" mts-content-type
      / "X400-Original-Encoded-Information-Types" ":"
                           encoded-info
      / "X400-Originator-and-DL-Expansion-History" ":"
                           mailbox ";" date-time ";"
      / "X400-Reporting-DL-Name" ":" mailbox
      / "X400-Content-Correlator" ":" content-correlator
      / "X400-Recipient-Info" ":" recipient-info
      / "X400-Subject-Intermediate-Trace-Information" ":"
                           x400-trace
      / dr-extensions

   dr-per-recipient-fields =
      / "X400-Redirect-Recipient" ":" "x400" ";" std-or
      / "X400-Mapped-Redirect-Recipient" ":" "rfc822" ";" mailbox
      / "X400-Converted-EITs" ":" encoded-info ";"
      / "X400-Delivery-Time" ":" date-time
      / "X400-Type-of-MTS-User" ":" labelled-integer
      / "X400-Last-Trace" ":" [ encoded-info ] date-time
      / "X400-Supplementary-Info" ":"
            <"> printablestring <"> ";"
      / "X400-Redirection-History" ":" redirect-history-item
      / "X400-Physical-Forwarding-Address" ":" mailbox
      / "X400-Originally-Specified-Recipient-Number" ":"
            integer
      / dr-extensions

   dr-extensions = "X400-Discarded-DR-Extensions" ":"
                     1# (object-identifier / labelled-integer)

   dr-diagnostic = "Reason" labelled-integer-2
                     [ ";" "Diagnostic" labelled-integer-2 ]

A body part of type delivery status, as defined by NOTARY, gets generated too 🎀 MIXER extends that DSN spec. It adds new per-message fields in EBNF.dr-per-message-fields and new per-recipient fields in EBNF.dr-per-recipient-fields, and those are used as extensions to DSN.per-message-fields and DSN.per-recipient-fields. MIXER also defines a new NOTARY address type, "x400", with the encoding of EBNF.std-or. A directory name may be included as an RFC 822 comment 💜

These DSN.per-message-fields are always generated:

DSN.reporting-mta-field 🌸 The DSN.mta-name-type is set to "x400", and this string is reserved by MIXER. The DSN.mta-name has its syntax specified by EBNF.report-point, and the info is derived from the first element of the DR's trace.

DSN.arrival-date-field ⭐ This is derived from the date of the MTA.PerRecipientReportTransferFields.last-trace-info.arrival-time of the first recipient in the report.

These two EBNF.per-message-fields are generated by the MIXER gateway 👑

DSN.dsn-gateway-field The type is set to "dns" and the domain is set to the local domain of the gateway.

X400-Conversion-Date: The EBNF.date-time is set to the time of the MIXER conversion. ⏰

Next up, the elements of MTS.ReportDeliveryEnvelope.per-report-fields get mapped onto the DSN per-message fields like this 🦋

subject-submission-identifier Mapped to DSN.original-envelope-id-field. This MTS Identifier's encoding follows the format EBNF.mts-msg-id.

content-identifier Mapped to X400-Content-Identifier:

content-type Mapped to X400-Content-Type:

original-encoded-information-types Mapped to X400-Encoded-Info:

The extensions from MTS.ReportDeliveryEnvelope.per-report-fields.extensions get mapped like this 🧚

originator-and-DL-expansion-history Each element is mapped to an X400-Originator-and-DL-Expansion-History:. They shall be ordered so the most recent expansion comes first in the header, which is the same order as the trace 💅

reporting-DL-name Mapped to X400-Reporting-DL-Name:

content-correlator If the content correlator starts with the string "SMTP/NOTARY ENVID: ", then the rest of the content correlator gets mapped to the DSN original-envelope-id field. If that's not the case, the content correlator gets mapped to X400-Content-Correlator:, as long as the encoding is IA5String. (It always will be, so don't stress 🙈)

message-security-label reporting-MTA-certificate report-origin-authentication-check

These security parameters won't be present unless there's an error in a remote MTA. If they are present, they shall be discarded in preference to discarding the whole report. They shall also be listed in the X400-Discarded-DR-Extensions: field.

If there are any other DR extensions, they shall also be discarded and listed in the X400-Discarded-DR-Extensions: field. Don't skip this part, bestie, it matters 🚨

For each element of MTS.ReportDeliveryEnvelope.per-recipient-fields, a set of DSN.per-recipient-fields gets generated. The fields get filled in like this 💖

actual-recipient-name If originally-intended-recipient-name is not present, generate a DSN.original-recipient-field, with DSN.address-type of "rfc822" and an RFC 822 mailbox generated from the address, encoded as NOTARY specifies. Also generate a DSN.final-recipient-field, which holds the X.400 representation of that same address. If the directory name is present, it shall be added as a trailing comment in the X.400 form.

If originally-intended-recipient-name is present, generate an X400-Mapped-Redirect-Recipient: field, with DSN.address-type of "rfc822" and an RFC 822 mailbox generated from the address, encoded as NOTARY specifies. Also generate an X400-Redirect-Recipient: field, which holds the X.400 representation of that same address. If the directory name is present, it shall be added as a trailing comment in the X.400 form.

report If it's MTS.Report.delivery, then set DSN.action-field to "delivered", and set X400-Delivery-Time: and X400-Type-of-MTS-User: from the info in the report. DSN.status field gets set to "2.0.0" ✨

If it's MTS.Report.non-delivery, then set DSN.action-field to "failed". DSN.diagnostic-code-field is encoded according to the syntax EBNF.dr-diagnostic, with the labelled integers set from the reason and diagnostic codes. DSN.status-field is derived from the reason and diagnostic codes, as described below 🔥

converted-encoded-information-types Set X400-Converted-EITs:

Okay so the first one, originally-intended-recipient, is the big main character moment 💅 Generate a DSN.final-recipient-field field with DSN.address-type set to "rfc822", and put an RFC 822 mailbox in it, generated from the address encoded as NOTARY says 📬 Also generate a DSN.original-recipient-field field that holds the X.400 representation of that same address. If the directory name is present, it shall be added as a trailing comment in the X.400 form 🎀

supplementary-info is simple: set X400-Supplementary-Info: ✨

redirection-history gets an "X400-Redirection-History:" field for each redirect history element, and they're ordered with the earliest redirect first 🦋 Very chronological, very iconic.

physical-forwarding-address gets set as X400-Physical-Forwarding-Address as a mailbox, with the directory name in a comment if there is one 🌸

recipient-certificate gets discarded 🙈 proof-of-delivery also gets discarded 💀 Bye bye.

Any unknown extensions shall be discarded, irrespective of criticality 🫶 Like, even if they're marked critical, they're gone. All discarded extensions shall be included in an "X400-Discarded-DR-Extensions:" field so nothing just vanishes into the void 👑

The number from MTA.PerRecipientReportTransferFields.originally-specified-recipient-number shall be mapped to "X400-Originally-Specified-Recipient-Number:", which helps with reverse mapping of delivery reports 🧚

The original message shall be included in the delivery status notification if it's available 💜 It will usually be available at the gateway, as discussed in Section 5.2. If the original message is available but is not a legal message format, a dump of the ASN.1 may be included, encoded as application/octet-string. This is recommended, but not required. Lowkey a vibe, but optional 🍓

Where the original message is included, it shall be encoded according to the MIME specifications as content type message/rfc822 🌈

5.3.8.2. Status Code Mappings

This section defines the mappings from X.400 diagnostic and status codes to the NOTARY Status field. It's the lookup table moment, bestie 📚✨

C/D     X400 meaning                            DSN code        Means
0/Any   Transfer failure (may be temporary)     4.4.0 Other net/route
1/Any   Unable to transfer                      5.0.0 Other, unknown
2/Any   Conversion not performed                5.6.3 Conv not supported
3/Any   Physical rendition not performed        5.6.0 Other media error
4/Any   Physical delivery not performed         5.1.0 Other address
                                                      status
5/Any   Restricted delivery                     5.7.1
6/Any   Directory operation unsuccessful        5.4.3 Routing server
                                                      failure
7/Any   Deferred delivery not performed         5.3.3 Not capable

1/0     Unrecognized OR name                    5.1.1
1/1     Ambiguous OR name                       5.1.4
1/2     MTS congestion                          4.3.1
1/3     Loop detected                           5.4.6
1/4     Recipient unavailable                   4.2.1
1/5     Delivery time expired                   4.4.7
1/6     Encoded information types unsupported   5.6.1 Media unsupp.
1/7     Content too long                        5.2.3
2/8     Conversion impractical                  5.6.3
2/9     Conversion prohibited                   5.6.3
1/10    Implicit conversion not subscribed      5.6.3
1/11    Invalid arguments                       5.5.2
1/12    Content syntax error                    5.5.2
1/13    Size constraint violation               5.5.2
1/14    Protocol violation                      5.5.0
1/15    Content type not supported              5.6.1 Media unsupp.
1/16    Too many recipients                     5.5.3
1/17    No bilateral agreement                  5.4.4
1/18    Unsupported critical function           5.3.3 System not capable
2/19    Conversion with loss prohibited         5.6.2
2/20    Line too long                           5.6.0
2/21    Page split                              5.6.0
2/22    Pictorial symbol loss                   5.6.2
2/23    Punctuation symbol loss                 5.6.2
2/24    Alphabetic character loss               5.6.2
2/25    Multiple information loss               5.6.2
1/26    Recipient reassignment prohibited       5.4.0 Undefined net/route
1/27    Redirection loop detected               5.4.6
1/28    DL expansion prohibited                 5.7.2
1/29    No DL submit permission                 5.7.1 Delivery not
                                                      authorized
1/30    DL expansion failure                    4.2.4
4/31    Physical rendition attrs not supported  5.6.0 Undefined media
                                                      error
4/32-45 Various physical mail stuff             5.1.0 Other address
                                                      status
1/43    New address unknown                     5.1.6 Destination mbox
                                                      moved
1/46    Secure messaging error                  5.7.0 Other security
                                                      status
2/47    Unable to downgrade                     5.3.3 System not capable
0/48    Unable to complete transfer             5.3.4 Message too big
0/49    Transfer attempts limit reached         4.4.7 Delivery time
                                                      expired

5.3.8.3. MTA Mappings

The single SMTP recipient is constructed from MTA.ReportTransferEnvelope.report-destination-name, using the mappings of Chapter 4. Unlike with a user message, this information is not available at the MTS level 🥺

The following additional mappings are made, which results in fields in the outer header of the DSN 💌

  • MTA.ReportTransferEnvelope.report-destination-name is used to generate the To: field.
  • MTA.ReportTransferEnvelope.identifier is mapped to the extended RFC 822 field "X400-MTS-Identifier:". It may also be used to derive a "Message-Id:" field.
  • MTA.ReportTransferEnvelope.trace-information and MTA.ReportTransferEnvelope.internal-trace-information are mapped onto the extended RFC 822 field "X400-Received:", as described in Section 5.3.7. Date: is generated from the first element of trace.

The following additional mappings are made, which result in per message fields in the DSN body part 🎀

  • MTA.PerRecipientReportTransferFields.last-trace-information is mapped to X400-Last-Trace:".
  • MTA.PerReportTransferFields.subject-intermediate-trace-information is mapped to "X400-Subject-Intermediate-Trace-Information:". These fields are ordered so that the most recent trace element comes first 🔥

5.3.8.4. Example Delivery Reports

This section contains sample delivery reports 📮 These are the same examples used in RFC 1327, so they also show the changes between RFC 1327 and this document. Bestie, it's a whole glow-up arc 🦋

Example Delivery Report 1:

Received: from cs.ucl.ac.uk by bells.cs.ucl.ac.uk
   via Delivery Reports Channel id <27699-0@bells.cs.ucl.ac.uk>;
   Thu, 7 Feb 1991 15:48:39 +0000 From: UCL-CS MTA
<postmaster@cs.ucl.ac.uk> To: S.Kille@cs.ucl.ac.uk Subject: Delivery
Report (failure) for H.Hildegard@bbn.com Message-Type: Delivery
Report Date: Thu, 7 Feb 1991 15:48:39 +0000 Message-ID:
<"bells.cs.u.694:07.01.91.15.48.34"@cs.ucl.ac.uk> X400-Content-
Identifier: Greetings.  MIME-Version: 1.0 Content-Type:
multipart/report; report-type=delivery-status;
    boundary=boundary-1

--boundary-1

This report relates to your message:
        Greetings.

        of Thu, 7 Feb 1991 15:48:20 +0000

Your message was not delivered to
        H.Hildegard@bbn.com for the following reason:
        Bad Address
        MTA 'bbn.com' gives error message  (USER) Unknown user name
in

        "H.Hildegard@bbn.com"

The Original Message follows:


--boundary-1 content-type: message/delivery-status

Reporting-MTA: x400;  bells.cs.ucl.ac.uk in /PRMD=uk.ac/ADMD=gold
400/C=gb/ Arrival-Date: Thu, 7 Feb 1991 15:48:34 +0000 DSN-Gateway:
dns;  bells.cs.ucl.ac.uk X400-Conversion-Date: Thu, 7 Feb 1991
15:48:40 +0000 Original-Envelope-Id:
         [/PRMD=uk.ac/ADMD=gold
400/C=gb/;<1803.665941698@UK.AC.UCL.CS>] X400-Content-Identifier:
Greetings.  X400-Subject-Intermediate-Trace-Information:
/PRMD=uk.ac/ADMD=gold 400/C=gb/;
         arrival Thu, 7 Feb 1991 15:48:20 +0000 action Relayed X400-
Subject-Intermediate-Trace-Information:  /PRMD=uk.ac/ADMD=gold
400/C=gb/;
         arrival Thu, 7 Feb 1991 15:48:18 +0000 action Relayed



Original-Recipient: rfc822; H.Hildegard@bbn.com Final-Recipient:
x400;
  /RFC-822=H.Hildegard(a)bbn.com/OU=cs/O=ucl/PRMD=uk.ac/ADMD=gold
400/C=gb/; Action: failure Status: 5.1.1 Diagnostic-Code: x400;
Reason 1 (Unable-To-Transfer);
     Diagnostic 0 (Unrecognised-ORName) X400-Last-Trace: (ia5) Thu, 7
Feb 1991 15:48:18 +0000; X400-Originally-Specified-Recipient-Number:
1 X400-Supplementary-Info: "MTA 'bbn.com' gives error message  (USER)
    Unknown user name in "H.Hildegard@bbn.com"";


--boundary-1 Content-Type: message/rfc822

Received: from glenlivet.cs.ucl.ac.uk by bells.cs.ucl.ac.uk
  with SMTP inbound id <27689-0@bells.cs.ucl.ac.uk>;
  Thu, 7 Feb 1991 15:48:21 +0000 To: H.Hildegard@bbn.com Subject:
Greetings.  Phone: +44-71-380-7294 Date: Thu, 07 Feb 91 15:48:18
+0000 Message-ID: <1803.665941698@UK.AC.UCL.CS> From: Steve Kille
<S.Kille@cs.ucl.ac.uk>


Steve

--boundary-1--

Example Delivery Report 2:

Received: from cs.ucl.ac.uk by bells.cs.ucl.ac.uk
  via Delivery Reports Channel id <27718-0@bells.cs.ucl.ac.uk>;
  Thu, 7 Feb 1991 15:49:11 +0000
X400-Received: by mta "bells.cs.ucl.ac.uk" in
  /PRMD=uk.ac/ADMD=gold 400/C=gb/;
  Relayed; Thu, 7 Feb 1991 15:49:08 +0000
X400-Received: by /PRMD=DGC/ADMD=GOLD 400/C=GB/; Relayed;
  Thu, 7 Feb 1991 15:48:40 +0000
From: UCL-CS MTA <postmaster@cs.ucl.ac.uk>
To: S.Kille@cs.ucl.ac.uk
Subject: Delivery Report (failure) for
         j.nosuchuser@dle.cambridge.DGC.gold-400.gb
Message-Type: Delivery Report
Date: Thu, 7 Feb 1991 15:46:11 +0000
Message-ID: <"DLE/910207154840Z/000"@cs.ucl.ac.uk>
X400-Content-Identifier: A useful mess...
MIME-Version: 1.0
Content-Type: multipart/report; report-type=delivery-status;
    boundary=boundary-1

--boundary-1

This report relates to your message:
        A useful mess...

        of Thu, 7 Feb 1991 15:43:20 +0000


Your message was not delivered to
        j.nosuchuser@dle.cambridge.DGC.gold-400.gb
        for the following reason:
        Bad Address
        DG 21187: (CEO POA) Unknown addressee.

The Original Message is not available


--boundary-1
content-type: message/delivery-status


Reporting-MTA: x400; /PRMD=DGC/ADMD=GOLD 400/C=GB/
Arrival-Date: Thu, 7 Feb 1991 15:48:40 +0000
DSN-Gateway: dns;  bells.cs.ucl.ac.uk
X400-Conversion-Date: Thu, 7 Feb 1991 15:49:12 +0000
Original-Envelope-Id:

  [/PRMD=uk.ac/ADMD=gold 400/C=gb/;<1796.665941626@UK.AC.UCL.CS>]
X400-Content-Identifier: A useful mess...


Original-Recipient: rfc822; j.nosuchuser@dle.cambridge.DGC.gold-400.gb
Final-Recipient: x400;
  /I=j/S=nosuchuser/OU=dle/O=cambridge/PRMD=DGC/ADMD=GOLD 400/C=GB/
Action: failure
Status: 5.1.1
Diagnostic-Code: x400; Reason 1 (Unable-To-Transfer);
    Diagnostic 0 (Unrecognised-ORName)
X400-Supplementary-Info: "DG 21187: (CEO POA) Unknown addressee."
X400-Originally-Specified-Recipient-Number: 1

--boundary-1--

5.3.9. Probe 💅

Okay so, probes are an MTS internal thing, bestie 🫶 There's no RFC 822 version of this, so the gateway is the one that has to service any probe. The reply depends on whether the gateway could handle an MTS Message with the values in the probe. And the reply shall make use of MTS.SupplementaryInformation to show that the gateway serviced the probe ✨

Appendix A - Mappings Specific to SMTP 🎀

This appendix is all about the Simple Mail Transfer Protocol (RFC 821), so it spells out the specific changes for this protocol. When MIXER is used with SMTP, conformance to this appendix is mandatory. No skipping, periodt 💅

1. Probes

When servicing a probe, as described in section 5.3.9, use may be made of the SMTP VRFY command to increase the accuracy of information in the delivery report 🧚

2. Long Lines

SMTP is a text oriented protocol and is required to support a line length of at least 1000 characters. Some implementations don't support line lengths greater than 1000 characters, and that can cause problems 😭 So where body parts have long lines, it is recommended to use a MIME encoding that folds lines (quoted printable).

3. SMTP Extensions

There are several RFCs that specify extensions to SMTP. Most of these aren't relevant to MIXER, but the NOTARY work to support delivery reports defines extensions that are [29] 👀 Use of these extensions by a MIXER gateway is optional. If they are used, they shall be used in the manner described below.

3.1. SMTP Extension mapping to X.400

Mappings are defined for the following extensions:

NOTIFY This is used to set the report and non-delivery bits of MTA.PerRecipientMessageTransferFields.per-recipient-indicators. If the value is NEVER, both bits are zero. If SUCCESS is present, the report bit is set. Otherwise, the non-delivery-report bit is set. If the gateway uses the NOTIFY command, it shall perform this mapping in all cases.

ORCPT If the address type of the original recipient is "x400" or "rfc822", this may be used at the MTS level to generate an element of redirection history. The redirection date is the date of conversion and the reason is set to "alias".

ENVID If present, this may be used to generate a content correlator. It's used rather than the MTS Identifier, since the ENVID is unique for the UA only and is likely to be too large to map to an MTS identifier. The content correlator is encoded as an IA5 String containing the ENVID, prefixed by "SMTP/NOTARY ENVID: ".

If the ENVID starts with "X400-MTS-Identifier: ", then this ENVID was generated from an X.400 MTS Identifier. The reverse mapping defined in Section 3.2 of Appendix A shall not be used, as this may cause problems in certain situations (e.g., where the message was expanded by an Internet mailing list). 🙈

3.2. X.400 Mapping to SMTP Extensions

The following extensions may be used as a part of the MIXER mapping:

NOTIFY The originator-report and originator-non-delivery-report bits of MTA.PerRecipientMessageTransferFields.per-recipient-indicators decide how this is used. If both bits are zero, the parameter is NEVER. If the report bit is set, SUCCESS is used. Otherwise, FAILURE is used. If this is done, the gateway shall not generate a delivery report for this recipient, unless that's needed where the originating MTA service report requirements differ from the user requirements. Additional originating MTA requirements are satisfied by the gateway.

ORCPT If MTS.perRecipientDeliveryFields.originally-intended-recipient-name is present, the ORCPT command may be used to carry this value, using the "x400" syntax.

ENVID This may be generated, with the value taken from MTS.MessageDeliveryEnvelope.message-delivery-identifer. If this is done, it shall be encoded as EBNF.mts-msg-id, preceded by the string "X400-MTS-Identifier: ".

RET If MTA.PerMessageTransferFields.per-message-indicators.content-return-request is set to FALSE, the parameter RET may be set to HDRS, to specify return of headers only.

Appendix B - Mapping with X.400(1984) 🌸

This appendix defines modifications to the mapping for use with X.400(1984).

The X.400(1984) protocols are a proper subset of X.400(1988). When mapping from X.400(1984) to RFC 822, no changes to this specification are needed.

When mapping from RFC 822 to X.400(1984), no use can be made of 1988 specific features, and no such features are used at the MTS level. The heading extension feature is used at the IPMS level, and this shall be replaced by the RFC 987 approach. All header information that would usually be mapped into the rfc-822-heading-list extension is mapped into a single IA5 body part, which is the first body part in the message. This body part starts with the string "RFC-822-Headers:" as its first line, and the headers follow that line. This specification requires correct reverse mapping of this format, either from 1988 or 1984. RFC 822 extended headers which could be mapped into X.400(1988) elements are also mapped to the body part.

In an environment where RFC 822 is of major importance, it may be desirable for downgrading to consider the case where the message was originated in an RFC 822 system and mapped according to this specification. The rfc-822-heading-list extension may be mapped according to this appendix.

When parsing std-or, the following restrictions shall be observed:

  • Only the 84/88 attributes identified in the table in Section 4.2 are present.
  • No teletex encoding is allowed.

If an address violates this, it shall be treated as an RFC 822 address, which will usually lead to encoding as a DDA "RFC-822".

It is possible that attributes of zero length may be present in an OR Address. This is not legal in 1988, except for ADMD, where the case is explicitly described in Section 4.3.5. Attributes of zero length are deprecated (the attribute shall be omitted), so they will be unusual. However, some systems generate them and rely on them. Therefore, any null attribute shall be encoded using the std-or encoding (e.g., /O=/).

If a non-Teletex Common Name (CN) is present, it shall be mapped onto a Domain Defined Attribute "Common". This is in line with RFC 1328 on X.400 1988 to 1984 downgrading [22].

This specification defines a mapping of the Internet message framework to X.400. Body part mappings are defined in RFC 2157 [6], which relies on X.400(88) features. Downgrading to X.400(84) for body parts is defined in RFC 1496 (HARPOON), which shall be followed in the context of this appendix [5].

Appendix C - RFC 822 Extensions for X.400 access ✨

This appendix defines a number of optional mappings that may be provided to give access from RFC 822 to a number of X.400 services. These mappings are beyond the basic scope of this specification. There has been a definite demand to use extended RFC 822 as a mechanism to access X.400, and these extensions provide access to certain features. If this functionality is provided, this appendix shall be followed. The following headings are defined:

extended-heading =
    "Prevent-NonDelivery-Report" ":"
    / "Generate-Delivery-Report" ":"
    / "Alternate-Recipient" ":" prohibition
    / "Disclose-Recipients" ":"  prohibition
    / "X400-Content-Return" ":" prohibition

Prevent-NonDelivery-Report and Generate-Delivery-Report allow setting of MTS.PerRecipientSubmissionFields.originator-report-request. The setting will be the same for all recipients.

Alternate-Recipient, Disclose-Recipients, and X400-Content-Return allow for override of the default settings for MTS.PerMessageIndicators.

Use of NOTARY mechanisms is a preferred mechanism for controlling these parameters. 🦋

Appendix D - Object Identifier Assignment 💜

The following Object Identifiers shall be used.

internet ::= OBJECT IDENTIFIER  { iso org(3) dod(6) 1 } -- from RFC
1155

mail OBJECT IDENTIFIER ::= { internet 7 }  -- IANA assigned

mixer OBJECT IDENTIFIER ::= { mail mixer(1) } -- inherited from RFC
1495
mixer-core OBJECT IDENTIFIER ::= { mixer core(3) }

id-rfc-822-field-list OBJECT IDENTIFIER ::= {mixer-core 2}
id-dsn-header-list OBJECT IDENTIFIER ::= {mixer-core 3}
id-dsn-field-list OBJECT IDENTIFIER ::= {mixer-core 4}

eit-mixer OBJECT IDENTIFIER ::= {mixer-core 5}
               -- the MIXER pseudo-EIT

This object identifier for id-rfc-822-field-list is different to the one assigned in RFC 1327, which was erroneous. Oops, we don't do that anymore 🙈

Appendix E - BNF Summary ✨

okay so this is the cheat sheet bestie 🧚 every grammar rule from the whole spec, all in one place so you can look stuff up without digging around. the ::= ones use a different notation than the = ones, so don't be confused if they look a little different 🙈

boolean = "TRUE" / "FALSE"


numericstring = *(DIGIT / " ")


printablestring  = *( ps-char )
ps-restricted-char      = 1DIGIT /  1ALPHA / " " / "'" / "+"
                          / "," / "-" / "." / "/" / ":" / "=" / "?"
ps-delim         = "(" / ")"
ps-char          = ps-delim / ps-restricted-char


ps-encoded       = *( ps-restricted-char / ps-encoded-char )
ps-encoded-char  = "(a)"               ; (@)
                   / "(p)"               ; (%)
                   / "(b)"               ; (!)
                   / "(q)"               ; (")
                   / "(u)"               ; (_)
                   / "(l)"               ; "("
                   / "(r)"               ; ")"
                   / "(" 3DIGIT ")"

teletex-string   = *( ps-char / t61-encoded )
t61-encoded      = "{" 1* t61-encoded-char "}"
t61-encoded-char = 3DIGIT


teletex-and-or-ps = [ printablestring ] [ "*" teletex-string ]


labelled-integer ::= [ key-string ] "(" numericstring ")"

labelled-integer-2 ::= [ numericstring ] "(" key-string ")"

key-string      = *key-char
key-char        = <a-z, A-Z, 0-9, and "-">

object-identifier  ::= oid-comp object-identifier
                       | oid-comp

oid-comp ::= [ key-string ] "(" numericstring ")"


encoded-info    = 1#encoded-type
encoded-type    = built-in-eit / object-identifier

built-in-eit    = "Undefined"         ; undefined (0)
                / "Telex"             ; tLX (1)
                / "IA5-Text"          ; iA5Text (2)
                / "G3-Fax"            ; g3Fax (3)
                / "TIF0"              ; tIF0 (4)
                / "Teletex"           ; tTX (5)
                / "Videotex"          ; videotex (6)
                / "Voice"             ; voice (7)
                / "SFD"               ; sFD (8)
                / "TIF1"              ; tIF1 (9)



encoded-pn      = [ given "." ] *( initial "." ) surname

given           = 2*<ps-char not including ".">

initial         = ALPHA

surname         = printablestring


std-or-address  = 1*( "/" attribute "=" value ) "/"
attribute       = standard-type
                / "RFC-822"
                / dd-key "." std-printablestring

std-or-address-input =  [ sep pair ] sep  pair *( sep pair )
                       sep  [ pair sep ]

sep             = "/" / ";"
pair            = input-attribute "=" value
input-attribute = attribute
                / dd-key ":" std-printablestring


standard-type   = key-string

dd-key          = key-string

value           = std-printablestring

std-printablestring
                = *( std-char / std-pair )

std-char        = <"{", "}", "*", and any ps-char

                                             except "/" and "=" >
std-pair        = "$" ps-char


global-id = std-or-address



mta-field       = "X400-Received" ":" x400-trace
                / "Deferred-Delivery" ":" date-time
                / "Latest-Delivery-Time" ":" date-time



x400-trace       = "by" md-and-mta ";"
                 [ "deferred until" date-time ";" ]
                 [ "converted" "(" encoded-info ")" ";" ]
                 [ "attempted" md-or-mta ";"  ]
                    action-list
                    ";" arrival-time


md-and-mta       = [ "mta" mta "in" ]  global-id
mta              = word
arrival-time     = date-time

md-or-mta        = "MD" global-id
                 / "MTA" mta

Action-list      = 1#action
action           = "Redirected"
                 / "Expanded"
                 / "Relayed"
                 / "Rerouted"

dr-user-info = dr-summary <CRLF>
               dr-recipients <CRLF>
               dr-content-return


dr-content-return = "The Original Message is not available"
     / "The Original Message follows:"

dr-summary = "This report relates to your message:" <CRLF>
                content-correlator <CRLF> <CRLF>
             "of" date-time <CRLF> <CRLF>

dr-recipients = *(dr-recipient <CRLF> <CRLF>)
dr-recipient = dr-recip-success / dr-recip-failure

dr-recip-success =
                "Your message was successfully delivered to:"
                 mailbox "at" date-time


dr-recip-failure = "Your message was not delivered to:"
                        mailbox <CRLF>
                "for the following reason:" *word

report-point = [ "mta" mta-name "in" ] global-id
content-correlator = *word
mta-name = word

   dr-per-message-fields =
             / "X400-Conversion-Date" ":" date-time
             / "X400-Subject-Submision-Identifier" ":"
                                   mts-msg-id
             / "X400-Content-Identifier" ":" printablestring
             / "X400-Content-Type" ":" mts-content-type
             / "X400-Original-Encoded-Information-Types" ":"
                           encoded-info
             / "X400-Originator-and-DL-Expansion-History" ":"
                           mailbox ";" date-time ";"
             / "X400-Reporting-DL-Name" ":" mailbox
             / "X400-Content-Correlator" ":" content-correlator
             / "X400-Recipient-Info" ":" recipient-info
             / "X400-Subject-Intermediate-Trace-Information" ":"
                                     x400-trace
             / dr-extensions


   dr-per-recipient-fields =
             / "X400-Redirect-Recipient" ":" "x400" ";" std-or
             / "X400-Mapped-Redirect-Recipient" ":" "rfc822" ";"
                   mailbox
             / "X400-Converted-EITs" ":" encoded-info ";"
             / "X400-Delivery-Time" ":" date-time
             / "X400-Type-of-MTS-User" ":" labelled-integer
             / "X400-Last-Trace" ":" [ encoded-info ] date-time
             / "X400-Supplementary-Info" ":"
                   <"> printablestring <"> ";"
             / "X400-Redirection-History" ":" redirect-history-item
             / "X400-Physical-Forwarding-Address" ":" mailbox
             / "X400-Originally-Specified-Recipient-Number" ":"
                   integer
             / dr-extensions

   dr-extensions = "X400-Discarded-DR-Extensions" ":"
                     1# (object-identifier / labelled-integer)


   dr-diagnostic = "Reason" labelled-integer-2
                   [ ";" "Diagnostic" labelled-integer-2 ]

   mts-field = "X400-MTS-Identifier" ":" mts-msg-id
             / "X400-Originator" ":" mailbox
             / "X400-Recipients" ":" 1#mailbox
             / "Original-Encoded-Information-Types" ":"
                             encoded-info
             / "X400-Content-Type" ":" mts-content-type
             / "X400-Content-Identifier" ":" printablestring
             / "Priority" ":" priority
             / "Originator-Return-Address" ":" 1#mailbox
             / "DL-Expansion-History" ":" mailbox ";" date-time ";"
             / "Conversion" ":" prohibition
             / "Conversion-With-Loss" ":" prohibition
             / "Delivery-Date" ":" date-time
             / "Discarded-X400-MTS-Extensions" ":"
                          1#( object-identifier / labelled-integer )

   prohibition     = "Prohibited" / "Allowed"

   mts-msg-id       = "[" global-id ";" *text "]"

   mts-content-type = "P2" /  labelled-integer
                   / object-identifier

   priority        = "normal" / "non-urgent" / "urgent"

   ipn-body-format = ipn-description <CRLF>
                   [ ipn-extra-information <CRLF> ]
                   [ ipn-content-return ]

   ipn-description = ipn-receipt / ipn-non-receipt

   ipn-receipt = "Your message to:" preferred-recipient <CRLF>
            "was received at" receipt-time <CRLF> <CRLF>
            "This notification was generated"
             acknowledgement-mode <CRLF>
            "The following extra information was given:" <CRLF>
             ipn-suppl <CRLF>

   ipn-non-receipt = "Your message to:"
           preferred-recipient <CRLF>
           ipn-reason

   ipn-reason = ipn-discarded / ipn-auto-forwarded

   ipn-discarded = "was discarded for the following reason:"
                   discard-reason <CRLF>

   ipn-auto-forwarded = "was automatically forwarded." <CRLF>
                   [ "The following comment was made:"
                           auto-comment ]


   ipn-extra-information =
            "The following information types were converted:"
            encoded-info

   ipn-content-return = "The Original Message is not available"
                   / "The Original Message follows:"

   preferred-recipient = mailbox
   receipt-time        = date-time
   auto-comment        = printablestring
   ipn-suppl           = printablestring


   discard-reason     = "Expired" / "Obsoleted" /
               "User Subscription Terminated" / "IPM Deleted"

   acknowledgement-mode = "Manually" / "Automatically"


   ipms-field = "Supersedes" ":" 1*msg-id
              / "Expires" ":" date-time
              / "Reply-By" ":" date-time
              / "Importance" ":" importance
              / "Sensitivity" ":" sensitivity
              / "Autoforwarded" ":" boolean
              / "Incomplete-Copy" ":"
              / "Content-Language" ":" 1#language
              / "Message-Type" ":" message-type
              / "Discarded-X400-IPMS-Extensions" ":"
                    1#object-identifier
              / "Autosubmitted" ":" autosubmitted

   importance      = "low" / "normal" / "high"

   sensitivity     = "Personal" / "Private" /
                          "Company-Confidential"

   language        = 2*ALPHA [ "(" language-description ")" ]
   language-description = printable-string


   message-type    = "Delivery Report"
                   / "InterPersonal Notification"
                   / "Multiple Part"


   autosubmitted   = "not-auto-submitted"
                   / "auto-generated"
                   / "auto-replied"
                   / "auto-forwarded"

   redirect-comment  = redirect-first *( redirect-subsequent )

   redirect-first = "Originally To:"  mailbox  "Redirected on"
            date-time "To:"  redirection-reason

   redirect-subsequent = mailbox  "Redirected Again on"
            date-time "To:"  redirection-reason

   redirection-history-item = "intended recipient" mailbox
            "redirected to"  redirection-reason
            "on" date-time

   redirection-reason =
            "Recipient Assigned Alternate Recipient"
            / "Originator Requested Alternate Recipient"
            / "Recipient MD Assigned Alternate Recipient"
            / "Directory Look Up"
            / "Alias"

   subject-line  = "Delivery-Report" "(" status ")"
                   [ "for" destination ]

   status        = "success" / "failure" / "success and failures"

   destination   = mailbox / "MTA" word

   extended-heading =
       "Prevent-NonDelivery-Report" ":"
       / "Generate-Delivery-Report" ":"
       / "Alternate-Recipient" ":" prohibition
       / "Disclose-Recipients" ":"  prohibition
       / "X400-Content-Return" ":" prohibition

Appendix F - Text format for MCGAM distribution 🦋

1. Text Formats 💖

ok so this appendix is all about the text formats you use when you're trading these four kinds of mapping around, like the little notes that get passed back and forth 💌

  1. Domain Name Space -> OR Address Space MCGAM
  2. OR Address Space -> Domain Name Space MCGAM
  3. Domain Name Space -> OR Address of preferred gateway
  4. OR Address Space -> Domain Name of preferred gateway

2. Mechanisms to register and to distribute MCGAMs ✨

okay so there's a well known set of MCGAM tables 📚 bestie, they're the official lookup lists everyone uses 🫶

The global coordination of the mapping rules is part of the DANTE MailFLOW Project 🦋 New mapping rules can be defined by the authority responsible for the relevant name space. Those rules need to get registered with a national mapping registration authority, which then passes them up to the central mapping registration authority. The MailFLOW Project Team merges all the collected rules into the globally coordinated mapping tables 💅 and you can grab those tables from the national mapping registration authorities 🌸

Want the contact address for the mapping registration authority in your country, or just more info about the MailFLOW Project? Here's the deets 💌

   SWITCH
   MailFLOW Project Team
   Limmatquai 138
   8001 Zuerich
   Switzerland

   email: mailflow@mailflow.dante.net
          S=MailFLOW;O=MailFLOW;P=DANTE;A=mailnet;C=fi;

   fax:   +41 1 268 15 68
   tel:   +41 1 268 15 20

3. Syntax Definitions 🎀

so the address syntax is built to be compatible with the syntax used for 822.domains 🧚 By representing OR addresses as domains, every lookup can be done mechanically as a domain -> domain mapping, which is honestly iconic 😭 This syntax is set up for table format at first, but it's designed so it can be adapted for use with the Domain Name Service. It can represent OR addresses in general, so other applications can use it too. Not every attribute gets used in the table formats, though.

To allow a mapping where a level of the hierarchy is left out, the pseudo-value "@" (not a printable string character) is used to show that a level is omitted 🙈 This is different from the form that includes the element with no value, although a correct X.400 implementation will interpret both in the same way. ngl that's a very specific detail, but it matters 💜

This syntax is not meant to be handled by users 🫣

dmn-or-address  = dmn-part *( "." dmn-part )
mn-part        = dmn-attribute "$" value
dmn-attribute  = standard-type
                /  "~" dmn-printablestring
value           = dmn-printablestring
                / "@"
dmn-printablestring =
                = *( dmn-char / dmn-pair )
dmn-char        = <"{", "}", "*", and any ps-char
                                        except ".">
dmn-pair        = "\."

An example usage:

~ROLE$Big\.Chief.ADMD$ATT.C$US
PRMD$DEC.ADMD$@.C$US

The first example shows how a "." gets quoted, plus a domain defining attribute (ROLE) 🎀 The second example shows the ADMD level being omitted 🌈 There shall be a strict ordering of all components in this table, with the most significant components on the RHS. That's what lets the encoding be treated as a domain ✨

Various further restrictions apply to how dmn-or-address is used in the address space mapping tables 👑

a. Only C, ADMD, PRMD, O, and up to four OUs may be used.

b. No components shall be omitted from this hierarchy, although the hierarchy may terminate at any level. If the mapping is to an omitted component, the "@" syntax is used.

4. Table Lookups 💖

when it's time to find a match, some stuff applies to every lookup 🔍 Matches are always case independent 🫶 The key for all three tables is a domain. The longest possible match shall be obtained. Say the table has two entries with these keys:

K.L
J.K.L

Domain "A.B.C" won't return any matches 💀 Domain "I.J.K.L" will match the entry "J.K.L:. 🦋

5. Domain -> OR Address MCGAM format 🌸

the BNF is:

domain-syntax "#" dmn-or-address "#"

EBNF.domain-syntax is defined in Section 4.2. The trailing "#" is there for clarity, since the dmn-or-address syntax might lead to values with trailing blanks 🙈 Lines starting with "#" are comments 💬

For example:

AC.UK#PRMD$UK\.AC.ADMD$GOLD 400.C$GB#
XEROX.COM#O$Xerox.ADMD$ATT.C$US#
GMD.DE#O$@.PRMD$GMD.ADMD$DBP.C$DE#

A domain gets looked up to figure out the top levels of an OR Address. Any components of the domain that don't match are used to build the rest of the OR address, as described in Section 4.3.4 🧚

6. OR Address -> Domain MCGAM format 💜

the syntax of this table is:

dmn-or-address "#" domain-syntax "#"

For example:

#
# Mapping table
#
PRMD$UK\.AC.ADMD$GOLD 400.C$GB#AC.UK#

The OR Address gets used to generate a domain key. It's important to order the components correctly and fill in any missing components in the hierarchy 🫶 How this mapping gets used is described in Section 4.3.2 ✨

7. Domain -> OR Address of Preferred Gateway table 👑

this uses the same format as the domain -> OR address MCGAM table 💅 In this case, the restriction to only use C/ADMD/PRMD/O/OU does not apply. How this mapping gets used is described in Section 4.3.4. A domain cannot appear in this table and in the domain to OR Address table 🚫

8. OR Addresss -> domain of Preferred Gateway table 🌈

this uses the same format as the OR Address -> domain MCGAM table 🎀 How this mapping gets used is described in Section 4.3.5. An OR Address cannot appear in this table and in the OR Address to domain table ⭐

Appendix G - Conformance 🫶

this appendix defines a bunch of options, which a conforming gateway shall specify 🔥 You can't claim conformance if any of the mandatory features aren't implemented 😭 A specification of conformance may list the service elements of Chapter 2, so it's super clear that full conformance is provied. Specifically:

  • Formats for all fields shall be followed.
  • The gateway shall enable MCGAMs to be used.
  • Formats for subject lines, delivery reports and IPNs shall be followed. A system which followed the syntax, but translated text into a language other than english would be conformant. 🌍
  • RFC 1137 shall not be followed when mapping to SMTP.
  • All mappings of trace shall be implemented.
  • There shall be a mechanism to access all three global mappings.
  • RFC 2157 shall be followed for mapping body parts.
  • When it is specified that a MIME format message is generated, RFC 2045 shall be followed.

A gateway shall specify:

  • Which Interent Message Transport (822-MTS) protocols are supported. If SMTP is supported, Appendex A of MIXER shall be used.
  • Which X.400 versions are supported (84, 88, 92).
  • Which mechanisms (table, X.500, DNS) are supported to access MCGAMs.
  • The mechanism or mechanisms by which the global mapping information is accessed.

The following are optional parts of this specification. A conforming implementation shall specify which of these it supports 💖

  • Support for the extension mappings of Appendix C.
  • Support for returning illegal format content in a delivery report.
  • Which address interpretation heuristics are supported (4.3.4.1).
  • If RFC 987 generated message ids are handled in a backwards compatible manner (4.7.3.6).

Appendix H - Change History: RFC 987, 1026, 1138, 1148 🦋

RFC 987 was the original document, and had the key elements of this specification 🌸 It was specific to X.400(1984). RFC 1026 specified a small number of necessary changes to RFC 987 ✨

RFC 1138 was based on the RFC 987 work. It had an editorial error, so it got reissued a few months later as RFC 1148 😭 RFC 1148 is what this document will refer to, since it's the one that everyone else cites 💅 The major goal of RFC 1148 was upgrading RFC 987 to X.400(1988). It did that, but it didn't obsolete RFC 987, which was recommended for use with X.400(1984). This appendix summarises the changes from RFC 987 to RFC 1148 🧚

RFC 1148 noted the following about its upgrade from RFC 987:

Unnecessary change is usually a bad idea. Changes on the RFC 822 side are avoided as far as possible, so that RFC 822 users do not see arbitrary differences between systems conforming to this specification, and those following RFC 987. Changes on the X.400 side are minimised, but are more acceptable, due to the mapping onto a new set of services and protocols. 🫶

1. Introduction 🌈

the model has shifted from a protocol based mapping to a service based mapping. This has increased the generality of the specification and improved the model 👑 This change affects the entire document.

A restriction on scope has been added ⭐

2. Service Elements 💜

  • The new service elements of X.400 are dealt with.
  • A clear distinction is made between origination and reception.

3. Basic Mappings 🎀

  • Add teletex support.
  • Add object identifier support.
  • Add labelled integer support.
  • Make PrintableString <-> ASCII mapping reversible.
  • The printable string mapping is aligned to the NBS mapping derived from RFC 987.

4. Addressing 🍓

  • Support for new addressing attributes.
  • The message ID mapping is changed to not be table driven.

5. Detailed Mappings 🔥

  • Define extended IPM Header, and use instead of second body part for RFC 822 extensions.
  • Realignment of element names.
  • New syntax for reports, simplifying the header and introducing a mandatory body format (the RFC 987 header format was unusable).
  • Drop complex autoforwarded mapping.
  • Add full mapping for IP Notifications, defining a body format.
  • Adopt an MTS Identifier syntax in line with the OR Address syntax.
  • A new format for X400 Trace representation on the RFC 822 side.

6. Appendices 🧚

  • Move Appendix on restricted 822 mappings to a separate RFC.
  • Delete Phonenet and SMTP Appendixes.

Appendix I - Change History: RFC 1148 to RFC 1327 💖

1. General 🌸

  • The scope of the document was changed to cover X.400(1984), and so obsolete RFC 987.
  • Changes were made to allow usage to connect RFC 822 networks using X.400.
  • Text was tightened to be clear about optional and mandatory aspects.
  • A good deal of clarification.
  • A number of minor EBNF errors.
  • Better examples are given.
  • Further X.400 upper bounds are handled correctly.

2. Basic Mappings ✨

  • The encoding of object identifier is changed slightly.

3. Addressing 💅

  • A global mapping of domain to preferred gateway is introduced.
  • An overflow mechanism is defined for RFC 822 addresses of greater than 128 bytes.
  • Changes were made to improve compatibility with the PDAM on writing OR Addresses.
    • The PD and Terminal Type keywords were aligned to the PDAM. It is believed that minimal use has been made of the RFC 1148 keywords.
    • P and A are allowed as alternate keys for PRMD and ADMD.
    • Where keywords are different, the PDAM keywords are alternatives on input. This is mandatory.

4. Detailed Mappings 🦋

  • The format of the Subject: lines is defined.
  • Illegal use (repetition) of the heading EXTENSION is corrected, and a new object identifier assigned.
  • The Delivery Report format is extensively revised in light of operational experience.
  • The handling of redirects is significantly changed, as the previous mechanism did not work. 🙈

5. Appendices 💅

  • An SMTP appendix is added, allowing optional use of the VRFY command to improve probe information. 📬
  • Handling of JNT Mail Acknowledge-To is changed slightly. 🔄
  • A DDA JNT-MAIL is allowed on input. 📥
  • The format definitions of Appendix F are explained further, and a third table definition added. 📊
  • An appendix on use with X.400(1984) is added. 🗂️
  • Optional extensions are defined to give RFC 822 access to further X.400 facilities. 🔓
  • An appendix on conformance is added. ✅

Appendix J - Change History: RFC 1327 to this Document ✨

1. General

This update is primarily for stability, and to fold in compatibility for MIME and to add support for the new NOTARY delivery status notifications. Other general changes:

  • Various editorial updates ✏️
  • Minor EBNF errors 🐛
  • Reference to mapping table support by DNS and X.500. 🗺️
  • Alignment to X.400(92) 🤝
  • Assignment of a new object identifier 🆔
  • Removal of specification relating to body mapping, which is now defined in RFC 2157. 👋

2. Service Elements

  • Support of Auto-Submitted service 🤖

3. Basic Mappings

  • Comments shall not be used in new headers, to remove parsing ambiguity 🚫
  • RFC 1522 encoding may be used as an alternative to X.408 downgrade, where appropriate. 🎀
  • Correct handling of RFC 822 four year dates. 📅

4. Addressing 🏠

  • Replaced the mandatory global address mapping with MCGAMs.
  • Add codes and add a heuristic to align to the standard X.400 form of writing OR Addresses.
  • Improved text on ordering heuristic
  • Leading "/" interpretation added
  • All bar one of the address mapping heuristics made mandatory.
  • Interpretation of domain defined attribute "RFC-822" made mandatory in all cases
  • Make report request comments optional

5. Detailed Mappings 🧩

  • Comments no longer maps to separate body part
  • Allow Languages to be multi-valued 🌍
  • Change Content-Identifier to X400-Content-Identifier, in order to avoid confusion with MIME. 🙈
  • Reverse mapping of MIXER defined fields made mandatory
  • "Expiry-Date:" changed to "Expires:".
  • "Obsoletes:" changed to "Supersedes:".
  • Define correct handling when "Resent-Date:" is present.

6. Appendices 🌸

  • Change "Content-Return" to "X400-Content-Return" in Appendix C.
  • Relaxation of restrictions on mapping 3 in Appendix F.
  • Add linkage to HARPOON in Appendix B.
  • RFC 2157 added to the conformance statement of Appendix G.
  • Added Appendix L, with ASN. Summary. 🎉

Appendix L - ASN.1 Summary 🧚

   MIXER Definitions { iso org(3) dod(6) internet(1) mail(7)
         mixer(1) mixer-core(3) definitions(1) }

   DEFINITIONS IMPLICIT TAGS ::=

   BEGIN

   -- exports everything

   IMPORTS

   EXTENSION FROM
     MTSAbstractService {join-iso-ccit mhs-motis(6) mts(3)
           modules(0) mts-abstract-service(1) }

     HEADING-EXTENSION FROM
       IPMSAbstractService {join-iso-ccit mhs-motis(6) ipms(1)
             modules(0) abstract-service(3) }



   rfc-822-field HEADING-EXTENSION
           VALUE RFC822FieldList
           ::= id-rfc-822-field-list


   RFC822FieldList ::= SEQUENCE OF RFC822Field

   RFC822Field ::= IA5String



   dsn-header-list EXTENSION
      RFC822FieldList
      ::= id-dsn-header-list

   dsn-field-list EXTENSION
      RFC822FieldList
      ::= id-dsn-field-list

   internet ::= OBJECT IDENTIFIER  { iso org(3) dod(6) 1 } -- from RFC
   1155

   mail OBJECT IDENTIFIER ::= { internet 7 }  -- IANA assigned
   mixer OBJECT IDENTIFIER ::= { mail mixer(1) } -- inherited from RFC
   1495
   mixer-core OBJECT IDENTIFIER ::= { mixer core(3) }

   id-rfc-822-field-list OBJECT IDENTIFIER ::= {mixer-core 2}
   id-dsn-header-list OBJECT IDENTIFIER ::= {mixer-core 3}
   id-dsn-field-list OBJECT IDENTIFIER ::= {mixer-core 4}

   eit-mixer OBJECT IDENTIFIER ::= {mixer-core 5}
                   -- the MIXER pseudo-EIT


   END -- MIXER ASN.1

SECURITY CONSIDERATIONS 🚨

Security issues are not discussed in this memo. 💀 Yes, that is the whole section, and it's giving very "we'll get to it later" energy, so take it seriously, bestie. 🙈

AUTHOR'S ADDRESS 💌

   Steve Kille
   Isode Ltd
   The Dome
   The Square
   Richmond
   TW9 1DT
   England

   Phone: +44-181-332-9091
   Internet EMail: S.Kille@ISODE.COM

   X.400 Email: I=S; S=Kille; P=Isode; A=Mailnet; C=FI;

   UFN:  S.Kille, Isode, GB

References 📚

  1. CCITT , "Recommendations X.400", Message Handling Systems: System Model - Service Elements, October 1984.
  2. Allocchio, C., "MaXIM11 - Mapping between X.400 / Internet Mail and Mail-11 mail", RFC 2162, January 1998.
  3. Allocchio, C., "Using the Internet DNS to Distribute MIXER Conformant Global Address Mapping (MCGAM)", RFC 2163, January 1998.
  4. Alvestrand, H., Kille, S., Miles, R., Rose, M., and S. Thompson, "Mapping between X.400 and RFC-822 Message Bodies", RFC 1495, August 1993.
  5. Alvestrand, H., Romaguera, J., and K. Jordan, "Rules for Downgrading Messages for X.400(88) to X.400(84) When MIME Content-Types are Present in the Messages (Harpoon)", RFC 1496, August 1993.
  6. Alvestrand, H., and S. Thompson, "Equivalences between X.400 and RFC-822 Message Bodies", RFC 1494, August 1993.
  7. Alvestrand, H., "Tags for the Identification of Languages", RFC 1766, March 1995.
  8. Alvestrand, H., "Mapping between X.400 and RFC-822/MIME Message Bodies", RFC 2157, January 1998.
  9. Freed, N., and N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies", RFC 2045, November 1996.
  10. Braden, R., "Requirements for Internet Hosts -- Application and Support", STD 3, RFC 1123, October 1989.
  11. CCITT/ISO, "CCITT Recommendations X.420/ ISO/IEC 10021-7," Message Handling Systems: Interpersonal Messaging System, Dec 1988.
  12. CCITT/ISO, "CCITT Recommendations X.411/ ISO/IEC 10021-4," Message Handling Systems: Message Transfer System: Abstract Service Definition and Procedures, Dec 1988.
  13. CCITT/ISO, "CCITT Recommendations X.400/ ISO/IEC 10021-1," Message Handling: System and Service Overview , Dec 1988.
  14. CCITT/ISO, "Specification of Abstract Syntax Notation One (ASN.1)," CCITT Recommendation X.208 / ISO/IEC 8824, Dec 1988.
  15. CCITT/ISO, "CCITT Recommendations X.400/ ISO/IEC 10021-1," Message Handling: System and Service Overview , Dec 1992.
  16. Crocker, D., "Standard of the Format of ARPA Internet Text Messages", STD 11, RFC 822, August 1982.
  17. Kille, S., "Mapping Between X.400 and RFC 822", UK Academic Community Report (MG.19) / RFC 987, June 1986.
  18. Kille, S., "Addendum to RFC 987", UK Academic Community Report (MG.23) / RFC 1026, August 1987.
  19. Kille, S., "Mapping Between X.400(1988) / ISO 10021 and RFC 822", RFC 1138, October 1989.
  20. Kille, S., "Mapping Between X.400(1988) / ISO 10021 and RFC 822", RFC 1148, March 1990.
  21. Kille, S., "Mapping Between X.400(1988) / ISO 10021 and RFC 822", RFC 1327, May 1992.
  22. Kille, S., "X.400 1988 to 1984 downgrading", RFC 1328, May 1992.
  23. Kille, S., "A String Encoding of Presentation Address", RFC 1278, November 1992.
  24. Kille, S., "A String Representation of Distinguished Name", RFC 1485, January 1992.
  25. Kille, S., "Using the OSI Directory to achieve User Friendly Naming", RFC 1484, January 1992.
  26. Kille, S., "Use of an X.500/LDAP directory to support MIXER address mapping", RFC 2164, January 1998.
  27. Koorland, N., "Message Attachmment Work Group (MAWG): MAWG Feasibility Project Guide," EMA Report, Version 1.5, Nov 1995.
  28. Moore, K., and G. Vaudreuil, "An Extensible Message Format for Delivery Status Notifications", RFC 1894, January 1996.
  29. Moore, K., "SMTP Service Extensions for Delivery Status Notifications", RFC 1891, Januaty 1996.
  30. Postel, J., "SIMPLE MAIL TRANSFER PROTOCOL", STD 10, RFC 821, August 1982.

Copyright (C) The Internet Society (1998). All Rights Reserved.

This document and translations of it may be copied and furnished to others, and derivative works that comment on or otherwise explain it or assist in its implementation may be prepared, copied, published and distributed, in whole or in part, without restriction of any kind, provided that the above copyright notice and this paragraph are included on all such copies and derivative works. However, this document itself may not be modified in any way, such as by removing the copyright notice or references to the Internet Society or other Internet organizations, except as needed for the purpose of developing Internet standards in which case the procedures for copyrights defined in the Internet Standards process must be followed, or as required to translate it into languages other than English.

The limited permissions granted above are perpetual and will not be revoked by the Internet Society or its successors or assigns.

This document and the information contained herein is provided on an "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.

📦 where this page comes from