Haraka 3.1.0 → 3.1.2

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 (160) hide show
  1. package/.prettierignore +4 -0
  2. package/CONTRIBUTORS.md +5 -5
  3. package/Changes.md +69 -50
  4. package/Plugins.md +3 -1
  5. package/README.md +1 -1
  6. package/bin/haraka +475 -478
  7. package/config/outbound.ini +3 -0
  8. package/connection.js +1072 -1108
  9. package/docs/Connection.md +29 -30
  10. package/docs/CoreConfig.md +38 -39
  11. package/docs/CustomReturnCodes.md +0 -1
  12. package/docs/HAProxy.md +2 -2
  13. package/docs/Header.md +1 -1
  14. package/docs/Logging.md +29 -5
  15. package/docs/Outbound.md +93 -78
  16. package/docs/Plugins.md +103 -108
  17. package/docs/Transaction.md +49 -51
  18. package/docs/Tutorial.md +127 -143
  19. package/docs/deprecated/access.md +0 -1
  20. package/docs/deprecated/backscatterer.md +2 -3
  21. package/docs/deprecated/connect.rdns_access.md +18 -27
  22. package/docs/deprecated/data.headers.md +0 -1
  23. package/docs/deprecated/data.nomsgid.md +1 -2
  24. package/docs/deprecated/data.noreceived.md +1 -2
  25. package/docs/deprecated/data.rfc5322_header_checks.md +1 -2
  26. package/docs/deprecated/dkim_sign.md +13 -17
  27. package/docs/deprecated/dkim_verify.md +9 -17
  28. package/docs/deprecated/dnsbl.md +36 -38
  29. package/docs/deprecated/dnswl.md +41 -43
  30. package/docs/deprecated/lookup_rdns.strict.md +21 -34
  31. package/docs/deprecated/mail_from.access.md +17 -25
  32. package/docs/deprecated/mail_from.blocklist.md +9 -12
  33. package/docs/deprecated/mail_from.nobounces.md +1 -2
  34. package/docs/deprecated/rcpt_to.access.md +20 -27
  35. package/docs/deprecated/rcpt_to.blocklist.md +10 -13
  36. package/docs/deprecated/rcpt_to.routes.md +0 -1
  37. package/docs/deprecated/rdns.regexp.md +13 -15
  38. package/docs/plugins/aliases.md +89 -89
  39. package/docs/plugins/auth/auth_bridge.md +5 -7
  40. package/docs/plugins/auth/auth_ldap.md +11 -14
  41. package/docs/plugins/auth/auth_proxy.md +10 -12
  42. package/docs/plugins/auth/auth_vpopmaild.md +5 -6
  43. package/docs/plugins/auth/flat_file.md +4 -4
  44. package/docs/plugins/block_me.md +3 -3
  45. package/docs/plugins/data.signatures.md +1 -2
  46. package/docs/plugins/delay_deny.md +3 -4
  47. package/docs/plugins/max_unrecognized_commands.md +4 -4
  48. package/docs/plugins/prevent_credential_leaks.md +6 -6
  49. package/docs/plugins/process_title.md +18 -18
  50. package/docs/plugins/queue/deliver.md +2 -3
  51. package/docs/plugins/queue/discard.md +4 -4
  52. package/docs/plugins/queue/lmtp.md +1 -3
  53. package/docs/plugins/queue/qmail-queue.md +7 -9
  54. package/docs/plugins/queue/quarantine.md +16 -21
  55. package/docs/plugins/queue/rabbitmq.md +8 -11
  56. package/docs/plugins/queue/rabbitmq_amqplib.md +43 -39
  57. package/docs/plugins/queue/smtp_bridge.md +7 -10
  58. package/docs/plugins/queue/smtp_forward.md +42 -34
  59. package/docs/plugins/queue/smtp_proxy.md +30 -29
  60. package/docs/plugins/queue/test.md +1 -3
  61. package/docs/plugins/rcpt_to.in_host_list.md +6 -6
  62. package/docs/plugins/rcpt_to.max_count.md +1 -1
  63. package/docs/plugins/record_envelope_addresses.md +3 -3
  64. package/docs/plugins/reseed_rng.md +6 -6
  65. package/docs/plugins/status.md +9 -8
  66. package/docs/plugins/tarpit.md +7 -11
  67. package/docs/plugins/tls.md +12 -17
  68. package/docs/plugins/toobusy.md +4 -4
  69. package/docs/plugins/xclient.md +3 -3
  70. package/docs/tutorials/Migrating_from_v1_to_v2.md +19 -41
  71. package/docs/tutorials/SettingUpOutbound.md +6 -9
  72. package/endpoint.js +35 -38
  73. package/eslint.config.mjs +22 -19
  74. package/haraka.js +42 -47
  75. package/host_pool.js +75 -79
  76. package/http/html/404.html +45 -49
  77. package/http/html/index.html +39 -28
  78. package/http/package.json +2 -4
  79. package/line_socket.js +27 -28
  80. package/logger.js +182 -201
  81. package/outbound/client_pool.js +34 -27
  82. package/outbound/config.js +64 -59
  83. package/outbound/fsync_writestream.js +24 -25
  84. package/outbound/hmail.js +888 -835
  85. package/outbound/index.js +194 -187
  86. package/outbound/qfile.js +49 -52
  87. package/outbound/queue.js +197 -190
  88. package/outbound/timer_queue.js +41 -43
  89. package/outbound/tls.js +68 -61
  90. package/outbound/todo.js +11 -11
  91. package/package.json +38 -33
  92. package/plugins/.eslintrc.yaml +0 -1
  93. package/plugins/auth/auth_base.js +123 -127
  94. package/plugins/auth/auth_bridge.js +7 -7
  95. package/plugins/auth/auth_proxy.js +121 -126
  96. package/plugins/auth/auth_vpopmaild.js +84 -85
  97. package/plugins/auth/flat_file.js +18 -17
  98. package/plugins/block_me.js +31 -31
  99. package/plugins/data.signatures.js +13 -13
  100. package/plugins/delay_deny.js +65 -61
  101. package/plugins/prevent_credential_leaks.js +23 -23
  102. package/plugins/process_title.js +125 -128
  103. package/plugins/profile.js +5 -5
  104. package/plugins/queue/deliver.js +3 -3
  105. package/plugins/queue/discard.js +13 -14
  106. package/plugins/queue/lmtp.js +16 -17
  107. package/plugins/queue/qmail-queue.js +54 -55
  108. package/plugins/queue/quarantine.js +68 -70
  109. package/plugins/queue/rabbitmq.js +80 -87
  110. package/plugins/queue/rabbitmq_amqplib.js +75 -54
  111. package/plugins/queue/smtp_bridge.js +16 -16
  112. package/plugins/queue/smtp_forward.js +175 -179
  113. package/plugins/queue/smtp_proxy.js +69 -71
  114. package/plugins/queue/test.js +9 -9
  115. package/plugins/rcpt_to.host_list_base.js +30 -34
  116. package/plugins/rcpt_to.in_host_list.js +19 -19
  117. package/plugins/record_envelope_addresses.js +4 -4
  118. package/plugins/reseed_rng.js +4 -4
  119. package/plugins/status.js +90 -97
  120. package/plugins/tarpit.js +25 -14
  121. package/plugins/tls.js +68 -68
  122. package/plugins/toobusy.js +21 -23
  123. package/plugins/xclient.js +51 -53
  124. package/plugins.js +276 -293
  125. package/rfc1869.js +30 -35
  126. package/server.js +308 -299
  127. package/smtp_client.js +244 -228
  128. package/test/.eslintrc.yaml +0 -1
  129. package/test/connection.js +127 -134
  130. package/test/endpoint.js +53 -47
  131. package/test/fixtures/line_socket.js +12 -12
  132. package/test/fixtures/util_hmailitem.js +89 -85
  133. package/test/host_pool.js +90 -92
  134. package/test/installation/plugins/base_plugin.js +2 -2
  135. package/test/installation/plugins/folder_plugin/index.js +2 -3
  136. package/test/installation/plugins/inherits.js +3 -3
  137. package/test/installation/plugins/load_first.js +2 -3
  138. package/test/installation/plugins/plugin.js +1 -3
  139. package/test/installation/plugins/tls.js +2 -4
  140. package/test/logger.js +135 -116
  141. package/test/outbound/hmail.js +49 -35
  142. package/test/outbound/index.js +118 -101
  143. package/test/outbound/qfile.js +51 -53
  144. package/test/outbound_bounce_net_errors.js +84 -69
  145. package/test/outbound_bounce_rfc3464.js +235 -165
  146. package/test/plugins/auth/auth_base.js +420 -279
  147. package/test/plugins/auth/auth_vpopmaild.js +38 -39
  148. package/test/plugins/queue/smtp_forward.js +126 -104
  149. package/test/plugins/rcpt_to.host_list_base.js +85 -67
  150. package/test/plugins/rcpt_to.in_host_list.js +159 -112
  151. package/test/plugins/status.js +71 -64
  152. package/test/plugins/tls.js +37 -34
  153. package/test/plugins.js +97 -92
  154. package/test/rfc1869.js +19 -26
  155. package/test/server.js +293 -272
  156. package/test/smtp_client.js +180 -176
  157. package/test/tls_socket.js +62 -66
  158. package/test/transaction.js +159 -160
  159. package/tls_socket.js +331 -333
  160. package/transaction.js +129 -137
