Haraka 3.0.2 → 3.0.4

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.
Files changed (267) hide show
  1. package/.eslintrc.yaml +5 -9
  2. package/.prettierrc.yml +1 -0
  3. package/CONTRIBUTORS.md +11 -0
  4. package/Changes.md +1393 -1211
  5. package/Dockerfile +3 -3
  6. package/Plugins.md +119 -106
  7. package/README.md +7 -16
  8. package/TODO +1 -24
  9. package/bin/haraka +197 -298
  10. package/config/auth_flat_file.ini +2 -0
  11. package/config/auth_vpopmaild.ini +4 -2
  12. package/config/dhparams.pem +8 -0
  13. package/config/mail_from.is_resolvable.ini +4 -2
  14. package/config/me +1 -0
  15. package/config/outbound.ini +0 -2
  16. package/config/plugins +36 -35
  17. package/config/rabbitmq_amqplib.ini +8 -1
  18. package/config/smtp.ini +0 -1
  19. package/config/smtp.json +17 -0
  20. package/config/tls_cert.pem +23 -0
  21. package/config/tls_key.pem +28 -0
  22. package/connection.js +46 -73
  23. package/contrib/bsd-rc.d/haraka +3 -1
  24. package/contrib/plugin2npm.sh +6 -36
  25. package/docs/Connection.md +1 -1
  26. package/docs/CoreConfig.md +2 -2
  27. package/docs/Logging.md +7 -21
  28. package/docs/Outbound.md +104 -210
  29. package/docs/Plugins.md +47 -40
  30. package/docs/Transaction.md +59 -82
  31. package/docs/{plugins → deprecated}/connect.rdns_access.md +1 -1
  32. package/docs/{plugins → deprecated}/mail_from.access.md +1 -1
  33. package/docs/{plugins → deprecated}/rcpt_to.access.md +1 -1
  34. package/docs/plugins/auth/auth_vpopmaild.md +15 -19
  35. package/docs/plugins/auth/flat_file.md +23 -30
  36. package/docs/plugins/queue/rabbitmq_amqplib.md +7 -0
  37. package/docs/plugins/queue/smtp_forward.md +1 -1
  38. package/docs/plugins/queue/smtp_proxy.md +5 -10
  39. package/docs/plugins/relay.md +2 -2
  40. package/docs/plugins/tls.md +29 -9
  41. package/endpoint.js +16 -13
  42. package/haraka.js +10 -14
  43. package/host_pool.js +5 -5
  44. package/line_socket.js +3 -4
  45. package/logger.js +44 -28
  46. package/outbound/client_pool.js +27 -23
  47. package/outbound/config.js +4 -6
  48. package/outbound/fsync_writestream.js +1 -1
  49. package/outbound/hmail.js +180 -220
  50. package/outbound/index.js +86 -99
  51. package/outbound/qfile.js +1 -1
  52. package/outbound/queue.js +55 -43
  53. package/outbound/timer_queue.js +3 -2
  54. package/outbound/tls.js +19 -7
  55. package/package.json +66 -55
  56. package/plugins/.eslintrc.yaml +0 -6
  57. package/plugins/auth/auth_base.js +30 -12
  58. package/plugins/auth/auth_proxy.js +14 -12
  59. package/plugins/auth/auth_vpopmaild.js +30 -20
  60. package/plugins/auth/flat_file.js +17 -12
  61. package/plugins/block_me.js +1 -1
  62. package/plugins/data.signatures.js +2 -4
  63. package/plugins/early_talker.js +2 -1
  64. package/plugins/mail_from.is_resolvable.js +65 -135
  65. package/plugins/queue/deliver.js +4 -5
  66. package/plugins/queue/lmtp.js +11 -14
  67. package/plugins/queue/qmail-queue.js +2 -2
  68. package/plugins/queue/quarantine.js +2 -2
  69. package/plugins/queue/rabbitmq.js +16 -17
  70. package/plugins/queue/rabbitmq_amqplib.js +1 -1
  71. package/plugins/queue/smtp_forward.js +6 -6
  72. package/plugins/queue/smtp_proxy.js +10 -1
  73. package/plugins/queue/test.js +2 -2
  74. package/plugins/rcpt_to.host_list_base.js +5 -5
  75. package/plugins/rcpt_to.in_host_list.js +2 -2
  76. package/plugins/relay.js +6 -7
  77. package/plugins/reseed_rng.js +1 -1
  78. package/plugins/status.js +37 -33
  79. package/plugins/tls.js +2 -2
  80. package/plugins/xclient.js +3 -2
  81. package/plugins.js +51 -54
  82. package/run_tests +3 -30
  83. package/server.js +190 -190
  84. package/smtp_client.js +30 -23
  85. package/{tests → test}/config/plugins +0 -2
  86. package/{tests → test}/config/smtp.ini +1 -1
  87. package/test/config/tls/example.com/_.example.com.key +28 -0
  88. package/test/config/tls/example.com/example.com.crt +25 -0
  89. package/test/connection.js +302 -0
  90. package/test/endpoint.js +94 -0
  91. package/{tests → test}/fixtures/line_socket.js +1 -1
  92. package/{tests → test}/fixtures/util_hmailitem.js +19 -25
  93. package/{tests → test}/host_pool.js +42 -57
  94. package/test/logger.js +258 -0
  95. package/test/outbound/hmail.js +141 -0
  96. package/test/outbound/index.js +220 -0
  97. package/test/outbound/qfile.js +126 -0
  98. package/test/outbound_bounce_net_errors.js +142 -0
  99. package/{tests → test}/outbound_bounce_rfc3464.js +110 -122
  100. package/test/plugins/auth/auth_base.js +484 -0
  101. package/test/plugins/auth/auth_vpopmaild.js +83 -0
  102. package/test/plugins/early_talker.js +104 -0
  103. package/test/plugins/mail_from.is_resolvable.js +35 -0
  104. package/test/plugins/queue/smtp_forward.js +206 -0
  105. package/test/plugins/rcpt_to.host_list_base.js +122 -0
  106. package/test/plugins/rcpt_to.in_host_list.js +193 -0
  107. package/test/plugins/relay.js +303 -0
  108. package/test/plugins/status.js +130 -0
  109. package/test/plugins/tls.js +70 -0
  110. package/test/plugins.js +228 -0
  111. package/{tests → test}/queue/multibyte +0 -0
  112. package/{tests → test}/queue/plain +0 -0
  113. package/test/rfc1869.js +73 -0
  114. package/test/server.js +491 -0
  115. package/test/smtp_client.js +299 -0
  116. package/test/tls_socket.js +273 -0
  117. package/test/transaction.js +270 -0
  118. package/tls_socket.js +202 -252
  119. package/transaction.js +9 -24
  120. package/CONTRIBUTING.md +0 -1
  121. package/bin/dkimverify +0 -40
  122. package/config/access.domains +0 -13
  123. package/config/attachment.ctype.regex +0 -2
  124. package/config/attachment.filename.regex +0 -1
  125. package/config/avg.ini +0 -5
  126. package/config/bounce.ini +0 -15
  127. package/config/data.headers.ini +0 -61
  128. package/config/dkim/dkim_key_gen.sh +0 -78
  129. package/config/dkim_sign.ini +0 -4
  130. package/config/dkim_verify.ini +0 -7
  131. package/config/dnsbl.ini +0 -23
  132. package/config/greylist.ini +0 -43
  133. package/config/helo.checks.ini +0 -52
  134. package/config/lookup_rdns.strict.ini +0 -12
  135. package/config/lookup_rdns.strict.timeout +0 -1
  136. package/config/lookup_rdns.strict.whitelist +0 -1
  137. package/config/lookup_rdns.strict.whitelist_regex +0 -5
  138. package/config/messagesniffer.ini +0 -18
  139. package/config/rcpt_to.blocklist +0 -1
  140. package/config/rdns.allow_regexps +0 -0
  141. package/config/rdns.deny_regexps +0 -0
  142. package/config/spamassassin.ini +0 -56
  143. package/config.js +0 -6
  144. package/dkim.js +0 -614
  145. package/docs/plugins/avg.md +0 -35
  146. package/docs/plugins/bounce.md +0 -69
  147. package/docs/plugins/clamd.md +0 -147
  148. package/docs/plugins/esets.md +0 -8
  149. package/docs/plugins/greylist.md +0 -90
  150. package/docs/plugins/helo.checks.md +0 -135
  151. package/docs/plugins/messagesniffer.md +0 -163
  152. package/docs/plugins/relay_acl.md +0 -29
  153. package/docs/plugins/relay_all.md +0 -15
  154. package/docs/plugins/relay_force_routing.md +0 -33
  155. package/docs/plugins/spamassassin.md +0 -180
  156. package/outbound/mx_lookup.js +0 -70
  157. package/plugins/auth/auth_ldap.js +0 -3
  158. package/plugins/avg.js +0 -162
  159. package/plugins/backscatterer.js +0 -25
  160. package/plugins/bounce.js +0 -381
  161. package/plugins/clamd.js +0 -381
  162. package/plugins/data.headers.js +0 -4
  163. package/plugins/data.uribl.js +0 -4
  164. package/plugins/dkim_sign.js +0 -395
  165. package/plugins/dkim_verify.js +0 -62
  166. package/plugins/dns_list_base.js +0 -221
  167. package/plugins/dnsbl.js +0 -146
  168. package/plugins/dnswl.js +0 -58
  169. package/plugins/esets.js +0 -71
  170. package/plugins/graph.js +0 -5
  171. package/plugins/greylist.js +0 -645
  172. package/plugins/helo.checks.js +0 -533
  173. package/plugins/messagesniffer.js +0 -381
  174. package/plugins/rcpt_to.ldap.js +0 -3
  175. package/plugins/rcpt_to.max_count.js +0 -24
  176. package/plugins/relay_all.js +0 -13
  177. package/plugins/spamassassin.js +0 -384
  178. package/tests/config/dkim/example.com/dns +0 -29
  179. package/tests/config/dkim/example.com/private +0 -6
  180. package/tests/config/dkim/example.com/public +0 -4
  181. package/tests/config/dkim/example.com/selector +0 -1
  182. package/tests/config/dkim.private.key +0 -6
  183. package/tests/config/dkim_sign.ini +0 -4
  184. package/tests/config/helo.checks.ini +0 -52
  185. package/tests/connection.js +0 -327
  186. package/tests/endpoint.js +0 -128
  187. package/tests/fixtures/vm_harness.js +0 -59
  188. package/tests/logger.js +0 -327
  189. package/tests/outbound/hmail.js +0 -112
  190. package/tests/outbound/index.js +0 -324
  191. package/tests/outbound/qfile.js +0 -67
  192. package/tests/outbound_bounce_net_errors.js +0 -173
  193. package/tests/plugins/auth/auth_base.js +0 -463
  194. package/tests/plugins/auth/auth_vpopmaild.js +0 -91
  195. package/tests/plugins/bounce.js +0 -307
  196. package/tests/plugins/clamd.js +0 -224
  197. package/tests/plugins/deprecated/relay_acl.js +0 -140
  198. package/tests/plugins/deprecated/relay_all.js +0 -59
  199. package/tests/plugins/dkim_sign.js +0 -315
  200. package/tests/plugins/dkim_signer.js +0 -108
  201. package/tests/plugins/dns_list_base.js +0 -259
  202. package/tests/plugins/dnsbl.js +0 -101
  203. package/tests/plugins/early_talker.js +0 -115
  204. package/tests/plugins/greylist.js +0 -58
  205. package/tests/plugins/helo.checks.js +0 -525
  206. package/tests/plugins/mail_from.is_resolvable.js +0 -116
  207. package/tests/plugins/queue/smtp_forward.js +0 -221
  208. package/tests/plugins/rcpt_to.host_list_base.js +0 -132
  209. package/tests/plugins/rcpt_to.in_host_list.js +0 -218
  210. package/tests/plugins/relay.js +0 -339
  211. package/tests/plugins/spamassassin.js +0 -171
  212. package/tests/plugins/status.js +0 -138
  213. package/tests/plugins/tls.js +0 -84
  214. package/tests/plugins.js +0 -247
  215. package/tests/rfc1869.js +0 -61
  216. package/tests/server.js +0 -510
  217. package/tests/smtp_client/auth.js +0 -105
  218. package/tests/smtp_client/basic.js +0 -101
  219. package/tests/smtp_client.js +0 -80
  220. package/tests/tls_socket.js +0 -333
  221. package/tests/transaction.js +0 -284
  222. /package/docs/{plugins → deprecated}/dkim_sign.md +0 -0
  223. /package/docs/{plugins → deprecated}/dkim_verify.md +0 -0
  224. /package/docs/{plugins → deprecated}/dnsbl.md +0 -0
  225. /package/docs/{plugins → deprecated}/dnswl.md +0 -0
  226. /package/docs/{plugins → deprecated}/rcpt_to.routes.md +0 -0
  227. /package/{tests → test}/.eslintrc.yaml +0 -0
  228. /package/{tests → test}/config/auth_flat_file.ini +0 -0
  229. /package/{tests → test}/config/dhparams.pem +0 -0
  230. /package/{tests → test}/config/host_list +0 -0
  231. /package/{tests → test}/config/outbound_tls_cert.pem +0 -0
  232. /package/{tests → test}/config/outbound_tls_key.pem +0 -0
  233. /package/{tests → test}/config/smtp_forward.ini +0 -0
  234. /package/{tests → test}/config/tls/ec.pem +0 -0
  235. /package/{tests → test}/config/tls/haraka.local.pem +0 -0
  236. /package/{tests → test}/config/tls/mismatched.pem +0 -0
  237. /package/{tests → test}/config/tls.ini +0 -0
  238. /package/{tests → test}/config/tls_cert.pem +0 -0
  239. /package/{tests → test}/config/tls_key.pem +0 -0
  240. /package/{tests → test}/fixtures/todo_qfile.txt +0 -0
  241. /package/{tests → test}/installation/config/test-plugin-flat +0 -0
  242. /package/{tests → test}/installation/config/test-plugin.ini +0 -0
  243. /package/{tests → test}/installation/config/tls.ini +0 -0
  244. /package/{tests → test}/installation/node_modules/load_first/index.js +0 -0
  245. /package/{tests → test}/installation/node_modules/load_first/package.json +0 -0
  246. /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin-flat +0 -0
  247. /package/{tests → test}/installation/node_modules/test-plugin/config/test-plugin.ini +0 -0
  248. /package/{tests → test}/installation/node_modules/test-plugin/package.json +0 -0
  249. /package/{tests → test}/installation/node_modules/test-plugin/test-plugin.js +0 -0
  250. /package/{tests → test}/installation/plugins/base_plugin.js +0 -0
  251. /package/{tests → test}/installation/plugins/folder_plugin/index.js +0 -0
  252. /package/{tests → test}/installation/plugins/folder_plugin/package.json +0 -0
  253. /package/{tests → test}/installation/plugins/inherits.js +0 -0
  254. /package/{tests → test}/installation/plugins/load_first.js +0 -0
  255. /package/{tests → test}/installation/plugins/plugin.js +0 -0
  256. /package/{tests → test}/installation/plugins/tls.js +0 -0
  257. /package/{tests → test}/loud/config/dhparams.pem +0 -0
  258. /package/{tests → test}/loud/config/tls/goobered.pem +0 -0
  259. /package/{tests → test}/loud/config/tls.ini +0 -0
  260. /package/{tests → test}/mail_specimen/base64-root-part.txt +0 -0
  261. /package/{tests → test}/mail_specimen/varied-fold-lengths-preserve-data.txt +0 -0
  262. /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_fixed +0 -0
  263. /package/{tests → test}/queue/1507509981169_1507509981169_0_61403_e0Y0Ym_1_haraka +0 -0
  264. /package/{tests → test}/queue/1508269674999_1508269674999_0_34002_socVUF_1_haraka +0 -0
  265. /package/{tests → test}/queue/1508455115683_1508455115683_0_90253_9Q4o4V_1_haraka +0 -0
  266. /package/{tests → test}/queue/zero-length +0 -0
  267. /package/{tests → test}/test-queue/delete-me +0 -0
