haraka 0.0.32 → 3.3.0
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/.claude/settings.local.json +28 -0
- package/.githooks/pre-commit +41 -0
- package/.prettierignore +6 -0
- package/.qlty/.gitignore +7 -0
- package/.qlty/configs/.shellcheckrc +1 -0
- package/.qlty/qlty.toml +15 -0
- package/CHANGELOG.md +1872 -62
- package/CLAUDE.md +40 -0
- package/CONTRIBUTORS.md +34 -0
- package/Dockerfile +50 -0
- package/GEMINI.md +38 -0
- package/LICENSE +2 -1
- package/Plugins.md +227 -0
- package/README.md +100 -115
- package/SECURITY.md +178 -0
- package/TODO +22 -0
- package/address.js +53 -0
- package/bin/haraka +593 -0
- package/bin/haraka_grep +32 -0
- package/config/aliases +2 -0
- package/config/auth_flat_file.ini +7 -0
- package/config/auth_vpopmaild.ini +9 -0
- package/config/connection.ini +79 -0
- package/config/delay_deny.ini +7 -0
- package/config/dhparams.pem +8 -0
- package/config/host_list +3 -0
- package/config/host_list_regex +6 -0
- package/config/http.ini +11 -0
- package/config/lmtp.ini +7 -0
- package/config/log.ini +11 -0
- package/config/me +1 -0
- package/config/outbound.bounce_message +18 -0
- package/config/outbound.bounce_message_html +36 -0
- package/config/outbound.bounce_message_image +106 -0
- package/config/outbound.ini +24 -0
- package/config/plugins +67 -0
- package/config/smtp.ini +37 -0
- package/config/smtp_bridge.ini +4 -0
- package/config/smtp_forward.ini +31 -0
- package/config/smtp_proxy.ini +27 -0
- package/config/tarpit.timeout +1 -0
- package/config/tls.ini +83 -0
- package/config/tls_cert.pem +23 -0
- package/config/tls_key.pem +28 -0
- package/config/watch.ini +12 -0
- package/config/xclient.hosts +2 -0
- package/connection.js +1863 -0
- package/contrib/Haraka.cf +6 -0
- package/contrib/Haraka.pm +35 -0
- package/contrib/bad_smtp_server.pl +25 -0
- package/contrib/bsd-rc.d/haraka +61 -0
- package/contrib/debian-init.d/haraka +87 -0
- package/contrib/haraka.init +96 -0
- package/contrib/haraka.service +23 -0
- package/contrib/plugin2npm.sh +81 -0
- package/contrib/ubuntu-upstart/haraka.conf +27 -0
- package/coverage/coverage-final.json +2 -0
- package/coverage/coverage-summary.json +33 -0
- package/coverage/tmp/coverage-79131-1779241025146-0.json +1 -0
- package/coverage/tmp/coverage-79132-1779240999690-0.json +1 -0
- package/coverage/tmp/coverage-79172-1779241000095-0.json +1 -0
- package/coverage/tmp/coverage-79210-1779241000156-0.json +1 -0
- package/coverage/tmp/coverage-79211-1779241000209-0.json +1 -0
- package/coverage/tmp/coverage-79212-1779241000266-0.json +1 -0
- package/coverage/tmp/coverage-79213-1779241000441-0.json +1 -0
- package/coverage/tmp/coverage-79214-1779241000626-0.json +1 -0
- package/coverage/tmp/coverage-79215-1779241000795-0.json +1 -0
- package/coverage/tmp/coverage-79216-1779241000965-0.json +1 -0
- package/coverage/tmp/coverage-79218-1779241001013-0.json +1 -0
- package/coverage/tmp/coverage-79219-1779241001179-0.json +1 -0
- package/coverage/tmp/coverage-79220-1779241006249-0.json +1 -0
- package/coverage/tmp/coverage-79227-1779241011453-0.json +1 -0
- package/coverage/tmp/coverage-79229-1779241011537-0.json +1 -0
- package/coverage/tmp/coverage-79230-1779241011647-0.json +1 -0
- package/coverage/tmp/coverage-79231-1779241011765-0.json +1 -0
- package/coverage/tmp/coverage-79232-1779241011841-0.json +1 -0
- package/coverage/tmp/coverage-79233-1779241011909-0.json +1 -0
- package/coverage/tmp/coverage-79234-1779241011984-0.json +1 -0
- package/coverage/tmp/coverage-79235-1779241012055-0.json +1 -0
- package/coverage/tmp/coverage-79236-1779241012230-0.json +1 -0
- package/coverage/tmp/coverage-79237-1779241012300-0.json +1 -0
- package/coverage/tmp/coverage-79238-1779241012368-0.json +1 -0
- package/coverage/tmp/coverage-79239-1779241012438-0.json +1 -0
- package/coverage/tmp/coverage-79240-1779241012511-0.json +1 -0
- package/coverage/tmp/coverage-79241-1779241012582-0.json +1 -0
- package/coverage/tmp/coverage-79242-1779241012652-0.json +1 -0
- package/coverage/tmp/coverage-79243-1779241012814-0.json +1 -0
- package/coverage/tmp/coverage-79244-1779241012931-0.json +1 -0
- package/coverage/tmp/coverage-79245-1779241013007-0.json +1 -0
- package/coverage/tmp/coverage-79246-1779241013106-0.json +1 -0
- package/coverage/tmp/coverage-79247-1779241013178-0.json +1 -0
- package/coverage/tmp/coverage-79248-1779241013244-0.json +1 -0
- package/coverage/tmp/coverage-79249-1779241013409-0.json +1 -0
- package/coverage/tmp/coverage-79250-1779241013697-0.json +1 -0
- package/coverage/tmp/coverage-79251-1779241013847-0.json +1 -0
- package/coverage/tmp/coverage-79252-1779241014288-0.json +1 -0
- package/coverage/tmp/coverage-79253-1779241014378-0.json +1 -0
- package/coverage/tmp/coverage-79254-1779241014428-0.json +1 -0
- package/coverage/tmp/coverage-79255-1779241021774-0.json +1 -0
- package/coverage/tmp/coverage-80382-1779241021949-0.json +1 -0
- package/coverage/tmp/coverage-80383-1779241025019-0.json +1 -0
- package/coverage/tmp/coverage-80384-1779241025133-0.json +1 -0
- package/docs/Body.md +1 -0
- package/docs/Config.md +1 -0
- package/docs/Connection.md +153 -0
- package/docs/CoreConfig.md +96 -0
- package/docs/CustomReturnCodes.md +3 -0
- package/docs/HAProxy.md +62 -0
- package/docs/Header.md +1 -0
- package/docs/Logging.md +129 -0
- package/docs/Outbound.md +210 -0
- package/docs/Plugins.md +372 -0
- package/docs/Results.md +7 -0
- package/docs/Transaction.md +135 -0
- package/docs/Tutorial.md +183 -0
- package/docs/deprecated/access.md +3 -0
- package/docs/deprecated/backscatterer.md +9 -0
- package/docs/deprecated/connect.rdns_access.md +53 -0
- package/docs/deprecated/data.headers.md +3 -0
- package/docs/deprecated/data.nomsgid.md +7 -0
- package/docs/deprecated/data.noreceived.md +11 -0
- package/docs/deprecated/data.rfc5322_header_checks.md +11 -0
- package/docs/deprecated/dkim_sign.md +97 -0
- package/docs/deprecated/dkim_verify.md +28 -0
- package/docs/deprecated/dnsbl.md +80 -0
- package/docs/deprecated/dnswl.md +73 -0
- package/docs/deprecated/lookup_rdns.strict.md +67 -0
- package/docs/deprecated/mail_from.access.md +52 -0
- package/docs/deprecated/mail_from.blocklist.md +18 -0
- package/docs/deprecated/mail_from.nobounces.md +8 -0
- package/docs/deprecated/rcpt_to.access.md +53 -0
- package/docs/deprecated/rcpt_to.blocklist.md +18 -0
- package/docs/deprecated/rcpt_to.routes.md +3 -0
- package/docs/deprecated/rdns.regexp.md +30 -0
- package/docs/plugins/aliases.md +3 -0
- package/docs/plugins/auth/auth_bridge.md +34 -0
- package/docs/plugins/auth/auth_ldap.md +4 -0
- package/docs/plugins/auth/auth_proxy.md +36 -0
- package/docs/plugins/auth/auth_vpopmaild.md +33 -0
- package/docs/plugins/auth/flat_file.md +40 -0
- package/docs/plugins/block_me.md +18 -0
- package/docs/plugins/data.signatures.md +11 -0
- package/docs/plugins/delay_deny.md +23 -0
- package/docs/plugins/max_unrecognized_commands.md +6 -0
- package/docs/plugins/prevent_credential_leaks.md +22 -0
- package/docs/plugins/process_title.md +42 -0
- package/docs/plugins/queue/deliver.md +3 -0
- package/docs/plugins/queue/discard.md +32 -0
- package/docs/plugins/queue/lmtp.md +24 -0
- package/docs/plugins/queue/qmail-queue.md +16 -0
- package/docs/plugins/queue/quarantine.md +87 -0
- package/docs/plugins/queue/smtp_bridge.md +32 -0
- package/docs/plugins/queue/smtp_forward.md +127 -0
- package/docs/plugins/queue/smtp_proxy.md +68 -0
- package/docs/plugins/queue/test.md +7 -0
- package/docs/plugins/rcpt_to.in_host_list.md +34 -0
- package/docs/plugins/rcpt_to.max_count.md +3 -0
- package/docs/plugins/record_envelope_addresses.md +20 -0
- package/docs/plugins/relay.md +3 -0
- package/docs/plugins/reseed_rng.md +16 -0
- package/docs/plugins/status.md +41 -0
- package/docs/plugins/tarpit.md +50 -0
- package/docs/plugins/tls.md +235 -0
- package/docs/plugins/toobusy.md +27 -0
- package/docs/plugins/xclient.md +10 -0
- package/docs/tutorials/Migrating_from_v1_to_v2.md +96 -0
- package/docs/tutorials/SettingUpOutbound.md +62 -0
- package/eslint.config.mjs +2 -0
- package/haraka.js +74 -0
- package/haraka.sh +2 -0
- package/http/html/404.html +58 -0
- package/http/html/index.html +47 -0
- package/http/package.json +21 -0
- package/line_socket.js +24 -0
- package/logger.js +322 -0
- package/outbound/client_pool.js +59 -0
- package/outbound/config.js +134 -0
- package/outbound/hmail.js +1504 -0
- package/outbound/index.js +349 -0
- package/outbound/qfile.js +93 -0
- package/outbound/queue.js +399 -0
- package/outbound/tls.js +85 -0
- package/outbound/todo.js +17 -0
- package/package.json +91 -29
- package/plugins/.eslintrc.yaml +3 -0
- package/plugins/auth/auth_base.js +261 -0
- package/plugins/auth/auth_bridge.js +20 -0
- package/plugins/auth/auth_proxy.js +227 -0
- package/plugins/auth/auth_vpopmaild.js +162 -0
- package/plugins/auth/flat_file.js +44 -0
- package/plugins/block_me.js +88 -0
- package/plugins/data.signatures.js +30 -0
- package/plugins/delay_deny.js +153 -0
- package/plugins/prevent_credential_leaks.js +61 -0
- package/plugins/process_title.js +197 -0
- package/plugins/profile.js +11 -0
- package/plugins/queue/deliver.js +12 -0
- package/plugins/queue/discard.js +27 -0
- package/plugins/queue/lmtp.js +45 -0
- package/plugins/queue/qmail-queue.js +93 -0
- package/plugins/queue/quarantine.js +133 -0
- package/plugins/queue/smtp_bridge.js +45 -0
- package/plugins/queue/smtp_forward.js +371 -0
- package/plugins/queue/smtp_proxy.js +142 -0
- package/plugins/queue/test.js +15 -0
- package/plugins/rcpt_to.host_list_base.js +65 -0
- package/plugins/rcpt_to.in_host_list.js +56 -0
- package/plugins/record_envelope_addresses.js +17 -0
- package/plugins/reseed_rng.js +7 -0
- package/plugins/status.js +274 -0
- package/plugins/tarpit.js +45 -0
- package/plugins/tls.js +164 -0
- package/plugins/toobusy.js +47 -0
- package/plugins/xclient.js +124 -0
- package/plugins.js +604 -0
- package/queue/1772642154987_1775581346001_4_82235_TGwgfd_2_mattbook-m3.home.simerson.net +0 -0
- package/run_tests +11 -0
- package/server.js +827 -0
- package/smtp_client.js +504 -0
- package/test/.eslintrc.yaml +11 -0
- package/test/config/auth_flat_file.ini +5 -0
- package/test/config/block_me.recipient +1 -0
- package/test/config/block_me.senders +1 -0
- package/test/config/dhparams.pem +8 -0
- package/test/config/host_list +2 -0
- package/test/config/outbound_tls_cert.pem +1 -0
- package/test/config/outbound_tls_key.pem +1 -0
- package/test/config/plugins +7 -0
- package/test/config/smtp.ini +11 -0
- package/test/config/smtp_forward.ini +30 -0
- package/test/config/tls/example.com/_.example.com.key +28 -0
- package/test/config/tls/example.com/example.com.crt +25 -0
- package/test/config/tls/haraka.local.pem +51 -0
- package/test/config/tls.ini +45 -0
- package/test/config/tls_cert.pem +21 -0
- package/test/config/tls_key.pem +28 -0
- package/test/connection.js +817 -0
- package/test/fixtures/haproxy_allowed/config/connection.ini +3 -0
- package/test/fixtures/haproxy_disabled/config/connection.ini +3 -0
- package/test/fixtures/haproxy_untrusted/config/connection.ini +3 -0
- package/test/fixtures/line_socket.js +21 -0
- package/test/fixtures/todo_qfile.txt +0 -0
- package/test/fixtures/util_hmailitem.js +156 -0
- package/test/installation/config/test-plugin-flat +1 -0
- package/test/installation/config/test-plugin.ini +10 -0
- package/test/installation/config/tls.ini +1 -0
- package/test/installation/node_modules/load_first/index.js +5 -0
- package/test/installation/node_modules/load_first/package.json +11 -0
- package/test/installation/node_modules/test-plugin/config/test-plugin-flat +1 -0
- package/test/installation/node_modules/test-plugin/config/test-plugin.ini +9 -0
- package/test/installation/node_modules/test-plugin/package.json +5 -0
- package/test/installation/node_modules/test-plugin/test-plugin.js +5 -0
- package/test/installation/plugins/base_plugin.js +3 -0
- package/test/installation/plugins/folder_plugin/index.js +3 -0
- package/test/installation/plugins/folder_plugin/package.json +11 -0
- package/test/installation/plugins/inherits.js +7 -0
- package/test/installation/plugins/load_first.js +3 -0
- package/test/installation/plugins/plugin.js +1 -0
- package/test/installation/plugins/tls.js +3 -0
- package/test/logger.js +217 -0
- package/test/loud/config/dhparams.pem +0 -0
- package/test/loud/config/tls/goobered.pem +45 -0
- package/test/loud/config/tls.ini +43 -0
- package/test/mail_specimen/base64-root-part.txt +23 -0
- package/test/mail_specimen/varied-fold-lengths-preserve-data.txt +283 -0
- package/test/outbound/bounce_net_errors.js +133 -0
- package/test/outbound/bounce_rfc3464.js +226 -0
- package/test/outbound/hmail.js +210 -0
- package/test/outbound/index.js +385 -0
- package/test/outbound/qfile.js +124 -0
- package/test/outbound/queue.js +325 -0
- package/test/plugins/auth/auth_base.js +620 -0
- package/test/plugins/auth/auth_bridge.js +80 -0
- package/test/plugins/auth/auth_vpopmaild.js +81 -0
- package/test/plugins/auth/flat_file.js +123 -0
- package/test/plugins/block_me.js +141 -0
- package/test/plugins/data.signatures.js +111 -0
- package/test/plugins/delay_deny.js +262 -0
- package/test/plugins/prevent_credential_leaks.js +174 -0
- package/test/plugins/process_title.js +141 -0
- package/test/plugins/queue/deliver.js +98 -0
- package/test/plugins/queue/discard.js +78 -0
- package/test/plugins/queue/lmtp.js +137 -0
- package/test/plugins/queue/qmail-queue.js +98 -0
- package/test/plugins/queue/quarantine.js +80 -0
- package/test/plugins/queue/smtp_bridge.js +152 -0
- package/test/plugins/queue/smtp_forward.js +1023 -0
- package/test/plugins/queue/smtp_proxy.js +138 -0
- package/test/plugins/rcpt_to.host_list_base.js +102 -0
- package/test/plugins/rcpt_to.in_host_list.js +186 -0
- package/test/plugins/record_envelope_addresses.js +66 -0
- package/test/plugins/reseed_rng.js +34 -0
- package/test/plugins/status.js +207 -0
- package/test/plugins/tarpit.js +90 -0
- package/test/plugins/tls.js +86 -0
- package/test/plugins/toobusy.js +21 -0
- package/test/plugins/xclient.js +119 -0
- package/test/plugins.js +230 -0
- package/test/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_fixed +0 -0
- package/test/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_haraka +0 -0
- package/test/queue/1508269674999_1508269674999_0_34002_socVUF_1_haraka +0 -0
- package/test/queue/1508455115683_1508455115683_0_90253_9Q4o4V_1_haraka +0 -0
- package/test/queue/zero-length +0 -0
- package/test/server.js +1012 -0
- package/test/smtp_client.js +1303 -0
- package/test/tls_socket.js +321 -0
- package/test/transaction.js +554 -0
- package/tls_socket.js +771 -0
- package/transaction.js +267 -0
- package/lib/index.js +0 -371
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Migrating from Haraka v1.x to v2.x
|
|
2
|
+
|
|
3
|
+
Haraka v2.x contains two significant changes to the v1.x API related to streams.
|
|
4
|
+
|
|
5
|
+
Streams are an abstraction over a data flow that is provided by Node core and is used throughout node to "pipe" data between two places or more. This makes programming very easy, and is hence why we started using them in Haraka starting with version 2.0.0.
|
|
6
|
+
|
|
7
|
+
For more information about the Stream API, see http://nodejs.org/api/stream.html
|
|
8
|
+
|
|
9
|
+
Note that when using bundled Haraka plugins, it's very unlikely you will need to change anything. Though you may want to configure `spool_dir` and `spool_after` in `config/smtp.ini` (v2.x), or in `config/connection.ini` (v3.1 or newer). If you have custom plugins, continue reading.
|
|
10
|
+
|
|
11
|
+
## Changes To Look For
|
|
12
|
+
|
|
13
|
+
Firstly, the incoming data in an email (the email body) is now stored in an object which you can treat as a ReadableStream. To find if this is relevant for you, look for instances of `data_lines` in your plugins.
|
|
14
|
+
|
|
15
|
+
Secondly, if you parse the mail body, attachments are now provided as a stream, rather than custom start/data/end events. To find if this is relevant for you, look for instances of `attachment_hooks` in your plugins.
|
|
16
|
+
|
|
17
|
+
## Fixing data_lines plugins
|
|
18
|
+
|
|
19
|
+
Any plugins now working on each line of data will need to change to using a stream. The stream is called `transaction.message_stream`.
|
|
20
|
+
|
|
21
|
+
These changes may be complicated if you are iterating over each line and doing something with the strings therein. However if you are piping the data to an application or over a network, your code will become significantly simpler (and a lot faster).
|
|
22
|
+
|
|
23
|
+
In v1.x Haraka populated the `transaction.data_lines` array for each line of data received. If you were writing the data to a socket then you had to handle backpressure manually by checking the return of `write()` and adding `on('drain')` handlers like so:
|
|
24
|
+
|
|
25
|
+
var data_marker = 0;
|
|
26
|
+
var in_data = false;
|
|
27
|
+
var end_pending = true;
|
|
28
|
+
var send_data = function () {
|
|
29
|
+
in_data = true;
|
|
30
|
+
var wrote_all = true;
|
|
31
|
+
while (wrote_all && (data_marker < connection.transaction.data_lines.length)) {
|
|
32
|
+
var line = connection.transaction.data_lines[data_marker];
|
|
33
|
+
data_marker++;
|
|
34
|
+
wrote_all = socket.write(Buffer.from(line.replace(/^\./, '..').replace(/\r?\n/g, '\r\n')), 'binary');
|
|
35
|
+
if (!wrote_all) return;
|
|
36
|
+
}
|
|
37
|
+
// we get here if wrote_all still true, and we got to end of data_lines
|
|
38
|
+
if (end_pending) {
|
|
39
|
+
end_pending = false;
|
|
40
|
+
// Finished...
|
|
41
|
+
socket.send_command('dot');
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
socket.on('drain', function () {
|
|
45
|
+
if (end_pending && in_data) {
|
|
46
|
+
setImmediate(function () { send_data() });
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
In v2.x this now becomes:
|
|
51
|
+
|
|
52
|
+
connection.transaction.message_stream.pipe(socket, {ending_dot: true});
|
|
53
|
+
|
|
54
|
+
This automatically chunks the data, handles backpressure and will apply any
|
|
55
|
+
necessary format changes. See `docs/Transaction.md` for the full details.
|
|
56
|
+
|
|
57
|
+
If you need to handle the input data by line, then you will need to create
|
|
58
|
+
your own writable stream and then pipe the message to the stream and then
|
|
59
|
+
extract the lines from the stream of data. See the `dkim` plugin for
|
|
60
|
+
an example.
|
|
61
|
+
|
|
62
|
+
## Fixing attachment_hooks plugins
|
|
63
|
+
|
|
64
|
+
For v1.x you passed in functions to `transaction.attachment_hooks()` as
|
|
65
|
+
follows:
|
|
66
|
+
|
|
67
|
+
transaction.attachment_hooks(
|
|
68
|
+
function (ctype, filename, body) {...}, // start
|
|
69
|
+
function (buf) {...}, // data
|
|
70
|
+
function () {...} // end
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
That has now changed to:
|
|
74
|
+
|
|
75
|
+
transaction.attachment_hooks(
|
|
76
|
+
function (ctype, filename, body, stream) {...}, // start
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
This allows you to attach the stream to other streams via `stream.pipe(dest)`.
|
|
80
|
+
|
|
81
|
+
Sometimes destination streams will apply backpressure on the sending stream,
|
|
82
|
+
for example if you are sending attachments to a remote service. In order
|
|
83
|
+
for this backpressure to apply to the connection itself (so that we don't
|
|
84
|
+
have to buffer up data in memory), we need to provide the connection object
|
|
85
|
+
to the stream:
|
|
86
|
+
|
|
87
|
+
var transaction = connection.transaction;
|
|
88
|
+
transaction.attachment_hooks(
|
|
89
|
+
function (ctype, filename, body, stream) {
|
|
90
|
+
stream.connection = connection;
|
|
91
|
+
...
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
For a full example of using attachment streams, see the Transaction.md
|
|
96
|
+
documentation file.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Configuring Haraka For Outbound Email
|
|
2
|
+
|
|
3
|
+
It is straightforward to run Haraka as an outbound (submission) mail server. Before turning on the server itself, get a few external things in order:
|
|
4
|
+
|
|
5
|
+
- **DNS PTR record** — make sure it matches the A/AAAA record of the host you are sending from. Receivers that disagree on `HELO`/PTR will treat your mail with suspicion.
|
|
6
|
+
- **SPF, DKIM, and DMARC** — publish records for any domain you send from. Most receivers downgrade or reject mail without them. Haraka signs outbound with [haraka-plugin-dkim](https://github.com/haraka/haraka-plugin-dkim).
|
|
7
|
+
- **Reverse DNS at the IP owner** — if your hosting provider controls the PTR, set the value through their console.
|
|
8
|
+
|
|
9
|
+
How to provision DNS varies by provider; the records are network-specific so no one-size-fits-all command applies.
|
|
10
|
+
|
|
11
|
+
## Background
|
|
12
|
+
|
|
13
|
+
Haraka treats outbound mail as "relaying". When any plugin sets `connection.relaying = true`, the message is queued for outbound delivery once `DATA` ends. The outbound engine then tries each MX in sequence; on permanent failure a DSN is generated and sent to the `MAIL FROM` address. If the DSN itself bounces, Haraka logs the "double bounce" and drops it.
|
|
14
|
+
|
|
15
|
+
## Setup
|
|
16
|
+
|
|
17
|
+
Modern submission uses **implicit TLS on port 465** (RFC 8314); port 587 with `STARTTLS` is also still common. Plain port 25 is for server-to-server traffic and should not be used for submission.
|
|
18
|
+
|
|
19
|
+
Create a new Haraka instance:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
haraka -i haraka-outbound
|
|
23
|
+
cd haraka-outbound
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
In `config/smtp.ini`, set the listener:
|
|
27
|
+
|
|
28
|
+
```ini
|
|
29
|
+
listen=[::0]:465,[::0]:587
|
|
30
|
+
smtps_port=465
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Anything in `smtps_port` runs implicit TLS; the other ports advertise `STARTTLS`.
|
|
34
|
+
|
|
35
|
+
Enable just the TLS and auth plugins. AUTH is only advertised after TLS is established (except for connections from localhost):
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
cat > config/plugins <<'EOF'
|
|
39
|
+
tls
|
|
40
|
+
auth/flat_file
|
|
41
|
+
EOF
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Add a user to `config/auth_flat_file.ini`. See [`docs/plugins/auth/flat_file.md`](../plugins/auth/flat_file.md) for the format.
|
|
45
|
+
|
|
46
|
+
Start Haraka:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
haraka -c .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
In another shell, test with [swaks](https://www.jetmore.org/john/code/swaks/) — substitute your real test address and the credentials you configured:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
swaks --to youremail@yourdomain.com --from test@example.com \
|
|
56
|
+
--server localhost --port 587 --tls \
|
|
57
|
+
--auth-user testuser --auth-password testpassword
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
For port 465 (implicit TLS), use `--tls-on-connect` instead of `--tls`.
|
|
61
|
+
|
|
62
|
+
Watch the swaks output for errors and confirm the message arrives. That's all the basic configuration you need; once you're satisfied, turn on DKIM signing for the domains you send from.
|
package/haraka.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
'use strict'
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const makePathJoin = () => path.join(process.env.HARAKA, 'node_modules')
|
|
6
|
+
|
|
7
|
+
if (!process.env.HARAKA) {
|
|
8
|
+
console.warn('WARNING: Not running installed Haraka - command line arguments ignored')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// this must be set before "server.js" is loaded
|
|
12
|
+
process.env.HARAKA = process.env.HARAKA || path.resolve('.')
|
|
13
|
+
try {
|
|
14
|
+
require.paths.push(makePathJoin())
|
|
15
|
+
} catch {
|
|
16
|
+
process.env.NODE_PATH = process.env.NODE_PATH ? `${process.env.NODE_PATH}:${makePathJoin()}` : makePathJoin()
|
|
17
|
+
require('module')._initPaths() // Horrible hack
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const utils = require('haraka-utils')
|
|
21
|
+
const logger = require('./logger')
|
|
22
|
+
const server = require('./server')
|
|
23
|
+
|
|
24
|
+
exports.version = utils.getVersion(__dirname)
|
|
25
|
+
|
|
26
|
+
process.on('uncaughtException', (err) => {
|
|
27
|
+
if (err.stack) {
|
|
28
|
+
for (const line of err.stack.split('\n')) logger.crit(line)
|
|
29
|
+
} else {
|
|
30
|
+
logger.crit(`Caught exception: ${JSON.stringify(err)}`)
|
|
31
|
+
}
|
|
32
|
+
logger.dump_and_exit(1)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
let shutting_down = false
|
|
36
|
+
const signals = ['SIGINT']
|
|
37
|
+
|
|
38
|
+
if (process.pid === 1) signals.push('SIGTERM')
|
|
39
|
+
|
|
40
|
+
for (const sig of signals) {
|
|
41
|
+
process.on(sig, () => {
|
|
42
|
+
if (shutting_down) return process.exit(1)
|
|
43
|
+
shutting_down = true
|
|
44
|
+
const [, filename] = process.argv
|
|
45
|
+
process.title = path.basename(filename, '.js')
|
|
46
|
+
|
|
47
|
+
logger.notice(`${sig} received`)
|
|
48
|
+
logger.dump_and_exit(() => {
|
|
49
|
+
if (server.cluster?.isMaster) {
|
|
50
|
+
server.performShutdown()
|
|
51
|
+
} else if (!server.cluster) {
|
|
52
|
+
server.performShutdown()
|
|
53
|
+
}
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
process.on('SIGHUP', () => {
|
|
59
|
+
logger.notice('Flushing the temp fail queue')
|
|
60
|
+
server.flushQueue()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
process.on('exit', () => {
|
|
64
|
+
if (shutting_down) return
|
|
65
|
+
const [, filename] = process.argv
|
|
66
|
+
process.title = path.basename(filename, '.js')
|
|
67
|
+
|
|
68
|
+
logger.notice('Shutting down')
|
|
69
|
+
logger.dump_logs()
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
logger.log('NOTICE', `Starting up Haraka version ${exports.version}`)
|
|
73
|
+
|
|
74
|
+
server.createServer()
|
package/haraka.sh
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Page Not Found</title>
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
7
|
+
<style>
|
|
8
|
+
* {
|
|
9
|
+
line-height: 1.2;
|
|
10
|
+
margin: 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
html {
|
|
14
|
+
color: #888;
|
|
15
|
+
display: table;
|
|
16
|
+
font-family: sans-serif;
|
|
17
|
+
height: 100%;
|
|
18
|
+
text-align: center;
|
|
19
|
+
width: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
body {
|
|
23
|
+
display: table-cell;
|
|
24
|
+
vertical-align: middle;
|
|
25
|
+
margin: 2em auto;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
h1 {
|
|
29
|
+
color: #555;
|
|
30
|
+
font-size: 2em;
|
|
31
|
+
font-weight: 400;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
p {
|
|
35
|
+
margin: 0 auto;
|
|
36
|
+
width: 280px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@media only screen and (max-width: 280px) {
|
|
40
|
+
body,
|
|
41
|
+
p {
|
|
42
|
+
width: 95%;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
h1 {
|
|
46
|
+
font-size: 1.5em;
|
|
47
|
+
margin: 0 0 0.3em;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
51
|
+
</head>
|
|
52
|
+
|
|
53
|
+
<body>
|
|
54
|
+
<h1>Page Not Found</h1>
|
|
55
|
+
<p>Sorry, but the page you were trying to view does not exist.</p>
|
|
56
|
+
</body>
|
|
57
|
+
</html>
|
|
58
|
+
<!-- IE needs 512+ bytes: https://docs.microsoft.com/archive/blogs/ieinternals/friendly-http-error-pages -->
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
6
|
+
<title></title>
|
|
7
|
+
<meta name="description" content="" />
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
9
|
+
|
|
10
|
+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.5.1/css/bootstrap.min.css" />
|
|
11
|
+
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.5.1/css/bootstrap-theme.min.css" />
|
|
12
|
+
|
|
13
|
+
<script src="https://code.jquery.com/jquery-3.5.1.min.js" async></script>
|
|
14
|
+
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.5.1/js/bootstrap.min.js" async></script>
|
|
15
|
+
</head>
|
|
16
|
+
<body>
|
|
17
|
+
<!--[if lt IE 7]>
|
|
18
|
+
<p class="browsehappy">
|
|
19
|
+
You are using an <strong>outdated</strong> browser. Please
|
|
20
|
+
<a href="https://browsehappy.com/">upgrade your browser</a> to improve your experience.
|
|
21
|
+
</p>
|
|
22
|
+
<![endif]-->
|
|
23
|
+
|
|
24
|
+
<ul id="tabList" class="nav nav-tabs" role="tablist navigation">
|
|
25
|
+
<li class="active">
|
|
26
|
+
<a href="#home" role="tab" data-toggle="tab">Home</a>
|
|
27
|
+
</li>
|
|
28
|
+
</ul>
|
|
29
|
+
|
|
30
|
+
<div id="bodyDivContainer" class="tab-content">
|
|
31
|
+
<div class="tab-pane fade in active" id="home">
|
|
32
|
+
<h1>Haraka, a mail server (MTA).</h1>
|
|
33
|
+
|
|
34
|
+
<p>
|
|
35
|
+
You are visiting an installation of
|
|
36
|
+
<a href="https://haraka.github.io">Haraka</a>.
|
|
37
|
+
</p>
|
|
38
|
+
|
|
39
|
+
<p>
|
|
40
|
+
Haraka is on the
|
|
41
|
+
<a href="https://haraka.github.io">web</a> and
|
|
42
|
+
<a href="https://github.com/haraka/Haraka">GitHub</a>
|
|
43
|
+
</p>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
</body>
|
|
47
|
+
</html>
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "haraka-httpd",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Haraka HTTP for SMTPd",
|
|
5
|
+
"main": "server",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"http",
|
|
8
|
+
"watch"
|
|
9
|
+
],
|
|
10
|
+
"authors": [
|
|
11
|
+
"Matt Simerson"
|
|
12
|
+
],
|
|
13
|
+
"private": true,
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"homepage": "http://haraka.github.io/",
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"express": "^4.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {},
|
|
20
|
+
"scripts": {}
|
|
21
|
+
}
|
package/line_socket.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
// Back-compat shim. The Socket class lives in haraka-net-utils as LineSocket;
|
|
3
|
+
// the line-processing helper is `add_line_processor` there. The connect()
|
|
4
|
+
// helper stays here because it depends on Haraka's tls_socket.
|
|
5
|
+
|
|
6
|
+
const { LineSocket, add_line_processor } = require('haraka-net-utils')
|
|
7
|
+
|
|
8
|
+
const tls_socket = require('./tls_socket')
|
|
9
|
+
|
|
10
|
+
exports.Socket = LineSocket
|
|
11
|
+
|
|
12
|
+
// New interface - uses TLS
|
|
13
|
+
exports.connect = (port, host) => {
|
|
14
|
+
let options = {}
|
|
15
|
+
if (typeof port === 'object') {
|
|
16
|
+
options = port
|
|
17
|
+
} else {
|
|
18
|
+
options.port = port
|
|
19
|
+
options.host = host
|
|
20
|
+
}
|
|
21
|
+
const sock = tls_socket.connect(options)
|
|
22
|
+
add_line_processor(sock)
|
|
23
|
+
return sock
|
|
24
|
+
}
|