Haraka 3.1.5 → 3.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +1 -1
- package/{Changes.md → CHANGELOG.md} +54 -3
- package/CONTRIBUTORS.md +26 -26
- package/Plugins.md +99 -99
- package/README.md +68 -93
- package/SECURITY.md +178 -0
- package/bin/haraka +7 -14
- package/config/plugins +0 -3
- package/config/smtp_forward.ini +10 -0
- package/config/smtp_proxy.ini +10 -0
- package/connection.js +25 -8
- package/docs/Connection.md +126 -39
- package/docs/CoreConfig.md +92 -74
- package/docs/HAProxy.md +41 -25
- package/docs/Logging.md +68 -38
- package/docs/Outbound.md +124 -179
- package/docs/Plugins.md +38 -59
- package/docs/Transaction.md +78 -83
- package/docs/Tutorial.md +122 -209
- package/docs/plugins/aliases.md +1 -141
- package/docs/plugins/auth/auth_ldap.md +2 -39
- package/docs/plugins/max_unrecognized_commands.md +4 -18
- package/docs/plugins/process_title.md +3 -3
- package/docs/plugins/queue/smtp_forward.md +19 -3
- package/docs/plugins/queue/smtp_proxy.md +10 -2
- package/docs/plugins/reseed_rng.md +11 -13
- package/docs/plugins/tls.md +7 -7
- package/docs/plugins/toobusy.md +10 -4
- package/docs/tutorials/SettingUpOutbound.md +40 -48
- package/endpoint.js +32 -2
- package/haraka.js +1 -1
- package/outbound/hmail.js +42 -41
- package/outbound/index.js +7 -4
- package/outbound/tls.js +2 -43
- package/package.json +51 -61
- package/plugins/auth/auth_base.js +9 -3
- package/plugins/auth/auth_proxy.js +14 -11
- package/plugins/block_me.js +4 -2
- package/plugins/prevent_credential_leaks.js +3 -1
- package/plugins/process_title.js +6 -6
- package/plugins/queue/qmail-queue.js +15 -19
- package/plugins/queue/smtp_forward.js +12 -4
- package/plugins/queue/smtp_proxy.js +14 -3
- package/plugins/tls.js +13 -5
- package/plugins/xclient.js +3 -1
- package/server.js +22 -10
- package/smtp_client.js +20 -11
- package/test/config/block_me.recipient +1 -0
- package/test/config/block_me.senders +1 -0
- package/test/connection.js +258 -0
- package/test/endpoint.js +27 -0
- package/test/outbound/bounce_net_errors.js +3 -2
- package/test/outbound/hmail.js +19 -0
- package/test/outbound/index.js +189 -0
- package/test/outbound/queue.js +92 -0
- package/test/plugins/auth/auth_bridge.js +80 -0
- package/test/plugins/auth/flat_file.js +128 -0
- package/test/plugins/block_me.js +157 -0
- package/test/plugins/data.signatures.js +114 -0
- package/test/plugins/delay_deny.js +263 -0
- package/test/plugins/prevent_credential_leaks.js +178 -0
- package/test/plugins/process_title.js +135 -0
- package/test/plugins/queue/deliver.js +99 -0
- package/test/plugins/queue/discard.js +79 -0
- package/test/plugins/queue/lmtp.js +138 -0
- package/test/plugins/queue/qmail-queue.js +99 -0
- package/test/plugins/queue/quarantine.js +81 -0
- package/test/plugins/queue/smtp_bridge.js +154 -0
- package/test/plugins/queue/smtp_forward.js +42 -6
- package/test/plugins/queue/smtp_proxy.js +139 -0
- package/test/plugins/reseed_rng.js +34 -0
- package/test/plugins/tarpit.js +91 -0
- package/test/plugins/tls.js +25 -0
- package/test/plugins/toobusy.js +21 -0
- package/test/plugins/xclient.js +14 -0
- package/test/server.js +231 -0
- package/test/smtp_client.js +45 -12
- package/test/tls_socket.js +220 -0
- package/tls_socket.js +52 -2
package/docs/Tutorial.md
CHANGED
|
@@ -1,270 +1,183 @@
|
|
|
1
1
|
# Writing Haraka Plugins
|
|
2
2
|
|
|
3
|
-
Part of the joy of using Haraka as your main mail server is having a strong
|
|
4
|
-
plugin based system which means you control all aspects of how your mail is
|
|
5
|
-
processed, accepted, and delivered.
|
|
3
|
+
Part of the joy of using Haraka as your main mail server is having a strong plugin system: you control every aspect of how mail is processed, accepted, and delivered.
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
sort of plugin file of your own to customise how things work. The good news
|
|
9
|
-
is that writing plugins in Haraka is simple, even for novice coders. You
|
|
10
|
-
just need a little knowledge of Javascript (and maybe some understanding of
|
|
11
|
-
Node.js) and the world is your oyster.
|
|
5
|
+
This tutorial walks through a small plugin that supports *disposable addresses*: an email like `user-20271231@example.com` is accepted up until 31 December 2027, after which delivery is rejected. Mail that is still within the validity window is rewritten back to `user@example.com` before it is forwarded on.
|
|
12
6
|
|
|
13
|
-
|
|
14
|
-
email addresses that expire in a short period of time. This is handy if you
|
|
15
|
-
want a _disposable email address_ to use to sign up for a web site that you
|
|
16
|
-
don't wish to continually receive communication from.
|
|
7
|
+
## What You'll Need
|
|
17
8
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
In order to make this simple, we are going to simply let you have tagged
|
|
21
|
-
email addresses such as `user-20120515@domain.com` which will expire on the
|
|
22
|
-
15th May, 2012. Haraka will then check the email has yet to expire, and
|
|
23
|
-
reject mails to that address after the expiry date. If the address hasn't
|
|
24
|
-
expired yet it will re-write the address to `user@domain.com` before onward
|
|
25
|
-
delivery.
|
|
26
|
-
|
|
27
|
-
## What You Will Need
|
|
28
|
-
|
|
29
|
-
- Node.js and npm
|
|
9
|
+
- Node.js (an active LTS release) and npm
|
|
30
10
|
- Haraka
|
|
31
11
|
- A text editor
|
|
32
|
-
- [swaks][
|
|
33
|
-
- A screwdriver
|
|
34
|
-
|
|
35
|
-
[1]: http://jetmore.org/john/code/swaks/
|
|
12
|
+
- [swaks][swaks] for sending test mail
|
|
36
13
|
|
|
37
14
|
## Getting Started
|
|
38
15
|
|
|
39
|
-
|
|
16
|
+
Install Haraka and create a project:
|
|
40
17
|
|
|
41
|
-
|
|
18
|
+
```sh
|
|
19
|
+
sudo npm install -g Haraka
|
|
20
|
+
haraka -i /path/to/new_project
|
|
21
|
+
```
|
|
42
22
|
|
|
43
|
-
|
|
23
|
+
Use a directory that does not yet exist. Now scaffold a plugin:
|
|
44
24
|
|
|
45
|
-
|
|
25
|
+
```sh
|
|
26
|
+
haraka -c /path/to/new_project -p rcpt_to.disposable
|
|
27
|
+
```
|
|
46
28
|
|
|
47
|
-
|
|
29
|
+
`haraka -p` reports the files it created:
|
|
48
30
|
|
|
49
|
-
|
|
31
|
+
```
|
|
32
|
+
Plugin rcpt_to.disposable created
|
|
33
|
+
Now edit javascript in: /path/to/new_project/plugins/rcpt_to.disposable.js
|
|
34
|
+
Add the plugin to config: /path/to/new_project/config/plugins
|
|
35
|
+
And edit documentation in: /path/to/new_project/docs/plugins/rcpt_to.disposable.md
|
|
36
|
+
```
|
|
50
37
|
|
|
51
|
-
|
|
38
|
+
Edit `config/plugins` so the only enabled lines are:
|
|
52
39
|
|
|
53
|
-
|
|
40
|
+
```
|
|
41
|
+
rcpt_to.disposable
|
|
42
|
+
rcpt_to.in_host_list
|
|
43
|
+
queue/test
|
|
44
|
+
```
|
|
54
45
|
|
|
55
|
-
|
|
56
|
-
Now edit javascript in: /path/to/new_project/plugins/rcpt_to.disposable.js
|
|
57
|
-
Add the plugin to config: /path/to/new_project/config/plugins
|
|
58
|
-
And edit documentation in: /path/to/new_project/docs/plugins/rcpt_to.disposable.md
|
|
46
|
+
The ordering matters — the disposable plugin must run *before* `rcpt_to.in_host_list`, which accepts mail for domains listed in `config/host_list`. `queue/test` writes accepted mail to a `.eml` file in `os.tmpdir()` so you can confirm delivery.
|
|
59
47
|
|
|
60
|
-
|
|
61
|
-
set it up to test. Comment out most of the plugins, except for
|
|
62
|
-
`rcpt_to.in_host_list` and add in our new plugin, and change the queue
|
|
63
|
-
plugin to `test_queue`. The final file should look like this:
|
|
48
|
+
Open `plugins/rcpt_to.disposable.js` and start with:
|
|
64
49
|
|
|
65
|
-
|
|
50
|
+
```js
|
|
51
|
+
exports.hook_rcpt = (next, connection, params) => {
|
|
52
|
+
const rcpt = params[0]
|
|
53
|
+
connection.loginfo(`got recipient: ${rcpt}`)
|
|
54
|
+
next()
|
|
55
|
+
}
|
|
56
|
+
```
|
|
66
57
|
|
|
67
|
-
|
|
68
|
-
#data.signatures
|
|
58
|
+
Verify it works. In one terminal:
|
|
69
59
|
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
```sh
|
|
61
|
+
echo LOGDEBUG > config/loglevel
|
|
62
|
+
echo myserver.com >> config/host_list
|
|
63
|
+
sudo haraka -c /path/to/new_project
|
|
64
|
+
```
|
|
72
65
|
|
|
73
|
-
|
|
74
|
-
#mail_from.is_resolvable
|
|
66
|
+
In another:
|
|
75
67
|
|
|
76
|
-
|
|
77
|
-
|
|
68
|
+
```sh
|
|
69
|
+
swaks -h example.com -t booya@myserver.com -f sender@example.com -s localhost -p 25
|
|
70
|
+
```
|
|
78
71
|
|
|
79
|
-
|
|
80
|
-
rcpt_to.in_host_list
|
|
72
|
+
You should see something like this in the Haraka log:
|
|
81
73
|
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
```
|
|
75
|
+
[INFO] [<uuid>] [rcpt_to.disposable] got recipient: <booya@myserver.com>
|
|
76
|
+
```
|
|
84
77
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
The ordering here is important - our new plugin has to come before `rcpt_to.in_host_list`.
|
|
88
|
-
|
|
89
|
-
Fire up your favourite editor and put the following into the `plugins/rcpt_to.disposable.js` file:
|
|
90
|
-
|
|
91
|
-
exports.hook_rcpt = function (next, connection, params) {
|
|
92
|
-
const rcpt = params[0];
|
|
93
|
-
this.loginfo("Got recipient: " + rcpt);
|
|
94
|
-
next();
|
|
95
|
-
}
|
|
78
|
+
…and a `.eml` file in your system temp directory containing the message.
|
|
96
79
|
|
|
97
|
-
|
|
80
|
+
## Parsing Out the Date
|
|
98
81
|
|
|
99
|
-
|
|
82
|
+
Detect addresses of the form `user-YYYYMMDD` and parse the date:
|
|
100
83
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
84
|
+
```js
|
|
85
|
+
exports.hook_rcpt = (next, connection, params) => {
|
|
86
|
+
const rcpt = params[0]
|
|
87
|
+
connection.loginfo(`got recipient: ${rcpt}`)
|
|
104
88
|
|
|
105
|
-
|
|
89
|
+
const match = /^(.*)-(\d{4})(\d{2})(\d{2})$/.exec(rcpt.user)
|
|
90
|
+
if (!match) return next()
|
|
106
91
|
|
|
107
|
-
|
|
108
|
-
|
|
92
|
+
// Date constructor uses zero-indexed months (Dec === 11)
|
|
93
|
+
const expiry = new Date(match[2], match[3] - 1, match[4])
|
|
94
|
+
connection.loginfo(`expires on: ${expiry.toISOString()}`)
|
|
109
95
|
|
|
110
|
-
|
|
96
|
+
next()
|
|
97
|
+
}
|
|
98
|
+
```
|
|
111
99
|
|
|
112
|
-
|
|
100
|
+
Restart Haraka and send:
|
|
113
101
|
|
|
114
|
-
|
|
115
|
-
|
|
102
|
+
```sh
|
|
103
|
+
swaks -h example.com -t booya-20271231@myserver.com \
|
|
104
|
+
-f sender@example.com -s localhost -p 25
|
|
105
|
+
```
|
|
116
106
|
|
|
117
|
-
|
|
107
|
+
Logs:
|
|
118
108
|
|
|
119
|
-
|
|
120
|
-
|
|
109
|
+
```
|
|
110
|
+
[INFO] [rcpt_to.disposable] got recipient: <booya-20271231@myserver.com>
|
|
111
|
+
[INFO] [rcpt_to.disposable] expires on: 2027-12-31T00:00:00.000Z
|
|
112
|
+
```
|
|
121
113
|
|
|
122
|
-
|
|
123
|
-
var rcpt = params[0];
|
|
124
|
-
this.loginfo("Got recipient: " + rcpt);
|
|
114
|
+
## Rejecting Expired Addresses
|
|
125
115
|
|
|
126
|
-
|
|
127
|
-
var match = /^(.*)-(\d{4})(\d{2})(\d{2})$/.exec(rcpt.user);
|
|
128
|
-
if (!match) {
|
|
129
|
-
return next();
|
|
130
|
-
}
|
|
116
|
+
Compare the parsed date to today and reject if it has already passed:
|
|
131
117
|
|
|
132
|
-
|
|
133
|
-
|
|
118
|
+
```js
|
|
119
|
+
exports.hook_rcpt = (next, connection, params) => {
|
|
120
|
+
const rcpt = params[0]
|
|
134
121
|
|
|
135
|
-
|
|
122
|
+
const match = /^(.*)-(\d{4})(\d{2})(\d{2})$/.exec(rcpt.user)
|
|
123
|
+
if (!match) return next()
|
|
136
124
|
|
|
137
|
-
|
|
125
|
+
const expiry = new Date(match[2], match[3] - 1, match[4])
|
|
126
|
+
if (expiry < new Date()) {
|
|
127
|
+
return next(DENY, 'Expired email address')
|
|
138
128
|
}
|
|
139
129
|
|
|
140
|
-
|
|
130
|
+
next()
|
|
131
|
+
}
|
|
132
|
+
```
|
|
141
133
|
|
|
142
|
-
|
|
143
|
-
-f somewhere@example.com -s localhost -p 25
|
|
134
|
+
Send mail to an expired address:
|
|
144
135
|
|
|
145
|
-
|
|
136
|
+
```sh
|
|
137
|
+
swaks -h example.com -t booya-20200101@myserver.com \
|
|
138
|
+
-f sender@example.com -s localhost -p 25
|
|
139
|
+
```
|
|
146
140
|
|
|
147
|
-
|
|
148
|
-
[INFO] [rcpt_to.disposable] Email expires on: Sun, 01 Jan 2012 05:00:00 GMT
|
|
141
|
+
The remote end sees:
|
|
149
142
|
|
|
150
|
-
|
|
151
|
-
|
|
143
|
+
```
|
|
144
|
+
<** 550 Expired email address
|
|
145
|
+
```
|
|
152
146
|
|
|
153
|
-
##
|
|
147
|
+
## Rewriting Live Addresses
|
|
154
148
|
|
|
155
|
-
|
|
156
|
-
and reject expired emails. Again, this is very simple:
|
|
149
|
+
When the address is still valid, strip the date tag so the downstream mail store receives plain `user@domain`:
|
|
157
150
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
151
|
+
```js
|
|
152
|
+
exports.hook_rcpt = (next, connection, params) => {
|
|
153
|
+
const rcpt = params[0]
|
|
161
154
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (!match) {
|
|
165
|
-
return next();
|
|
166
|
-
}
|
|
155
|
+
const match = /^(.*)-(\d{4})(\d{2})(\d{2})$/.exec(rcpt.user)
|
|
156
|
+
if (!match) return next()
|
|
167
157
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
this.loginfo("Email expires on: " + expiry_date);
|
|
172
|
-
|
|
173
|
-
var today = new Date();
|
|
174
|
-
|
|
175
|
-
if (expiry_date < today) {
|
|
176
|
-
// If we get here, the email address has expired
|
|
177
|
-
return next(DENY, "Expired email address");
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
next();
|
|
158
|
+
const expiry = new Date(match[2], match[3] - 1, match[4])
|
|
159
|
+
if (expiry < new Date()) {
|
|
160
|
+
return next(DENY, 'Expired email address')
|
|
181
161
|
}
|
|
182
162
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
=== Connected to localhost.
|
|
189
|
-
<- 220 sergeant.org ESMTP Haraka 0.3 ready
|
|
190
|
-
-> EHLO foo.com
|
|
191
|
-
<- 250-Haraka says hi Unknown [127.0.0.1]
|
|
192
|
-
<- 250-PIPELINING
|
|
193
|
-
<- 250-8BITMIME
|
|
194
|
-
<- 250 SIZE 500000
|
|
195
|
-
-> MAIL FROM:<somewhere@example.com>
|
|
196
|
-
<- 250 From address is OK
|
|
197
|
-
-> RCPT TO:<booya-20110101@haraka.local>
|
|
198
|
-
<** 550 Expired email address
|
|
199
|
-
-> QUIT
|
|
200
|
-
<- 221 closing connection. Have a jolly good day.
|
|
201
|
-
=== Connection closed with remote host.
|
|
202
|
-
|
|
203
|
-
Now we need to do one more thing...
|
|
204
|
-
|
|
205
|
-
## Fixing Up Unexpired Emails
|
|
206
|
-
|
|
207
|
-
The last thing we need to do, is if we have an email that isn't expired, we
|
|
208
|
-
need to normalise it back to the real email address, because wherever we
|
|
209
|
-
deliver this to is unlikely to recognise these new email addresses.
|
|
210
|
-
|
|
211
|
-
Here's how our final plugin will look:
|
|
212
|
-
|
|
213
|
-
exports.hook_rcpt = function (next, connection, params) {
|
|
214
|
-
var rcpt = params[0];
|
|
215
|
-
this.loginfo("Got recipient: " + rcpt);
|
|
216
|
-
|
|
217
|
-
// Check user matches regex 'user-YYYYMMDD':
|
|
218
|
-
var match = /^(.*)-(\d{4})(\d{2})(\d{2})$/.exec(rcpt.user);
|
|
219
|
-
if (!match) {
|
|
220
|
-
return next();
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// get date - note Date constructor takes month-1 (i.e. Dec == 11).
|
|
224
|
-
var expiry_date = new Date(match[2], match[3]-1, match[4]);
|
|
225
|
-
|
|
226
|
-
this.loginfo("Email expires on: " + expiry_date);
|
|
227
|
-
|
|
228
|
-
var today = new Date();
|
|
229
|
-
|
|
230
|
-
if (expiry_date < today) {
|
|
231
|
-
// If we get here, the email address has expired
|
|
232
|
-
return next(DENY, "Expired email address");
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// now get rid of the extension:
|
|
236
|
-
rcpt.user = match[1];
|
|
237
|
-
this.loginfo("Email address now: " + rcpt);
|
|
238
|
-
|
|
239
|
-
next();
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
And when we test this with an unexpired address via swaks:
|
|
243
|
-
|
|
244
|
-
$ swaks -h foo.com -t booya-20120101@haraka.local \
|
|
245
|
-
-f somewhere@example.com -s localhost -p 25
|
|
246
|
-
|
|
247
|
-
We get in the logs:
|
|
163
|
+
rcpt.user = match[1]
|
|
164
|
+
connection.loginfo(`rewrote recipient to: ${rcpt}`)
|
|
165
|
+
next()
|
|
166
|
+
}
|
|
167
|
+
```
|
|
248
168
|
|
|
249
|
-
|
|
250
|
-
[INFO] [rcpt_to.disposable] Email expires on: Sun Jan 01 2012 00:00:00 GMT-0500 (EST)
|
|
251
|
-
[INFO] [rcpt_to.disposable] Email address now: <booya@haraka.local>
|
|
169
|
+
Send to a live tagged address and watch the log:
|
|
252
170
|
|
|
253
|
-
|
|
171
|
+
```
|
|
172
|
+
[INFO] [rcpt_to.disposable] rewrote recipient to: <booya@myserver.com>
|
|
173
|
+
```
|
|
254
174
|
|
|
255
|
-
|
|
175
|
+
## Further Reading
|
|
256
176
|
|
|
257
|
-
|
|
258
|
-
to the body of the email and the headers, access to the HELO string, and
|
|
259
|
-
implementing ESMTP extensions, among many others.
|
|
177
|
+
The Haraka API offers much more — body and header access, ESMTP extension hooks, the outbound delivery hooks, structured results, attachments, and so on. Two good starting points:
|
|
260
178
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
179
|
+
- The [Plugins guide](Plugins.md) and the rest of the `docs/` directory.
|
|
180
|
+
- The [Plugin registry](https://github.com/haraka/Haraka/blob/master/PLUGINS.md) for an inventory of real-world plugins.
|
|
181
|
+
- The plugins shipped in the [`plugins/`](../plugins/) directory. Even the most elaborate are under 200 lines; many are under 20.
|
|
264
182
|
|
|
265
|
-
|
|
266
|
-
The plugins that Haraka ships with use almost all parts of the API and so
|
|
267
|
-
should give you a good starting point if you want to implement a particular
|
|
268
|
-
piece of functionality. Even the most complicated plugins are under 200 lines
|
|
269
|
-
of code, so don't be intimidated by them! The simplest one is a mere 5 lines
|
|
270
|
-
of code.
|
|
183
|
+
[swaks]: https://www.jetmore.org/john/code/swaks/
|
package/docs/plugins/aliases.md
CHANGED
|
@@ -1,143 +1,3 @@
|
|
|
1
1
|
# aliases
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
change the RCPT address in a number of ways. All aliases are specified in
|
|
5
|
-
a JSON formatted configuration file, and must have at very least an action.
|
|
6
|
-
Any syntax error found in the JSON format config file will stop the server
|
|
7
|
-
from running.
|
|
8
|
-
|
|
9
|
-
IMPORTANT: this plugin must appear in `config/plugins` before other plugins
|
|
10
|
-
that run on hook_rcpt
|
|
11
|
-
|
|
12
|
-
WARNING: DO NOT USE THIS PLUGIN WITH queue/smtp_proxy.
|
|
13
|
-
|
|
14
|
-
## Configuration
|
|
15
|
-
|
|
16
|
-
- aliases
|
|
17
|
-
|
|
18
|
-
JSON formatted configuration file that must contain, at very least, a key
|
|
19
|
-
to match against RCPT address, and a value that is an associative array
|
|
20
|
-
with an "action" : "<action>" key, value pair. An example:
|
|
21
|
-
|
|
22
|
-
{ "test1" : { "action" : "drop" } }
|
|
23
|
-
|
|
24
|
-
In the above example the "test1" alias will drop any message that matches
|
|
25
|
-
test1, or test1-_ or test1+_ (wildcard '-' or '+', see below). Actions
|
|
26
|
-
may in turn have 0 or more options listed with them like so:
|
|
27
|
-
|
|
28
|
-
{ "test3" : { "action" : "alias", "to" : "test3-works" } }
|
|
29
|
-
|
|
30
|
-
In the above example the "test3" alias has an action of "alias", and
|
|
31
|
-
a required "to" field. If this "to" field were missing the alias would
|
|
32
|
-
fail to run, and an error would be printed in the logs.
|
|
33
|
-
|
|
34
|
-
Now aliases of 'user', '@host' and 'user@host' possible:
|
|
35
|
-
|
|
36
|
-
{ "demo" : { "action" : "drop" } }
|
|
37
|
-
or
|
|
38
|
-
{ "@example.com" : { "action" : "drop" } }
|
|
39
|
-
or
|
|
40
|
-
{ "demo@example.com" : { "action" : "drop" } }
|
|
41
|
-
|
|
42
|
-
Aliases may also be exploded to multiple recipients:
|
|
43
|
-
|
|
44
|
-
{ "sales@example.com": { "action: "alias", "to": ["alice@example.com", "bob@example.com"] } }
|
|
45
|
-
|
|
46
|
-
- wildcard notation
|
|
47
|
-
|
|
48
|
-
In an effort to match some of the functionality of other alias parsers
|
|
49
|
-
we've allowed wildcard matching of the alias against the right most
|
|
50
|
-
string of a RCPT address. The characters '-' and '+' are commonly used
|
|
51
|
-
for subaddressing and this plugin has built-in support to alias the
|
|
52
|
-
"user" part of the email address.
|
|
53
|
-
|
|
54
|
-
That is, if our address were test2-testing@example.com (or
|
|
55
|
-
test2+testing@example.com), the below alias would match:
|
|
56
|
-
|
|
57
|
-
{ "test2" : { "action" : "drop" } }
|
|
58
|
-
|
|
59
|
-
The larger, and more specific alias, should always match first when
|
|
60
|
-
using wildcard '-' notation. So if the above RCPT were put up against
|
|
61
|
-
this alias config, it would not drop, but rather map to another
|
|
62
|
-
address:
|
|
63
|
-
|
|
64
|
-
{
|
|
65
|
-
"test2" : { "action" : "drop" },
|
|
66
|
-
"test2-testing" : { "action" : "alias", "to" : "test@foo.com" }
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
- chaining and circuits
|
|
70
|
-
|
|
71
|
-
In short, we do not allow chaining of aliases at this time. As a
|
|
72
|
-
side-effect, we enjoy protections against alias circuits.
|
|
73
|
-
|
|
74
|
-
- optional one line formatting
|
|
75
|
-
|
|
76
|
-
Any valid JSON will due, however, please consider keeping each alias
|
|
77
|
-
on its own line so that others that wish to grep the aliases file
|
|
78
|
-
have an easier time finding the full configuration for an alias.
|
|
79
|
-
|
|
80
|
-
- nondeterministic duplicate matches
|
|
81
|
-
|
|
82
|
-
This plugin was written with speed in mind. That means every lookup
|
|
83
|
-
hashes into the alias file for its match. While the act of doing so
|
|
84
|
-
is fast, it does mean that any duplicate alias entries will match
|
|
85
|
-
nondeterministically. That is, we cannot predict what will happen
|
|
86
|
-
here:
|
|
87
|
-
|
|
88
|
-
{
|
|
89
|
-
"coinflip" : { "action" : "alias", "to" : "heads@coin.com" },
|
|
90
|
-
"coinflip" : { "action" : "alias", "to" : "tails@coin.com" }
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
Truth be told, one result will likely always be chosen over the other,
|
|
94
|
-
so this is not exactly a coinflip. We simply cannot say what the
|
|
95
|
-
language implementation will do here, it could change tomorrow.
|
|
96
|
-
|
|
97
|
-
- action (required)
|
|
98
|
-
|
|
99
|
-
The following is a list of supported actions, and the options they require.
|
|
100
|
-
- drop
|
|
101
|
-
|
|
102
|
-
This action simply drops a message, while pretending everything was
|
|
103
|
-
okay to the sender. This acts much like an alias to /dev/null in
|
|
104
|
-
other servers.
|
|
105
|
-
|
|
106
|
-
- alias
|
|
107
|
-
|
|
108
|
-
This action will map the alias key to the address specified in the
|
|
109
|
-
"to" option. A note about matching in addition to the note
|
|
110
|
-
about wildcard '-' above. When we match an alias, we store the
|
|
111
|
-
hostname of the match for a shortcut substitution syntax later.
|
|
112
|
-
- to (required)
|
|
113
|
-
|
|
114
|
-
This option is the full address, or local part at matched hostname
|
|
115
|
-
that the RCPT address will be re-written to. For an example of
|
|
116
|
-
an alias to a full address consider the following:
|
|
117
|
-
|
|
118
|
-
{ "test5" : { "action" : "alias", "to" : "test5@foo.com" } }
|
|
119
|
-
|
|
120
|
-
This will map RCPT matches for "test5" to "test5-works@foo.com".
|
|
121
|
-
This would map "test5@somedomain.com" to "test5-works@foo.com"
|
|
122
|
-
every time. Now compare this notation with its shortcut
|
|
123
|
-
counterpart, best used when the "to" address is at the same
|
|
124
|
-
domain as the match:
|
|
125
|
-
|
|
126
|
-
{ "test4" : { "action" : "alias", "to" : "test4" } }
|
|
127
|
-
|
|
128
|
-
Clearly, this notation is more compact, but what does it do. Well,
|
|
129
|
-
mail to "test4-foo@anydomain.com" will map to "test4@anydomain.com".
|
|
130
|
-
One can see the clear benefit of using this notation with lots of
|
|
131
|
-
aliases on a single domain that map to other local parts at the
|
|
132
|
-
same domain.
|
|
133
|
-
|
|
134
|
-
### Example Configuration
|
|
135
|
-
|
|
136
|
-
{
|
|
137
|
-
"test1" : { "action" : "drop" },
|
|
138
|
-
"test2" : { "action" : "drop" },
|
|
139
|
-
"test3" : { "action" : "alias", "to" : "test3-works" },
|
|
140
|
-
"test4" : { "action" : "alias", "to" : "test4" },
|
|
141
|
-
"test5" : { "action" : "alias", "to" : "test5-works@success.com" },
|
|
142
|
-
"test6" : { "action" : "alias", "to" : "test6-works@success.com" }
|
|
143
|
-
}
|
|
3
|
+
Repackaged as [haraka-plugin-aliases](https://github.com/haraka/haraka-plugin-aliases).
|
|
@@ -1,41 +1,4 @@
|
|
|
1
1
|
# auth/auth_ldap
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
the user is authenticated.
|
|
6
|
-
|
|
7
|
-
## Configuration
|
|
8
|
-
|
|
9
|
-
Configuration is stored in `config/auth_ldap.ini` and uses the INI
|
|
10
|
-
style formatting.
|
|
11
|
-
|
|
12
|
-
Only the `LOGIN` authentication method is supported assuming that passwords in the
|
|
13
|
-
LDAP database are not stored in cleartext (which would allow for CRAM-MD5). Note
|
|
14
|
-
that this means passwords will be sent in the clear to the LDAP server unless
|
|
15
|
-
an `ldaps://` conection is used.
|
|
16
|
-
|
|
17
|
-
Current configuration options in `[core]` are:
|
|
18
|
-
|
|
19
|
-
server - the url of the LDAP server (ldap:// or ldaps://)
|
|
20
|
-
timeout - time in miliseconds to wait for the server resonse before giving up
|
|
21
|
-
rejectUnauthorized - boolean (true or false) as to whether to reject connections
|
|
22
|
-
not verified against a CA. Meaning, a "false" allows non-verified.
|
|
23
|
-
|
|
24
|
-
Example:
|
|
25
|
-
|
|
26
|
-
[core]
|
|
27
|
-
server=ldaps://ldap.opoet.com
|
|
28
|
-
timeout=5000
|
|
29
|
-
rejectUnauthorized=false
|
|
30
|
-
|
|
31
|
-
The `[dns]` section (that is plural DN and not domain name system), is a list of DNs to use
|
|
32
|
-
to bind. The `%u` in the strings is substituted with the user name used in the SMTP
|
|
33
|
-
authentication. Note that the keys have no meaning and the DNs are tried in series until
|
|
34
|
-
the first successful bind. The LDAP RFC does not allow for parallel binds on a connection,
|
|
35
|
-
so it is suggested that the most commonly used DN be placed earlier in the list.
|
|
36
|
-
|
|
37
|
-
Example:
|
|
38
|
-
|
|
39
|
-
[dns]
|
|
40
|
-
dn1=uid=%u,ou=Users,dc=opoet,dc=com
|
|
41
|
-
dn2=uid=%u,ou=people,dc=opoet,dc=com
|
|
3
|
+
Repackaged as [haraka-plugin-auth-ldap](https://github.com/haraka/haraka-plugin-auth-ldap).
|
|
4
|
+
Loading `auth/auth_ldap` in `config/plugins` is auto-redirected to `auth-ldap`.
|
|
@@ -1,20 +1,6 @@
|
|
|
1
1
|
# max_unrecognized_commands
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
immediately (and rudely - technically an RFC violation) disconnected.
|
|
8
|
-
|
|
9
|
-
**IMPORTANT**:
|
|
10
|
-
This plugin should be listed near the bottom of `config/plugins` so that it
|
|
11
|
-
runs after any plugins that use the unrecognized_command hook to implement
|
|
12
|
-
other SMTP verbs and extensions (such as the auth/\* plugins), otherwise
|
|
13
|
-
commands valid for these plugins will be counted as unknown by this plugin.
|
|
14
|
-
|
|
15
|
-
## Configuration
|
|
16
|
-
|
|
17
|
-
- max_unrecognized_commands
|
|
18
|
-
|
|
19
|
-
Specifies the number of unrecognized commands to allow before disconnecting.
|
|
20
|
-
Default: 10.
|
|
3
|
+
The functionality of this plugin was folded into
|
|
4
|
+
[haraka-plugin-limit](https://github.com/haraka/haraka-plugin-limit).
|
|
5
|
+
Loading `max_unrecognized_commands` in `config/plugins` is auto-redirected
|
|
6
|
+
to `limit`.
|
|
@@ -37,6 +37,6 @@ across all workers, with the exception of outbound stats.
|
|
|
37
37
|
All of the counts shown are since the process started, so if a
|
|
38
38
|
worker has been re-started then the counts may not add up.
|
|
39
39
|
|
|
40
|
-
Note: this plugin
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
Note: this plugin should be added at the top of `config/plugins` so
|
|
41
|
+
that its `connect_init`, `rcpt`, `data`, and `disconnect` hooks run
|
|
42
|
+
before any plugin that might short-circuit those hooks.
|
|
@@ -38,9 +38,7 @@ Configuration is stored in smtp_forward.ini in the following keys:
|
|
|
38
38
|
|
|
39
39
|
- enable_tls=[true]
|
|
40
40
|
|
|
41
|
-
Enable TLS with the forward host (if
|
|
42
|
-
|
|
43
|
-
This option controls the use of TLS via `STARTTLS`. This plugin does not work with SMTP over TLS.
|
|
41
|
+
Enable opportunistic TLS with the forward host via `STARTTLS` (if the host advertises it). This plugin does not work with implicit SMTP over TLS.
|
|
44
42
|
|
|
45
43
|
- auth_type=[plain\|login]
|
|
46
44
|
|
|
@@ -69,6 +67,24 @@ Configuration is stored in smtp_forward.ini in the following keys:
|
|
|
69
67
|
[example.com]
|
|
70
68
|
[example.net]
|
|
71
69
|
|
|
70
|
+
- [tls]
|
|
71
|
+
|
|
72
|
+
Client STARTTLS options are assembled by merging:
|
|
73
|
+
|
|
74
|
+
1. `tls.ini` `[main]` — the global Haraka TLS config
|
|
75
|
+
2. `smtp_forward.ini` `[tls]` — overrides. Anything set here wins.
|
|
76
|
+
|
|
77
|
+
Example `smtp_forward.ini` `[tls]` section:
|
|
78
|
+
|
|
79
|
+
[tls]
|
|
80
|
+
rejectUnauthorized=true
|
|
81
|
+
minVersion=TLSv1.2
|
|
82
|
+
no_tls_hosts[]=10.0.0.5
|
|
83
|
+
|
|
84
|
+
Per-domain `enable_tls=false` still disables STARTTLS for that backend. Per-domain TLS cipher/cert overrides are not currently supported.
|
|
85
|
+
|
|
86
|
+
Changes to `tls.ini` require a Haraka restart to apply to the forward path; changes to `smtp_forward.ini` are picked up by the existing reload hook.
|
|
87
|
+
|
|
72
88
|
# Per-Domain Configuration
|
|
73
89
|
|
|
74
90
|
More specific forward routes for domains can be defined. The domain is chosen based on the value of the `domain_selector` config variable.
|