Despite being incomplete, it can be still be useful and provide
protection for users.
The missing part is the report generation, which is defined as a part of
a minimal implementation by RFC 7489, though.
-- Problem
The way module references are implemented was a big source of confusion,
mainly because in most cases there are at least two possible ways they
are handled. Additionally, for some modules (checks and modifiers) there
is the third way, what doesn't help either.
Consider the following cases of confiugraiton directives:
```
deliver_to smtp_downstream
```
This directive refers to the existing configuration block named
smtp_downstream. It doesn't have to be the instance of the
smtp_downstream module, though.
```
deliver_to smtp_downstream tcp://127.0.0.1:1125
```
This magically turns "reference to an existing block" into an inline
definition. And suddenly the first argument is not an configuration
block name, now it is a module name. Same "sudden" change happens when
the block is added:
```
deliver_to smtp_downstream { ... }
```
For modules having an "implicitly defined" config block, there's
another source of confusion:
```
deliver_to smtp_downstream
```
This directive may refere to the implicitly defined config block with
some default values. But to the user it looks like a module name and
nothing more. It's trickly to explain all dark corners of such behavior
in the user documentation.
Even more, there's another problem with the implementation, these
implicitly defined blocks can't access global directives because they
are defined before the configuration is parsed.
-- Solution
This commit removes the third way of module reference handling. There
are no "implicitly defined" config blocks anymore.
Second, all module references by default create a new module instance.
All following directives create a new module instance, no catches here.
```
deliver_to smtp_downstream
deliver_to smtp_downstream tcp://127.0.0.1:2525
deliver_to smtp_downstream { ... }
```
Although, the first one will fail because smtp_downstream needs at least
one endpoint address somewhere.
Ability to define configuration blocks at a top-level and reference them
in other places is retained for use in cases where it's actually
useful, including the initial idea of "state sharing" (see "Dev:
Comments on design" on the project wiki).
However, such referneces are now explicitly prefixed by the '&'
character. Such as the following:
```
deliver_to &smtp_downstream
```
This directive references the existing configuration block named
"smtp_downstream". Following directives are not allowed as they make no
sense:
```
deliver_to &smtp_downstream tcp://127.0.0.1:2525
deliver_to &smtp_downstream { ... }
```
So, there is no confusion about what happens when.
Closes#167. I decided to not make any radical changes now. Changes
made to the initialization logic solve the actual problem that led to
the creation of the referenced issue.
This allows for some complex but useful configurations, such as making
decision on delivery target based on the result of per-destination
address rewriting. One example where that can be useful is aliasing
local address to a remote address in a way that can't make the server
an open relay.