@@ -1,384 +0,0 @@
1
- 'use strict';
2
- // Call spamassassin via spamd
3
-
4
- const sock = require('./line_socket');
5
- const utils = require('haraka-utils');
6
-
7
- exports.register = function () {
8
- this.load_spamassassin_ini();
9
- }
10
-
11
- exports.load_spamassassin_ini = function () {
12
- this.cfg = this.config.get('spamassassin.ini', {
13
- booleans: [
14
- '+add_headers',
15
- '+check.authenticated',
16
- '+check.private_ip',
17
- '+check.local_ip',
18
- '+check.relay',
19
-
20
- '-defer.error',
21
- '-defer.connect_timeout',
22
- '-defer.scan_timeout',
23
- ],
24
- }, () => {
25
- this.load_spamassassin_ini();
26
- });
27
-
28
- const defaults = {
29
- spamd_socket: 'localhost:783',
30
- max_size: 500000,
31
- old_headers_action: "rename",
32
- subject_prefix: "*** SPAM ***",
33
- spamc_auth_header: 'X-Haraka-Relay',
34
- };
35
-
36
- for (const key in defaults) {
37
- if (this.cfg.main[key]) continue;
38
- this.cfg.main[key] = defaults[key];
39
- }
40
-
41
- [
42
- 'reject_threshold', 'relay_reject_threshold',
43
- 'munge_subject_threshold', 'max_size'
44
- ].forEach(item => {
45
- if (!this.cfg.main[item]) return;
46
- this.cfg.main[item] = Number(this.cfg.main[item]);
47
- });
48
- }
49
-
50
- exports.hook_data_post = function (next, connection) {
51
-
52
- if (this.should_skip(connection)) return next();
53
-
54
- const txn = connection.transaction;
55
- txn.remove_header(this.cfg.main.spamc_auth_header); // just to be safe
56
-
57
- const username = this.get_spamd_username(connection);
58
- const headers = this.get_spamd_headers(connection, username);
59
- const socket = this.get_spamd_socket(next, connection, headers);
60
-
61
- const spamd_response = { headers: {} };
62
- let state = 'line0';
63
- let last_header;
64
- const start = Date.now();
65
-
66
- socket.on('line', line => {
67
- connection.logprotocol(this, `Spamd C: ${line} state=${state}`);
68
- line = line.replace(/\r?\n/, '');
69
- if (state === 'line0') {
70
- spamd_response.line0 = line;
71
- state = 'response';
72
- }
73
- else if (state === 'response') {
74
- if (line.match(/\S/)) {
75
- const matches = line.match(/Spam: (True|False) ; (-?\d+\.\d) \/ (-?\d+\.\d)/);
76
- if (matches) {
77
- spamd_response.flag = matches[1];
78
- spamd_response.score = matches[2];
79
- spamd_response.hits = matches[2]; // backwards compat
80
- spamd_response.reqd = matches[3];
81
- spamd_response.flag = spamd_response.flag === 'True' ? 'Yes' : 'No';
82
- }
83
- }
84
- else {
85
- state = 'headers';
86
- }
87
- }
88
- else if (state === 'headers') {
89
- const m = line.match(/^X-Spam-([\x21-\x39\x3B-\x7E]+):\s*(.*)/);
90
- if (m) {
91
- connection.logdebug(this, `header: ${line}`);
92
- last_header = m[1];
93
- spamd_response.headers[m[1]] = m[2];
94
- return;
95
- }
96
- let fold;
97
- if (last_header && (fold = line.match(/^(\s+.*)/))) {
98
- spamd_response.headers[last_header] += `\r\n${fold[1]}`;
99
- return;
100
- }
101
- last_header = '';
102
- }
103
- });
104
-
105
- socket.once('end', () => {
106
- if (!connection.transaction) return next() // client gone
107
-
108
- if (spamd_response.headers?.Tests) {
109
- spamd_response.tests = spamd_response.headers.Tests.replace(/\s/g, '');
110
- }
111
- if (spamd_response.tests === undefined) {
112
- // strip the 'tests' from the X-Spam-Status header
113
- if (spamd_response.headers?.Status) {
114
- // SpamAssassin appears to have a bug that causes a space not to
115
- // be added before autolearn= when the header line has been folded.
116
- // So we modify the regexp here not to match autolearn onwards.
117
- const tests = /tests=((?:(?!autolearn)[^ ])+)/.exec(
118
- spamd_response.headers.Status.replace(/\r?\n\t/g,'')
119
- );
120
- if (tests) spamd_response.tests = tests[1];
121
- }
122
- }
123
-
124
- // do stuff with the results...
125
- txn.notes.spamassassin = spamd_response;
126
- connection.results.add(this, {
127
- time: (Date.now() - start)/1000,
128
- hits: spamd_response.hits,
129
- flag: spamd_response.flag,
130
- });
131
-
132
- this.fixup_old_headers(txn);
133
- this.do_header_updates(connection, spamd_response);
134
- this.log_results(connection, spamd_response);
135
-
136
- const exceeds_err = this.score_too_high(connection, spamd_response);
137
- if (exceeds_err) return next(DENY, exceeds_err);
138
-
139
- this.munge_subject(connection, spamd_response.score);
140
-
141
- next();
142
- });
143
- }
144
-
145
- exports.fixup_old_headers = function (txn) {
146
- const action = this.cfg.main.old_headers_action;
147
- const { headers } = txn.notes.spamassassin;
148
-
149
- let key;
150
- switch (action) {
151
- case "keep":
152
- break;
153
- case "drop":
154
- for (key in headers) {
155
- if (!key) continue;
156
- txn.remove_header(`X-Spam-${key}`);
157
- }
158
- break;
159
- // case 'rename':
160
- default:
161
- for (key in headers) {
162
- if (!key) continue;
163
- key = `X-Spam-${key}`;
164
- const old_val = txn.header.get(key);
165
- txn.remove_header(key);
166
- if (old_val) {
167
- // plugin.logdebug(plugin, `header: ${key}, ${old_val}`);
168
- txn.add_header(key.replace(/^X-/, 'X-Old-'), old_val);
169
- }
170
- }
171
- break;
172
- }
173
- }
174
-
175
- exports.munge_subject = function (conn, score) {
176
- const munge = this.cfg.main.munge_subject_threshold;
177
- if (!munge) return;
178
- if (parseFloat(score) < parseFloat(munge)) return;
179
-
180
- const subj = conn.transaction.header.get('Subject');
181
- const subject_re = new RegExp(`^${utils.regexp_escape(this.cfg.main.subject_prefix)}`);
182
- if (subject_re.test(subj)) return; // prevent double munge
183
-
184
- conn.transaction.remove_header('Subject');
185
- conn.transaction.add_header('Subject', `${this.cfg.main.subject_prefix} ${subj}`);
186
- }
187
-
188
- exports.do_header_updates = function (conn, spamd_response) {
189
- if (spamd_response.flag === 'Yes') {
190
- // X-Spam-Flag is added by SpamAssassin
191
- conn.transaction.remove_header('precedence');
192
- conn.transaction.add_header('Precedence', 'junk');
193
- }
194
-
195
- const modern = this.cfg.main.modern_status_syntax;
196
- if ( !this.cfg.main.add_headers ) return;
197
-
198
- for (const key in spamd_response.headers) {
199
- if (!key || key === '' || key === undefined) continue;
200
- let val = spamd_response.headers[key];
201
- if (val === undefined) { val = ''; }
202
-
203
- if (key === 'Status' && !modern) {
204
- const legacy = spamd_response.headers[key].replace(/ score=/,' hits=');
205
- conn.transaction.add_header('X-Spam-Status', legacy);
206
- continue;
207
- }
208
- if (val === '') continue;
209
- conn.transaction.add_header(`X-Spam-${key}`, val);
210
- }
211
- }
212
-
213
- exports.score_too_high = function (conn, spamd_response) {
214
- const { score } = spamd_response;
215
- if (conn.relaying) {
216
- const rmax = this.cfg.main.relay_reject_threshold;
217
- if (rmax && (score >= rmax)) {
218
- return "spam score exceeded relay threshold";
219
- }
220
- }
221
-
222
- const max = this.cfg.main.reject_threshold;
223
- if (max && (score >= max)) return "spam score exceeded threshold";
224
-
225
- return '';
226
- }
227
-
228
- exports.get_spamd_username = function (conn) {
229
-
230
- let user = conn.transaction.notes.spamd_user; // 1st priority
231
- if (user && user !== undefined) return user;
232
-
233
- if (!this.cfg.main.spamd_user) return 'default'; // when not defined
234
- user = this.cfg.main.spamd_user;
235
-
236
- // Enable per-user SA prefs
237
- if (user === 'first-recipient') { // special cases
238
- return conn.transaction.rcpt_to[0].address();
239
- }
240
- if (user === 'all-recipients') {
241
- throw "Unimplemented";
242
- // TODO: pass the message through SA for each recipient. Then apply
243
- // the least strict result to the connection. That is useful when
244
- // one user blacklists a sender that another user wants to get mail
245
- // from. If this is something you care about, this is the spot.
246
- }
247
- return user;
248
- }
249
-
250
- exports.get_spamd_headers = function (conn, username) {
251
- // http://svn.apache.org/repos/asf/spamassassin/trunk/spamd/PROTOCOL
252
- const headers = [
253
- 'HEADERS SPAMC/1.4',
254
- `User: ${username}`,
255
- '',
256
- `X-Envelope-From: ${conn.transaction.mail_from.address()}`,
257
- `X-Haraka-UUID: ${conn.transaction.uuid}`,
258
- ];
259
- if (conn.relaying) {
260
- headers.push(`${this.cfg.main.spamc_auth_header}: true`);
261
- }
262
-
263
- return headers;
264
- }
265
-
266
- exports.get_spamd_socket = function (next, conn, headers) {
267
- const plugin = this;
268
- const txn = conn.transaction;
269
-
270
- // TODO: support multiple spamd backends
271
-
272
- const socket = new sock.Socket();
273
- socket.is_connected = false;
274
- const results_timeout = parseInt(plugin.cfg.main.results_timeout) || 300;
275
-
276
- socket.on('connect', function () {
277
- // Abort if the transaction is gone
278
- if (!txn) {
279
- plugin.logwarn(conn, 'Transaction gone, cancelling SPAMD connection');
280
- socket.end();
281
- return;
282
- }
283
-
284
- this.is_connected = true;
285
- // Reset timeout
286
- this.setTimeout(results_timeout * 1000);
287
- socket.write(`${headers.join("\r\n")}\r\n`);
288
- conn.transaction.message_stream.pipe(socket);
289
- });
290
-
291
- socket.on('error', err => {
292
- socket.destroy();
293
- if (txn) txn.results.add(plugin, {err: `socket error: ${err.message}` });
294
- if (plugin.cfg.defer.error) return next(DENYSOFT, 'spamd scan error');
295
- return next();
296
- });
297
-
298
- socket.on('timeout', function () {
299
- socket.destroy();
300
- if (!this.is_connected) {
301
- if (txn) txn.results.add(plugin, {err: `socket connect timeout` });
302
- if (plugin.cfg.defer.connect_timeout) return next(DENYSOFT, 'spamd connect timeout');
303
- }
304
- else {
305
- if (txn) txn.results.add(plugin, {err: `timeout waiting for results` });
306
- if (plugin.cfg.defer.scan_timeout) return next(DENYSOFT, 'spamd scan timeout');
307
- }
308
- return next();
309
- });
310
-
311
- const connect_timeout = parseInt(plugin.cfg.main.connect_timeout) || 30;
312
- socket.setTimeout(connect_timeout * 1000);
313
-
314
- if (plugin.cfg.main.spamd_socket.match(/\//)) { // assume unix socket
315
- socket.connect(plugin.cfg.main.spamd_socket);
316
- }
317
- else {
318
- const hostport = plugin.cfg.main.spamd_socket.split(/:/);
319
- socket.connect((hostport[1] || 783), hostport[0]);
320
- }
321
-
322
- return socket;
323
- }
324
-
325
- exports.log_results = function (conn, spamd_response) {
326
- const cfg = this.cfg.main;
327
- const reject_threshold = (conn.relaying) ? (cfg.relay_reject_threshold || cfg.reject_threshold) : cfg.reject_threshold;
328
-
329
- const human_text = `status=${spamd_response.flag}` +
330
- `, score=${spamd_response.score}` +
331
- `, required=${spamd_response.reqd}` +
332
- `, reject=${reject_threshold}` +
333
- `, tests="${spamd_response.tests}"`;
334
-
335
- conn.transaction.results.add(this, {
336
- human: human_text,
337
- status: spamd_response.flag, score: parseFloat(spamd_response.score),
338
- required: parseFloat(spamd_response.reqd), reject: reject_threshold, tests: spamd_response.tests,
339
- emit: true});
340
- }
341
-
342
- exports.should_skip = function (connection = {}) {
343
- const { transaction } = connection;
344
- if (!transaction) return true;
345
-
346
- // a message might be skipped for multiple reasons, store each in results
347
- let result = false; // default
348
-
349
- const max = this.cfg.main.max_size;
350
- if (max) {
351
- const size = connection.transaction.data_bytes;
352
- if (size > max) {
353
- connection.transaction.results.add(this, { skip: `size ${utils.prettySize(size)} exceeds max: ${utils.prettySize(max)}`});
354
- result = true;
355
- }
356
- }
357
-
358
- if (this.cfg.check.authenticated == false && connection.notes.auth_user) {
359
- connection.transaction.results.add(this, { skip: 'authed'});
360
- result = true;
361
- }
362
-
363
- if (this.cfg.check.relay == false && connection.relaying) {
364
- connection.transaction.results.add(this, { skip: 'relay'});
365
- result = true;
366
- }
367
-
368
- if (this.cfg.check.local_ip == false && connection.remote.is_local) {
369
- connection.transaction.results.add(this, { skip: 'local_ip'});
370
- result = true;
371
- }
372
-
373
- if (this.cfg.check.private_ip == false && connection.remote.is_private) {
374
- if (this.cfg.check.local_ip == true && connection.remote.is_local) {
375
- // local IPs are included in private IPs
376
- }
377
- else {
378
- connection.transaction.results.add(this, { skip: 'private_ip'});
379
- result = true;
380
- }
381
- }
382
-
383
- return result;
384
- }
@@ -1,29 +0,0 @@
1
-
2
- Add this TXT record to the example.com DNS zone.
3
-
4
- aug2019._domainkey IN TXT v=DKIM1;p=MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhALMNxNuzG2bsZlqWH4zV+V8ykzMSL/GyAFPzKY4iROa5AgMBAAE=
5
-
6
-
7
- BIND zone file formatted:
8
-
9
- aug2019._domainkey IN TXT (
10
- "v=DKIM1;p=MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhALMNxNuzG2bsZlqWH4zV+V8ykzMSL/GyAFPzKY4iROa5AgMBAAE="
11
- )
12
-
13
- Tell the world that the ONLY mail servers that send mail from this domain are DKIM signed and/or bear our MX and A records.
14
-
15
- With SPF:
16
-
17
- SPF "v=spf1 mx a -all"
18
- TXT "v=spf1 mx a -all"
19
-
20
- With DMARC:
21
-
22
- _dmarc TXT "v=DMARC1; p=reject; adkim=s; aspf=r; rua=mailto:dmarc-feedback@example.com; ruf=mailto:dmarc-feedback@example.com; pct=100"
23
-
24
- For more information about DKIM and SPF policy,
25
- the documentation within each plugin contains a longer discussion and links to more detailed information:
26
-
27
- haraka -h dkim_sign
28
- haraka -h spf
29
-
@@ -1,6 +0,0 @@
1
- -----BEGIN RSA PRIVATE KEY-----
2
- MIGqAgEAAiEAsw3E27MbZuxmWpYfjNX5XzKTMxIv8bIAU/MpjiJE5rkCAwEAAQIg
3
- IVsyTj96nlzx4HRRIlqGXw7wx3C+vGhoM/Ql/eFXRVECEQDbUYF19fyzPDKAqb7p
4
- Eu5tAhEA0QBD5Ns4QgpC8m1Qob05/QIQf1jWWU5aSyC7GmZ2ChQKCQIQIACNZNaY
5
- Z6xQkfRhG1LxNQIRAIyKwDCULf7Jl5ygc1MIIdk=
6
- -----END RSA PRIVATE KEY-----
@@ -1,4 +0,0 @@
1
- -----BEGIN PUBLIC KEY-----
2
- MDwwDQYJKoZIhvcNAQEBBQADKwAwKAIhALMNxNuzG2bsZlqWH4zV+V8ykzMSL/Gy
3
- AFPzKY4iROa5AgMBAAE=
4
- -----END PUBLIC KEY-----
@@ -1 +0,0 @@
1
- aug2019
@@ -1,6 +0,0 @@
1
- -----BEGIN RSA PRIVATE KEY-----
2
- MIGqAgEAAiEAsw3E27MbZuxmWpYfjNX5XzKTMxIv8bIAU/MpjiJE5rkCAwEAAQIg
3
- IVsyTj96nlzx4HRRIlqGXw7wx3C+vGhoM/Ql/eFXRVECEQDbUYF19fyzPDKAqb7p
4
- Eu5tAhEA0QBD5Ns4QgpC8m1Qob05/QIQf1jWWU5aSyC7GmZ2ChQKCQIQIACNZNaY
5
- Z6xQkfRhG1LxNQIRAIyKwDCULf7Jl5ygc1MIIdk=
6
- -----END RSA PRIVATE KEY-----
@@ -1,4 +0,0 @@
1
- disabled = false
2
- selector = mail
3
- domain = example.com
4
- headers_to_sign = From, Sender, Reply-To, Subject, Date, Message-ID, To, Cc, MIME-Version
@@ -1,52 +0,0 @@
1
- ; disable checks or reject for each test if you are worried about strictness
2
-
3
- ;dns_timeout=30
4
-
5
- [check]
6
- match_re=true
7
- bare_ip=true
8
- dynamic=true
9
- big_company=true
10
- ; literal_mismatch: 1 = exact IP match, 2 = IP/24 match, 3 = /24 or RFC1918
11
- literal_mismatch=2
12
- valid_hostname=true
13
- forward_dns=true
14
- rdns_match=true
15
- ; host_mismatch: hostname differs between EHLO invocations
16
- host_mismatch=true
17
- proto_mismatch: host sent EHLO but then tries to sent HELO or vice-versa
18
- proto_mismatch=true
19
-
20
- [reject]
21
- host_mismatch=true
22
- proto_mismatch=true
23
- rdns_match=true
24
- dynamic=true
25
- bare_ip=true
26
- literal_mismatch=true
27
- valid_hostname=true
28
- forward_dns=true
29
- big_company=true
30
-
31
- [skip]
32
- private_ip=true
33
- relaying=true
34
- whitelist=true
35
-
36
- [bigco]
37
- msn.com=msn.com
38
- hotmail.com=hotmail.com
39
- yahoo.com=yahoo.com,yahoo.co.jp
40
- yahoo.co.jp=yahoo.com,yahoo.co.jp
41
- yahoo.co.uk=yahoo.co.uk
42
- excite.com=excite.com,excitenetwork.com
43
- mailexcite.com=excite.com,excitenetwork.com
44
- yahoo.co.jp=yahoo.com,yahoo.co.jp
45
- mailexcite.com=excite.com,excitenetwork.com
46
- aol.com=aol.com
47
- compuserve.com=compuserve.com,adelphia.net
48
- nortelnetworks.com=nortelnetworks.com,nortel.com
49
- earthlink.net=earthlink.net
50
- earthling.net=earthling.net
51
- google.com=google.com
52
- gmail.com=google.com,gmail.com