|
|
# Build Instructions
|
|
|
|
|
|
## Requirements
|
|
|
|
|
|
* Boost (1.63 or newer)
|
|
|
* libiconv
|
|
|
(for Windows: https://github.com/pffang/libiconv-for-Windows )
|
|
|
* pEpEngine – see next section
|
|
|
* GoogleTest (GTest) – not to use library, but to run the unittests. :-)
|
|
|
(for Windows you might follow these instructions:
|
|
|
<https://docs.microsoft.com/en-us/visualstudio/test/how-to-use-google-test-for-cpp?view=vs-2019>)
|
|
|
|
|
|
## Solve the cyclic dependency to pEpEngine
|
|
|
To build p≡p MIME it's necessary that header files of p≡p engine are already
|
|
|
installed. Because of the dependency loop of p≡p MIME needing these headers and
|
|
|
p≡p engine depending on p≡p MIME you best do things in this sequence:
|
|
|
|
|
|
1. cd pEpEngine && make -C src install_headers
|
|
|
1. cd pEpMIME/src && make install
|
|
|
1. cd pEpEngine && make install
|
|
|
|
|
|
The build of p≡p MIME can be customized. Makefile variable PREFIX is the
|
|
|
install directory. The environment variables CXXFLAGS and LDFLAGS are being
|
|
|
used. So a typical build on macOS i.e. looks like this:
|
|
|
|
|
|
CXXFLAGS=-I/opt/local/include LDFLAGS=-L/opt/local/lib make PREFIX=$HOME -j4 all install
|
|
|
|
|
|
# Design criteria of pEpMIME
|
|
|
|
|
|
## Normalization
|
|
|
pEpMIME "normalizes" the MIME messages during parsing, and uses some heuristics especially for
|
|
|
non-MIME-compliant inputs. The generated `struct message` always
|
|
|
|
|
|
* contains UTF-8 NFC-compliant text in `longmsg` and `longmsg_formatted`
|
|
|
* contains appropriate MIME headers, e.g. `Mime-Type` and `charset`
|
|
|
* …
|
|
|
|
|
|
The MIME generator also serializes data in a special and predictive manner:
|
|
|
* Non-7bit data in MIME leaves' headers and bodies are always base64 encoded. "quoted printable"
|
|
|
encoding is never generated.
|
|
|
* MIME delimiter are short and predictive "=pEp=#=", where `#` is the smallest possible
|
|
|
hexadecimal number so the delimiter does not occur in the message.
|
|
|
|
|
|
Due to this normalization there is *no* round-trip guarantee that a generated MIME message is
|
|
|
identical to the original MIME message:
|
|
|
|
|
|
1) "MIME_text" --> `struct message` --> "MIME_text2"
|
|
|
"MIME text" and "MIME_text2" usually differ due to normalization
|
|
|
|
|
|
|
|
|
2) `struct message msg1` --> "MIME_text" --> `struct message msg2`
|
|
|
The content of `msg1` and `msg2` is identical, except …
|
|
|
(*FIXME*: AFAIK there are special bizarre cases, but I don't remember at the moment)
|
|
|
|
|
|
|
|
|
## Special Headers
|
|
|
Additionally pEpMIME adds some internal annotations into `message->opt_fields` using keys that start
|
|
|
with ":pEp:MIME:", a string that can never occur in MIME messages, so they cannot be set by external
|
|
|
attackers. The MIME generator of pEpMIME is aware of these special header lines, acts appropriately
|
|
|
and skips *any* element in `message->opt_fields` that start with ":", so they will never occur as
|
|
|
MIME header in the generated MIME message.
|
|
|
|
|
|
Adapters and clients are allowed to use these special header fields and might also define their own
|
|
|
(with another prefix, so they won't interfere with future pEpMIME headers).
|
|
|
|
|
|
Currently these special headers are used by pEpMIME:
|
|
|
|
|
|
* `:pEp:MIME:longmsg:format` and `:pEp:MIME:longmsg:delsp`: to store the special annotations for
|
|
|
plaintext bodies, according to RFC 3676 <https://datatracker.ietf.org/doc/html/rfc3676>.
|
|
|
* `:pEp:MIME:attachment1:forwarded`: represents the flag `has_possible_pEp_msg` / `has_pEp_msg_attachment`.
|
|
|
This field is used only internally and does not occur in the returned `struct message`.
|
|
|
|