package/docs/Plugins.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Most aspects of receiving an email in Haraka are controlled by plugins. Mail cannot even be received unless at least a 'rcpt' and 'queue' plugin are
4
4
  enabled.
5
5
 
6
- Recipient (*rcpt*) plugins determine if a particular recipient is allowed to be relayed or received for. A *queue* plugin queues the message somewhere - normally to disk or to an another SMTP server.
6
+ Recipient (_rcpt_) plugins determine if a particular recipient is allowed to be relayed or received for. A _queue_ plugin queues the message somewhere - normally to disk or to an another SMTP server.
7
7
 
8
8
  ## Plugin Lists
9
9
 
@@ -19,14 +19,13 @@ Display the help text for a plugin by running:
19
19
 
20
20
  ## Overview
21
21
 
22
-
23
22
  ## Anatomy of a Plugin
24
23
 
25
24
  Plugins in Haraka are JS files in the `plugins` directory (legacy) and npm
26
- modules in the node\_modules directory. See "Plugins as Modules" below.
25
+ modules in the node_modules directory. See "Plugins as Modules" below.
27
26
 
28
27
  Plugins can be installed in the Haraka global directory (default:
29
- /$os/$specific/lib/node\_modules/Haraka) or in the Haraka install directory
28
+ /$os/$specific/lib/node_modules/Haraka) or in the Haraka install directory
30
29
  (whatever you chose when you typed `haraka -i`. Example: `haraka -i /etc/haraka`
31
30
 
32
31
  To enable a plugin, add its name to `config/plugins`. For npm packaged plugins, the name does not include the `haraka-plugin` prefix.
@@ -37,27 +36,27 @@ Register is the only plugin function that is syncronous and receives no argument
37
36
 
38
37
  ### Register a Hook
39
38
 
40
- There are two ways for plugins to register hooks. Both examples register a function on the *rcpt* hook:
39
+ There are two ways for plugins to register hooks. Both examples register a function on the _rcpt_ hook:
41
40
 
42
41
  1. The `register_hook` function in register():
43
42
 
44
43
  ```js
45
44
  exports.register = function () {
46
- this.register_hook('rcpt', 'my_rcpt_validate')
47
- };
45
+ this.register_hook('rcpt', 'my_rcpt_validate')
46
+ }
48
47
 
49
48
  exports.my_rcpt_validate = function (next, connection, params) {
50
- // do processing
51
- next()
52
- };
49
+ // do processing
50
+ next()
51
+ }
53
52
  ```
54
53
 
55
- 2. The hook_[$name] syntax:
54
+ 2. The hook\_[$name] syntax:
56
55
 
57
56
  ```js
58
57
  exports.hook_rcpt = function (next, connection, params) {
59
- // do processing
60
- next()
58
+ // do processing
59
+ next()
61
60
  }
62
61
  ```
63
62
 
@@ -74,28 +73,28 @@ To register the same hook more than once, call `register_hook()` multiple times
74
73
 
75
74
  ```js
76
75
  exports.register = function () {
77
- this.register_hook('queue', 'try_queue_my_way')
78
- this.register_hook('queue', 'try_queue_highway')
79
- };
76
+ this.register_hook('queue', 'try_queue_my_way')
77
+ this.register_hook('queue', 'try_queue_highway')
78
+ }
80
79
  ```
81
80
 
82
- When `try_queue_my_way()` calls `next()`, the next function registered on hook *queue* will be called, in this case, `try_queue_highway()`.
81
+ When `try_queue_my_way()` calls `next()`, the next function registered on hook _queue_ will be called, in this case, `try_queue_highway()`.
83
82
 
84
83
  #### Determine hook name
85
84
 
86
85
  When a single function runs on multiple hooks, the function can check the
87
- *hook* property of the *connection* or *hmail* argument to determine which hook it is running on:
86
+ _hook_ property of the _connection_ or _hmail_ argument to determine which hook it is running on:
88
87
 
89
88
  ```js
90
89
  exports.register = function () {
91
- this.register_hook('rcpt', 'my_rcpt')
92
- this.register_hook('rcpt_ok', 'my_rcpt')
93
- };
94
-
90
+ this.register_hook('rcpt', 'my_rcpt')
91
+ this.register_hook('rcpt_ok', 'my_rcpt')
92
+ }
93
+
95
94
  exports.my_rcpt = function (next, connection, params) {
96
- const hook_name = connection.hook; // rcpt or rcpt_ok
97
- // email address is in params[0]
98
- // do processing
95
+ const hook_name = connection.hook // rcpt or rcpt_ok
96
+ // email address is in params[0]
97
+ // do processing
99
98
  }
100
99
  ```
101
100
 
@@ -113,20 +112,20 @@ After registering a hook, functions are called with that hooks arguments (see **
113
112
  These constants are in your plugin when it is loaded, you do not
114
113
  need to define them:
115
114
 
116
- * CONT
115
+ - CONT
117
116
 
118
117
  Continue and let other plugins handle this particular hook. This is the
119
118
  default. These are identical: `next()` and `next(CONT)`;
120
119
 
121
- * DENY - Reject with a 5xx error.
120
+ - DENY - Reject with a 5xx error.
122
121
 
123
- * DENYSOFT - Reject with a 4xx error.
122
+ - DENYSOFT - Reject with a 4xx error.
124
123
 
125
- * DENYDISCONNECT - Reject with a 5xx error and immediately disconnect.
124
+ - DENYDISCONNECT - Reject with a 5xx error and immediately disconnect.
126
125
 
127
- * DISCONNECT - Immediately disconnect
126
+ - DISCONNECT - Immediately disconnect
128
127
 
129
- * OK
128
+ - OK
130
129
 
131
130
  Required by `rcpt` plugins to accept a recipient and `queue` plugins when the queue was successful.
132
131
 
@@ -134,11 +133,11 @@ need to define them:
134
133
 
135
134
  Exceptions to next(OK):
136
135
 
137
- * connect_init and disconnect hooks are **always called**.
136
+ - connect_init and disconnect hooks are **always called**.
138
137
 
139
- * On the deny hook, `next(OK)` overrides the default CONT.
138
+ - On the deny hook, `next(OK)` overrides the default CONT.
140
139
 
141
- * HOOK\_NEXT
140
+ - HOOK_NEXT
142
141
 
143
142
  HOOK_NEXT is only available on the `unrecognized_command` hook. It instructs Haraka to run a different plugin hook. The `msg` argument must be set to the name of the hook to be run. Ex: `next(HOOK_NEXT, 'rcpt_ok');`
144
143
 
@@ -146,49 +145,49 @@ need to define them:
146
145
 
147
146
  These are the hook and their parameters (next excluded):
148
147
 
149
- * init\_master - called when the main (master) process is started
150
- * init\_child - in cluster, called when a child process is started
151
- * init\_http - called when Haraka is started.
152
- * init_wss - called after init_http
153
- * connect\_init - used to init data structures, called for *every* connection
154
- * lookup\_rdns - called to look up the rDNS - return the rDNS via `next(OK, rdns)`
155
- * connect - called after we got rDNS
156
- * capabilities - called to get the ESMTP capabilities (such as STARTTLS)
157
- * unrecognized\_command - called when the remote end sends a command we don't recognise
158
- * disconnect - called upon disconnect
159
- * helo (hostname)
160
- * ehlo (hostname)
161
- * quit
162
- * vrfy
163
- * noop
164
- * rset
165
- * mail ([from, esmtp\_params])
166
- * rcpt ([to, esmtp\_params])
167
- * rcpt\_ok (to)
168
- * data - called at the DATA command
169
- * data\_post - called at the end-of-data marker
170
- * max\_data\_exceeded - called when the message exceeds connection.max\_bytes
171
- * queue - called to queue the mail
172
- * queue\_outbound - called to queue the mail when connection.relaying is set
173
- * queue\_ok - called when a mail has been queued successfully
174
- * reset\_transaction - called before the transaction is reset (via RSET, or MAIL)
175
- * deny - called when a plugin returns DENY, DENYSOFT or DENYDISCONNECT
176
- * get\_mx (hmail, domain) - called by outbound to resolve the MX record
177
- * deferred (hmail, params) - called when an outbound message is deferred
178
- * bounce (hmail, err) - called when an outbound message bounces
179
- * delivered (hmail, [host, ip, response, delay, port, mode, ok_recips, secured, authenticated]) - called when outbound mail is delivered
180
- * send\_email (hmail) - called when outbound is about to be sent
181
- * pre\_send\_trans\_email (fake_connection) - called just before an email is queued to disk with a faked connection object
148
+ - init_master - called when the main (master) process is started
149
+ - init_child - in cluster, called when a child process is started
150
+ - init_http - called when Haraka is started.
151
+ - init_wss - called after init_http
152
+ - connect_init - used to init data structures, called for *every* connection
153
+ - lookup_rdns - called to look up the rDNS - return the rDNS via `next(OK, rdns)`
154
+ - connect - called after we got rDNS
155
+ - capabilities - called to get the ESMTP capabilities (such as STARTTLS)
156
+ - unrecognized_command - called when the remote end sends a command we don't recognise
157
+ - disconnect - called upon disconnect
158
+ - helo (hostname)
159
+ - ehlo (hostname)
160
+ - quit
161
+ - vrfy
162
+ - noop
163
+ - rset
164
+ - mail ([from, esmtp\_params])
165
+ - rcpt ([to, esmtp\_params])
166
+ - rcpt_ok (to)
167
+ - data - called at the DATA command
168
+ - data_post - called at the end-of-data marker
169
+ - max_data_exceeded - called when the message exceeds connection.max_bytes
170
+ - queue - called to queue the mail
171
+ - queue_outbound - called to queue the mail when connection.relaying is set
172
+ - queue_ok - called when a mail has been queued successfully
173
+ - reset_transaction - called before the transaction is reset (via RSET, or MAIL)
174
+ - deny - called when a plugin returns DENY, DENYSOFT or DENYDISCONNECT
175
+ - get_mx (hmail, domain) - called by outbound to resolve the MX record
176
+ - deferred (hmail, params) - called when an outbound message is deferred
177
+ - bounce (hmail, err) - called when an outbound message bounces
178
+ - delivered (hmail, [host, ip, response, delay, port, mode, ok_recips, secured, authenticated]) - called when outbound mail is delivered
179
+ - send_email (hmail) - called when outbound is about to be sent
180
+ - pre_send_trans_email (fake_connection) - called just before an email is queued to disk with a faked connection object
182
181
 
183
182
  ### rcpt
184
183
 
185
- The *rcpt* hook is slightly special.
184
+ The _rcpt_ hook is slightly special.
186
185
 
187
- When **connection.relaying == false** (the default, to avoid being an open relay), a rcpt plugin MUST return `next(OK)` or the sender will receive the error message "I cannot deliver for that user". The default *rcpt* plugin is **rcpt_to.in_host_list**, which lists the domains for which to accept email.
186
+ When **connection.relaying == false** (the default, to avoid being an open relay), a rcpt plugin MUST return `next(OK)` or the sender will receive the error message "I cannot deliver for that user". The default _rcpt_ plugin is **rcpt_to.in_host_list**, which lists the domains for which to accept email.
188
187
 
189
- After a *rcpt* plugin calls `next(OK)`, the *rcpt_ok* hook is run.
188
+ After a _rcpt_ plugin calls `next(OK)`, the _rcpt_ok_ hook is run.
190
189
 
191
- If a plugin prior to the *rcpt* hook sets **connection.relaying = true**, then it is not necessary for a rcpt plugin to call `next(OK)`.
190
+ If a plugin prior to the _rcpt_ hook sets **connection.relaying = true**, then it is not necessary for a rcpt plugin to call `next(OK)`.
192
191
 
193
192
  ### connect_init
194
193
 
@@ -202,11 +201,11 @@ If http listeners are are enabled in http.ini and the express module loaded, the
202
201
 
203
202
  If express loaded, an attempt is made to load [ws](https://www.npmjs.com/package/ws), the websocket server. If it succeeds, the wss server will be located at Server.http.wss. Because of how websockets work, only one websocket plugin will work at a time. One plugin using wss is [watch](https://github.com/haraka/Haraka/tree/master/plugins/watch).
204
203
 
205
- ### pre\_send\_trans\_email (next, fake_connection)
204
+ ### pre_send_trans_email (next, fake_connection)
206
205
 
207
206
  The `fake` connection here is a holder for a new transaction object. It only has the log methods and a `transaction` property
208
207
  so don't expect it to behave like a a real connection object. This hook is designed so you can add headers and modify mails
209
- sent via `outbound.send_email()`, see the dkim_sign plugin for an example.
208
+ sent via `outbound.send_email()`, see the dkim plugin for an example.
210
209
 
211
210
  ## Hook Order
212
211
 
@@ -217,18 +216,16 @@ The ordering of hooks is determined by the SMTP protocol. Knowledge of [RFC 5321
217
216
  - hook_connect_init
218
217
  - hook_lookup_rdns
219
218
  - hook_connect
220
- - hook_helo **OR** hook_ehlo (EHLO is sent when ESMTP is desired which allows extensions
221
- such as STARTTLS, AUTH, SIZE etc.)
222
- - hook_helo
223
- - hook_ehlo
224
- - hook_capabilities
225
- - *hook_unrecognized_command* is run for each ESMTP extension the client requests
226
- e.g. STARTTLS, AUTH etc.)
219
+ - hook_helo **OR** hook_ehlo
220
+ - hook_helo
221
+ - hook_ehlo (when ESMTP is desired, allows extensions such as STARTTLS, AUTH, SIZE etc.)
222
+ - hook_capabilities
223
+ - *hook_unrecognized_command* is run for each ESMTP extension the client requests (e.g. STARTTLS, AUTH etc.)
227
224
  - hook_mail
228
225
  - hook_rcpt (once per-recipient)
229
226
  - hook_rcpt_ok (for every recipient that hook_rcpt returned `next(OK)` for)
230
227
  - hook_data
231
- - *[attachment hooks]*
228
+ - _[attachment hooks]_
232
229
  - hook_data_post
233
230
  - hook_queue **OR** hook_queue_outbound
234
231
  - hook_queue_ok (called if hook_queue or hook_queue_outbound returns `next(OK)`)
@@ -239,16 +236,16 @@ e.g. STARTTLS, AUTH etc.)
239
236
  ##### Typical Outbound mail
240
237
 
241
238
  By 'outbound' we mean messages using Haraka's built-in queue and delivery
242
- mechanism. The Outbound queue is used when `connection.relaying = true` is set during the transaction and `hook_queue_outbound` is called to queue the message.
239
+ mechanism. The Outbound queue is used when `connection.relaying = true` is set during the transaction and `hook_queue_outbound` is called to queue the message.
243
240
 
244
241
  The Outbound hook ordering mirrors the Inbound hook order above until after `hook_queue_outbound`, which is followed by:
245
242
 
246
243
  - hook_send_email
247
244
  - hook_get_mx
248
245
  - at least one of:
249
- - hook_delivered (once per delivery domain with at least one successful recipient)
250
- - hook_deferred (once per delivery domain where at least one recipient or connection was deferred)
251
- - hook_bounce (once per delivery domain where the recipient(s) or message was rejected by the destination)
246
+ - hook_delivered (once per delivery domain with at least one successful recipient)
247
+ - hook_deferred (once per delivery domain where at least one recipient or connection was deferred)
248
+ - hook_bounce (once per delivery domain where the recipient(s) or message was rejected by the destination)
252
249
 
253
250
  ## Plugin Run Order
254
251
 
@@ -256,11 +253,11 @@ Plugins are run on each hook in the order that they are specified in `config/plu
256
253
 
257
254
  This is important as some plugins might rely on `results` or `notes` that have been set by plugins that need to run before them. This should be noted in the plugins documentation. Make sure to read it.
258
255
 
259
- If you are writing a complex plugin, you may have to split it into multiple plugins to run in a specific order e.g. you want hook_deny to run last after all other plugins and hook_lookup_rdns to run first, then you can explicitly register your hooks and provide a `priority` value which is an integer between -100 (highest priority) to 100 (lowest priority) which defaults to 0 (zero) if not supplied. You can apply a priority to your hook in the following way:
256
+ If you are writing a complex plugin, you may have to split it into multiple plugins to run in a specific order e.g. you want hook_deny to run last after all other plugins and hook_lookup_rdns to run first, then you can explicitly register your hooks and provide a `priority` value which is an integer between -100 (highest priority) to 100 (lowest priority) which defaults to 0 (zero) if not supplied. You can apply a priority to your hook in the following way:
260
257
 
261
258
  ```js
262
259
  exports.register = function () {
263
- this.register_hook('connect', 'do_connect_stuff', -100);
260
+ this.register_hook('connect', 'do_connect_stuff', -100)
264
261
  }
265
262
  ```
266
263
 
@@ -274,21 +271,21 @@ Check the order that the plugins will run on each hook by running:
274
271
 
275
272
  ## Skipping Plugins
276
273
 
277
- Plugins can be skipped at runtime by pushing the name of the plugin into the `skip_plugins` array in `transaction.notes`. This array is reset for every transaction and once a plugin is added to the list, it will not run any hooks in that plugin for the remainder of the transaction. For example, one could create a whitelist plugin that skipped `spamassassin` if the sender was in a whitelist.
274
+ Plugins can be skipped at runtime by pushing the name of the plugin into the `skip_plugins` array in `transaction.notes`. This array is reset for every transaction and once a plugin is added to the list, it will not run any hooks in that plugin for the remainder of the transaction. For example, one could create a whitelist plugin that skipped `spamassassin` if the sender was in a whitelist.
278
275
 
279
276
  ## Logging
280
277
 
281
278
  Plugins inherit all the logging methods of `logger.js`, which are:
282
279
 
283
- * logprotocol
284
- * logdebug
285
- * loginfo
286
- * lognotice
287
- * logwarn
288
- * logerror
289
- * logcrit
290
- * logalert
291
- * logemerg
280
+ - logprotocol
281
+ - logdebug
282
+ - loginfo
283
+ - lognotice
284
+ - logwarn
285
+ - logerror
286
+ - logcrit
287
+ - logalert
288
+ - logemerg
292
289
 
293
290
  If plugins throw an exception when in a hook, the exception will be caught
294
291
  and generate a logcrit level error. However, exceptions will not be caught
@@ -298,16 +295,16 @@ log the error, and run your next() function appropriately.
298
295
  ## Sharing State
299
296
 
300
297
  There are several cases where you might need to share information between
301
- plugins. This is done using `notes` - there are three types available:
298
+ plugins. This is done using `notes` - there are three types available:
302
299
 
303
- * server.notes
300
+ - server.notes
304
301
 
305
- Available in all plugins. This is created at PID start-up and is shared
302
+ Available in all plugins. This is created at PID start-up and is shared
306
303
  amongst all plugins on the same PID and listener.
307
304
  Typical uses for notes at this level would be to share database
308
305
  connections between multiple plugins or connection pools etc.
309
306
 
310
- * connection.notes
307
+ - connection.notes
311
308
 
312
309
  Available on any hook that passes 'connection' as a function parameter.
313
310
  This is shared amongst all plugins for a single connection and is
@@ -316,17 +313,17 @@ plugins. This is done using `notes` - there are three types available:
316
313
  about the connected client e.g. rDNS names, HELO/EHLO, white/black
317
314
  list status etc.
318
315
 
319
- * connection.transaction.notes
316
+ - connection.transaction.notes
320
317
 
321
318
  Available on any hook that passes 'connection' as a function parameter
322
- between hook\_mail and hook\_data\_post.
319
+ between hook_mail and hook_data_post.
323
320
  This is shared amongst all plugins for this transaction (e.g. MAIL FROM
324
321
  through until a message is received or the connection is reset).
325
322
  Typical uses for notes at this level would be to store information
326
323
  on things like greylisting which uses client, sender and recipient
327
324
  information etc.
328
325
 
329
- * hmail.todo.notes
326
+ - hmail.todo.notes
330
327
 
331
328
  Available on any outbound hook that passes `hmail` as a function parameter.
332
329
  This is the same object as 'connection.transaction.notes', so anything
@@ -377,7 +374,7 @@ e.g.
377
374
 
378
375
  ```js
379
376
  exports.shutdown = function () {
380
- clearInterval(this._interval);
377
+ clearInterval(this._interval)
381
378
  }
382
379
  ```
383
380
 
@@ -389,9 +386,7 @@ Note: This only applies when running with a `nodes=...` value in smtp.ini.
389
386
 
390
387
  ## See also, [Results](Results.md)
391
388
 
392
-
393
- Further Reading
394
- --------------
389
+ ## Further Reading
395
390
 
396
391
  Read about the [Connection](Connection.md) object.
397
392
 
@@ -4,19 +4,19 @@ An SMTP transaction is valid from MAIL FROM time until RSET or "final-dot".
4
4
 
5
5
  ## API
6
6
 
7
- * transaction.uuid
7
+ - transaction.uuid
8
8
 
9
9
  A unique UUID for this transaction. Is equal to the connection.uuid + '.N' where N increments for each transaction on this connection.
10
10
 
11
- * transaction.mail\_from
11
+ - transaction.mail_from
12
12
 
13
13
  The value of the MAIL FROM command is an `Address`[1] object.
14
14
 
15
- * transaction.rcpt\_to
15
+ - transaction.rcpt_to
16
16
 
17
17
  An Array of `Address`[1] objects of recipients from the RCPT TO command.
18
18
 
19
- * transaction.message\_stream
19
+ - transaction.message_stream
20
20
 
21
21
  A node.js Readable Stream object for the message.
22
22
 
@@ -31,7 +31,7 @@ Where WritableStream is a node.js Writable Stream object such as a net.socket, f
31
31
  The options argument should be an object that overrides the following properties:
32
32
 
33
33
  * line_endings (default: "\r\n")
34
- * dot_stuffing (default: false)
34
+ * dot_stuffed (default: true)
35
35
  * ending_dot (default: false)
36
36
  * end (default: true)
37
37
  * buffer_size (default: 65535)
@@ -40,46 +40,46 @@ The options argument should be an object that overrides the following properties
40
40
  e.g.
41
41
 
42
42
  ```js
43
- transaction.message_stream.pipe(socket, { dot_stuffing: true, ending_dot: true });
43
+ transaction.message_stream.pipe(socket, { ending_dot: true })
44
44
  ```
45
45
 
46
- * transaction.data\_bytes
46
+ - transaction.data_bytes
47
47
 
48
48
  The number of bytes in the email after DATA.
49
49
 
50
- * transaction.add\_data(line)
50
+ - transaction.add_data(line)
51
51
 
52
52
  Adds a line of data to the email. Note this is RAW email - it isn't useful for adding banners to the email.
53
53
 
54
- * transaction.notes
54
+ - transaction.notes
55
55
 
56
56
  A safe place to store transaction specific values. See also [haraka-results](https://github.com/haraka/haraka-results) and [haraka-notes](https://github.com/haraka/haraka-notes).
57
57
 
58
- * transaction.add\_leading\_header(key, value)
58
+ - transaction.add_leading_header(key, value)
59
59
 
60
- Adds a header to the top of the header list. This should only be used in very specific cases. Most cases will use `add_header()` instead.
60
+ Adds a header to the top of the header list. This should only be used in very specific cases. Most cases will use `add_header()` instead.
61
61
 
62
- * transaction.add\_header(key, value)
62
+ - transaction.add_header(key, value)
63
63
 
64
64
  Adds a header to the email.
65
65
 
66
- * transaction.remove\_header(key)
66
+ - transaction.remove_header(key)
67
67
 
68
68
  Deletes a header from the email.
69
69
 
70
- * transaction.header
70
+ - transaction.header
71
71
 
72
72
  The header of the email. See `Header Object`.
73
73
 
74
- * transaction.parse\_body = true|false [default: false]
74
+ - transaction.parse_body = true|false [default: false]
75
75
 
76
- Set to `true` to enable parsing of the mail body. Make sure you set this in hook\_data or before. Storing a transaction hook (with transaction.attachment\_hooks) will set this to true.
76
+ Set to `true` to enable parsing of the mail body. Make sure you set this in hook_data or before. Storing a transaction hook (with transaction.attachment_hooks) will set this to true.
77
77
 
78
- * transaction.body
78
+ - transaction.body
79
79
 
80
80
  The body of the email if you set `parse_body` above. See `Body Object`.
81
81
 
82
- * transaction.attachment\_hooks(start)
82
+ - transaction.attachment_hooks(start)
83
83
 
84
84
  Sets a callback for when we see an attachment.
85
85
 
@@ -91,51 +91,49 @@ If you set stream.connection then the stream will apply backpressure to the conn
91
91
 
92
92
  ```js
93
93
  exports.hook_data = function (next, connection) {
94
- // enable mail body parsing
95
- connection.transaction.attachment_hooks(
96
- function (ct, fn, body, stream) {
97
- start_att(connection, ct, fn, body, stream)
98
- }
99
- );
100
- next();
94
+ // enable mail body parsing
95
+ connection.transaction.attachment_hooks(function (ct, fn, body, stream) {
96
+ start_att(connection, ct, fn, body, stream)
97
+ })
98
+ next()
101
99
  }
102
100
 
103
- function start_att (connection, ct, fn, body, stream) {
104
- connection.loginfo(`Got attachment: ${ct}, ${fn} for user id: ${connection.transaction.notes.hubdoc_user.email}`)
105
- connection.transaction.notes.attachment_count++
106
-
107
- stream.connection = connection; // Allow backpressure
108
- stream.pause();
109
-
110
- require('tmp').file((err, path, fd) => {
111
- connection.loginfo(`Got tempfile: ${path} (${fd})`)
112
- const ws = fs.createWriteStream(path)
113
- stream.pipe(ws);
114
- stream.resume();
115
- ws.on('close', () => {
116
- connection.loginfo("End of stream reached");
117
- fs.fstat(fd, (err, stats) => {
118
- connection.loginfo(`Got data of length: ${stats.size}`);
119
- fs.close(fd, () => {}); // Close the tmp file descriptor
120
- });
121
- });
122
- });
101
+ function start_att(connection, ct, fn, body, stream) {
102
+ connection.loginfo(`Got attachment: ${ct}, ${fn} for user id: ${connection.transaction.notes.hubdoc_user.email}`)
103
+ connection.transaction.notes.attachment_count++
104
+
105
+ stream.connection = connection // Allow backpressure
106
+ stream.pause()
107
+
108
+ require('tmp').file((err, path, fd) => {
109
+ connection.loginfo(`Got tempfile: ${path} (${fd})`)
110
+ const ws = fs.createWriteStream(path)
111
+ stream.pipe(ws)
112
+ stream.resume()
113
+ ws.on('close', () => {
114
+ connection.loginfo('End of stream reached')
115
+ fs.fstat(fd, (err, stats) => {
116
+ connection.loginfo(`Got data of length: ${stats.size}`)
117
+ fs.close(fd, () => {}) // Close the tmp file descriptor
118
+ })
119
+ })
120
+ })
123
121
  }
124
122
  ```
125
123
 
126
- * transaction.discard\_data = true|false [default: false]
124
+ - transaction.discard_data = true|false [default: false]
127
125
 
128
- Set this flag to true to discard all data as it arrives and not store in memory or on disk (in the message\_stream property). You can still access the attachments and body if you set parse\_body to true. This is useful for systems which do not need the full email, just the attachments or mail text.
126
+ Set this flag to true to discard all data as it arrives and not store in memory or on disk (in the message_stream property). You can still access the attachments and body if you set parse_body to true. This is useful for systems which do not need the full email, just the attachments or mail text.
129
127
 
130
- * transaction.set\_banner(text, html)
128
+ - transaction.set_banner(text, html)
131
129
 
132
130
  Sets a banner to be added to the end of the email. If the html part is not given (optional) then the text part will have each line ending replaced with `<br/>` when being inserted into HTML parts.
133
131
 
134
- * transaction.add\_body\_filter(ct_match, filter)
132
+ - transaction.add_body_filter(ct_match, filter)
135
133
 
136
- Adds a filter to be applied to body parts in the email. ct\_match should be a regular expression to match against the full content-type line, or a string to match at the start, e.g. `/^text\/html/` or `'text/plain'`. filter will be called when each body part matching ct_match is complete. It receives three parameters: the content-type line, the encoding name, and a buffer with the full body part. It should return a buffer with the desired contents of the body in the same encoding.
134
+ Adds a filter to be applied to body parts in the email. ct_match should be a regular expression to match against the full content-type line, or a string to match at the start, e.g. `/^text\/html/` or `'text/plain'`. filter will be called when each body part matching ct_match is complete. It receives three parameters: the content-type line, the encoding name, and a buffer with the full body part. It should return a buffer with the desired contents of the body in the same encoding.
137
135
 
138
- * transaction.results
136
+ - transaction.results
139
137
 
140
138
  Store [results](https://github.com/haraka/haraka-results) of processing in a structured format.
141
139