Haraka 3.1.6 → 3.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/CONTRIBUTORS.md +8 -8
  3. package/Plugins.md +99 -99
  4. package/config/smtp_forward.ini +10 -0
  5. package/config/smtp_proxy.ini +10 -0
  6. package/connection.js +25 -8
  7. package/docs/plugins/queue/smtp_forward.md +19 -3
  8. package/docs/plugins/queue/smtp_proxy.md +10 -2
  9. package/haraka.js +1 -1
  10. package/outbound/hmail.js +39 -39
  11. package/outbound/index.js +4 -4
  12. package/outbound/tls.js +2 -43
  13. package/package.json +49 -48
  14. package/plugins/auth/auth_base.js +9 -3
  15. package/plugins/auth/auth_proxy.js +14 -11
  16. package/plugins/block_me.js +4 -2
  17. package/plugins/prevent_credential_leaks.js +3 -1
  18. package/plugins/process_title.js +6 -6
  19. package/plugins/queue/qmail-queue.js +15 -19
  20. package/plugins/queue/smtp_forward.js +12 -4
  21. package/plugins/queue/smtp_proxy.js +14 -3
  22. package/plugins/tls.js +13 -5
  23. package/plugins/xclient.js +3 -1
  24. package/server.js +5 -3
  25. package/smtp_client.js +20 -11
  26. package/test/config/block_me.recipient +1 -0
  27. package/test/config/block_me.senders +1 -0
  28. package/test/connection.js +24 -0
  29. package/test/outbound/bounce_net_errors.js +3 -2
  30. package/test/plugins/auth/auth_bridge.js +80 -0
  31. package/test/plugins/auth/flat_file.js +128 -0
  32. package/test/plugins/block_me.js +157 -0
  33. package/test/plugins/data.signatures.js +114 -0
  34. package/test/plugins/delay_deny.js +263 -0
  35. package/test/plugins/prevent_credential_leaks.js +178 -0
  36. package/test/plugins/process_title.js +135 -0
  37. package/test/plugins/queue/deliver.js +99 -0
  38. package/test/plugins/queue/discard.js +79 -0
  39. package/test/plugins/queue/lmtp.js +138 -0
  40. package/test/plugins/queue/qmail-queue.js +99 -0
  41. package/test/plugins/queue/quarantine.js +81 -0
  42. package/test/plugins/queue/smtp_bridge.js +154 -0
  43. package/test/plugins/queue/smtp_forward.js +42 -6
  44. package/test/plugins/queue/smtp_proxy.js +139 -0
  45. package/test/plugins/reseed_rng.js +34 -0
  46. package/test/plugins/tarpit.js +91 -0
  47. package/test/plugins/tls.js +25 -0
  48. package/test/plugins/toobusy.js +21 -0
  49. package/test/plugins/xclient.js +14 -0
  50. package/test/server.js +59 -0
  51. package/test/smtp_client.js +45 -12
  52. package/test/tls_socket.js +82 -0
  53. package/tls_socket.js +50 -0
package/CHANGELOG.md CHANGED
@@ -4,6 +4,36 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/).
4
4
 
5
5
  ### Unreleased
6
6
 
7
+ ### [3.1.7] - 2026-05-19
8
+
9
+ - feat(smtp_forward,smtp_proxy): honor `tls.ini` `[main]` and plugin `[tls]`
10
+ section for backend STARTTLS (matches docs). Behavior change: installs
11
+ that set `[main] rejectUnauthorized=true` in `tls.ini` will now see it applied
12
+ to the forward/proxy paths. Untouched installs match the previous behavior.
13
+ - fix(auth_proxy): try opportunistic STARTTLS w/o a key/cert, #matchTheDocs
14
+ - feat(tls_socket): new `load_plugin_tls_options(plugin_tls_cfg)` helper that
15
+ merges a plugin's `[tls]` section over `tls.ini` `[main]` for client STARTTLS
16
+ - refactor: `outbound/tls.js#load_config()` delegates to `load_plugin_tls_options()`
17
+ - change: update DSN.addr_bad_dest_system(...) to DSN.addr_null_mx(...)
18
+ - fix(tls): buffer discard on STARTTLS (RFC 3207 §4)
19
+ - fix(server): run the graceful restart/shutdown work queue
20
+ - fix(xclient): parse DESTPORT to int so the 587/465 auth check applies
21
+ - fix(smtp_client):
22
+ - no_tls_hosts works correctly by referencing the correct path
23
+ - unsupported AUTH no longer throws out of the event loop
24
+ - fix(smtputf8): all code paths use it, no more smtp_utf8
25
+ - fix(conn): reject control chars in HELO name (RFC 5321 §4.1.1.1)
26
+ - fix: sanitize AUTH usernames before storing
27
+ - fix: strip CR/LF from all strings passed into `auth_results()`
28
+ - fix(smtp_client,auth_proxy): redact AUTH credentials in protocol logs
29
+ - fix(prevent_credential_leaks): properly handle usernames w/o an `@`
30
+ - fix(queue/qmail-queue): size envelope dynamically; UTF-8 safe
31
+ - deps(some): bump patch versions to latest
32
+ - change: replace forEach with es6 style for...of #3569
33
+ - tests: add a few #3568
34
+ - doc(Plugins): add publish year to each plugin #3567
35
+ - deps(all): switch from ^ to ~ version ranges #3565
36
+
7
37
  ### [3.1.6] - 2026-05-15
8
38
 
9
39
  - fix(outbound): release queue slot when qfile unreadable #3561
@@ -131,7 +161,7 @@ AND
131
161
 
132
162
  - moves the following settings from smtp.ini to connection.ini:
133
163
  - headers.\*
134
- - main.smtp_utf8
164
+ - main.smtputf8
135
165
  - main.strict_rfc1869
136
166
  - early_talker.pause, removed support, use earlytalker.ini
137
167
 
@@ -1831,3 +1861,4 @@ config files.
1831
1861
  [3.1.4]: https://github.com/haraka/Haraka/releases/tag/v3.1.4
1832
1862
  [3.1.5]: https://github.com/haraka/Haraka/releases/tag/v3.1.5
1833
1863
  [3.1.6]: https://github.com/haraka/Haraka/releases/tag/v3.1.6
1864
+ [3.1.7]: https://github.com/haraka/Haraka/releases/tag/v3.1.7
package/CONTRIBUTORS.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  This handcrafted artisanal software is brought to you by:
4
4
 
5
- | <img height="80" src="https://avatars.githubusercontent.com/u/261635?v=4"><br><a href="https://github.com/msimerson">msimerson</a> (<a href="https://github.com/haraka/Haraka/commits?author=msimerson">1672</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/662371?v=4"><br><a href="https://github.com/baudehlo">baudehlo</a> (<a href="https://github.com/haraka/Haraka/commits?author=baudehlo">969</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/550490?v=4"><br><a href="https://github.com/smfreegard">smfreegard</a> (<a href="https://github.com/haraka/Haraka/commits?author=smfreegard">794</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/959600?v=4"><br><a href="https://github.com/godsflaw">godsflaw</a> (<a href="https://github.com/haraka/Haraka/commits?author=godsflaw">171</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/934254?v=4"><br><a href="https://github.com/analogic">analogic</a> (<a href="https://github.com/haraka/Haraka/commits?author=analogic">42</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1674289?v=4"><br><a href="https://github.com/Dexus">Dexus</a> (<a href="https://github.com/haraka/Haraka/commits?author=Dexus">42</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/82041?v=4"><br><a href="https://github.com/gramakri">gramakri</a> (<a href="https://github.com/haraka/Haraka/commits?author=gramakri">40</a>) |
5
+ | <img height="80" src="https://avatars.githubusercontent.com/u/261635?v=4"><br><a href="https://github.com/msimerson">msimerson</a> (<a href="https://github.com/haraka/Haraka/commits?author=msimerson">1682</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/662371?v=4"><br><a href="https://github.com/baudehlo">baudehlo</a> (<a href="https://github.com/haraka/Haraka/commits?author=baudehlo">969</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/550490?v=4"><br><a href="https://github.com/smfreegard">smfreegard</a> (<a href="https://github.com/haraka/Haraka/commits?author=smfreegard">794</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/959600?v=4"><br><a href="https://github.com/godsflaw">godsflaw</a> (<a href="https://github.com/haraka/Haraka/commits?author=godsflaw">171</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/934254?v=4"><br><a href="https://github.com/analogic">analogic</a> (<a href="https://github.com/haraka/Haraka/commits?author=analogic">42</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1674289?v=4"><br><a href="https://github.com/Dexus">Dexus</a> (<a href="https://github.com/haraka/Haraka/commits?author=Dexus">42</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/82041?v=4"><br><a href="https://github.com/gramakri">gramakri</a> (<a href="https://github.com/haraka/Haraka/commits?author=gramakri">40</a>) |
6
6
  | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
7
7
  | <img height="80" src="https://avatars.githubusercontent.com/u/203240?v=4"><br><a href="https://github.com/lnedry">lnedry</a> (<a href="https://github.com/haraka/Haraka/commits?author=lnedry">27</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/748075?v=4"><br><a href="https://github.com/celesteking">celesteking</a> (<a href="https://github.com/haraka/Haraka/commits?author=celesteking">21</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/791972?v=4"><br><a href="https://github.com/lpatters">lpatters</a> (<a href="https://github.com/haraka/Haraka/commits?author=lpatters">20</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/366268?v=4"><br><a href="https://github.com/chazomaticus">chazomaticus</a> (<a href="https://github.com/haraka/Haraka/commits?author=chazomaticus">19</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/123708?v=4"><br><a href="https://github.com/arlolra">arlolra</a> (<a href="https://github.com/haraka/Haraka/commits?author=arlolra">16</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/271024?v=4"><br><a href="https://github.com/hayesgm">hayesgm</a> (<a href="https://github.com/haraka/Haraka/commits?author=hayesgm">16</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1573133?v=4"><br><a href="https://github.com/gauravaror">gauravaror</a> (<a href="https://github.com/haraka/Haraka/commits?author=gauravaror">14</a>) |
8
8
  | <img height="80" src="https://avatars.githubusercontent.com/u/260607?v=4"><br><a href="https://github.com/typingArtist">typingArtist</a> (<a href="https://github.com/haraka/Haraka/commits?author=typingArtist">14</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/11343494?v=4"><br><a href="https://github.com/superman20">superman20</a> (<a href="https://github.com/haraka/Haraka/commits?author=superman20">13</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/158380?v=4"><br><a href="https://github.com/darkpixel">darkpixel</a> (<a href="https://github.com/haraka/Haraka/commits?author=darkpixel">12</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/9887966?v=4"><br><a href="https://github.com/KingNoosh">KingNoosh</a> (<a href="https://github.com/haraka/Haraka/commits?author=KingNoosh">11</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/5229495?v=4"><br><a href="https://github.com/tstonis">tstonis</a> (<a href="https://github.com/haraka/Haraka/commits?author=tstonis">10</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1746394?v=4"><br><a href="https://github.com/wltsmrz">wltsmrz</a> (<a href="https://github.com/haraka/Haraka/commits?author=wltsmrz">9</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/218741413?v=4"><br><a href="https://github.com/SamuelGrave">SamuelGrave</a> (<a href="https://github.com/haraka/Haraka/commits?author=SamuelGrave">9</a>) |
@@ -22,13 +22,13 @@ This handcrafted artisanal software is brought to you by:
22
22
  | <img height="80" src="https://avatars.githubusercontent.com/u/320906?v=4"><br><a href="https://github.com/martinvd">martinvd</a> (<a href="https://github.com/haraka/Haraka/commits?author=martinvd">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/217669830?v=4"><br><a href="https://github.com/lmacayo">lmacayo</a> (<a href="https://github.com/haraka/Haraka/commits?author=lmacayo">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/181014?v=4"><br><a href="https://github.com/k2s">k2s</a> (<a href="https://github.com/haraka/Haraka/commits?author=k2s">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/650890?v=4"><br><a href="https://github.com/zombified">zombified</a> (<a href="https://github.com/haraka/Haraka/commits?author=zombified">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1024137?v=4"><br><a href="https://github.com/dhager7">dhager7</a> (<a href="https://github.com/haraka/Haraka/commits?author=dhager7">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/274063935?v=4"><br><a href="https://github.com/cmooneycl">cmooneycl</a> (<a href="https://github.com/haraka/Haraka/commits?author=cmooneycl">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/25018388?v=4"><br><a href="https://github.com/ayankel">ayankel</a> (<a href="https://github.com/haraka/Haraka/commits?author=ayankel">1</a>) |
23
23
  | <img height="80" src="https://avatars.githubusercontent.com/u/3277165?v=4"><br><a href="https://github.com/X-Ryl669">X-Ryl669</a> (<a href="https://github.com/haraka/Haraka/commits?author=X-Ryl669">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/952007?v=4"><br><a href="https://github.com/szepeviktor">szepeviktor</a> (<a href="https://github.com/haraka/Haraka/commits?author=szepeviktor">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/20950126?v=4"><br><a href="https://github.com/varunzxzx">varunzxzx</a> (<a href="https://github.com/haraka/Haraka/commits?author=varunzxzx">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/95691?v=4"><br><a href="https://github.com/noogen">noogen</a> (<a href="https://github.com/haraka/Haraka/commits?author=noogen">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/209270?v=4"><br><a href="https://github.com/TimWolla">TimWolla</a> (<a href="https://github.com/haraka/Haraka/commits?author=TimWolla">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/29933243?v=4"><br><a href="https://github.com/tiagorlampert">tiagorlampert</a> (<a href="https://github.com/haraka/Haraka/commits?author=tiagorlampert">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/912257?v=4"><br><a href="https://github.com/tomscytale">tomscytale</a> (<a href="https://github.com/haraka/Haraka/commits?author=tomscytale">1</a>) |
24
24
  | <img height="80" src="https://avatars.githubusercontent.com/u/5239282?v=4"><br><a href="https://github.com/sriccio">sriccio</a> (<a href="https://github.com/haraka/Haraka/commits?author=sriccio">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/44905?v=4"><br><a href="https://github.com/fcoelho">fcoelho</a> (<a href="https://github.com/haraka/Haraka/commits?author=fcoelho">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/8796466?v=4"><br><a href="https://github.com/erickpece">erickpece</a> (<a href="https://github.com/haraka/Haraka/commits?author=erickpece">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/354409?v=4"><br><a href="https://github.com/endreszabo">endreszabo</a> (<a href="https://github.com/haraka/Haraka/commits?author=endreszabo">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/548763?v=4"><br><a href="https://github.com/duanefields">duanefields</a> (<a href="https://github.com/haraka/Haraka/commits?author=duanefields">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/6936055?v=4"><br><a href="https://github.com/DomAmato">DomAmato</a> (<a href="https://github.com/haraka/Haraka/commits?author=DomAmato">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/26029735?v=4"><br><a href="https://github.com/lavieennoir">lavieennoir</a> (<a href="https://github.com/haraka/Haraka/commits?author=lavieennoir">1</a>) |
25
- | <img height="80" src="https://avatars.githubusercontent.com/u/166466?v=4"><br><a href="https://github.com/dspangenberg">dspangenberg</a> (<a href="https://github.com/haraka/Haraka/commits?author=dspangenberg">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/100674?v=4"><br><a href="https://github.com/d--j">d--j</a> (<a href="https://github.com/haraka/Haraka/commits?author=d--j">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/81616?v=4"><br><a href="https://github.com/damoxc">damoxc</a> (<a href="https://github.com/haraka/Haraka/commits?author=damoxc">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/in/1143301?v=4"><br><a href="https://github.com/apps/copilot-swe-agent">Copilot</a> (<a href="https://github.com/haraka/Haraka/commits?author=Copilot">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/37262317?v=4"><br><a href="https://github.com/dkmaker">dkmaker</a> (<a href="https://github.com/haraka/Haraka/commits?author=dkmaker">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/805639?v=4"><br><a href="https://github.com/cbestall">cbestall</a> (<a href="https://github.com/haraka/Haraka/commits?author=cbestall">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/962436?v=4"><br><a href="https://github.com/txase">txase</a> (<a href="https://github.com/haraka/Haraka/commits?author=txase">1</a>) |
26
- | <img height="80" src="https://avatars.githubusercontent.com/u/1430118?v=4"><br><a href="https://github.com/thetrompf">thetrompf</a> (<a href="https://github.com/haraka/Haraka/commits?author=thetrompf">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/623363?v=4"><br><a href="https://github.com/bmatson">bmatson</a> (<a href="https://github.com/haraka/Haraka/commits?author=bmatson">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/47733?v=4"><br><a href="https://github.com/ardiesaeidi">ardiesaeidi</a> (<a href="https://github.com/haraka/Haraka/commits?author=ardiesaeidi">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/47601131?v=4"><br><a href="https://github.com/AprilGrimoire">AprilGrimoire</a> (<a href="https://github.com/haraka/Haraka/commits?author=AprilGrimoire">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/14093131?v=4"><br><a href="https://github.com/andbar">andbar</a> (<a href="https://github.com/haraka/Haraka/commits?author=andbar">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/2813838?v=4"><br><a href="https://github.com/amirkarimi">amirkarimi</a> (<a href="https://github.com/haraka/Haraka/commits?author=amirkarimi">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/332898?v=4"><br><a href="https://github.com/alessioalex">alessioalex</a> (<a href="https://github.com/haraka/Haraka/commits?author=alessioalex">1</a>) |
27
- | <img height="80" src="https://avatars.githubusercontent.com/u/124756761?v=4"><br><a href="https://github.com/littleslicebigcity">littleslicebigcity</a> (<a href="https://github.com/haraka/Haraka/commits?author=littleslicebigcity">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1177304?v=4"><br><a href="https://github.com/mildsunrise">mildsunrise</a> (<a href="https://github.com/haraka/Haraka/commits?author=mildsunrise">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/30565?v=4"><br><a href="https://github.com/ajimix">ajimix</a> (<a href="https://github.com/haraka/Haraka/commits?author=ajimix">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/58205701?v=4"><br><a href="https://github.com/adarshasp87">adarshasp87</a> (<a href="https://github.com/haraka/Haraka/commits?author=adarshasp87">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/284925?v=4"><br><a href="https://github.com/64kps">64kps</a> (<a href="https://github.com/haraka/Haraka/commits?author=64kps">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/803496?v=4"><br><a href="https://github.com/mskrajnowski">mskrajnowski</a> (<a href="https://github.com/haraka/Haraka/commits?author=mskrajnowski">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/18592942?v=4"><br><a href="https://github.com/mnsilva">mnsilva</a> (<a href="https://github.com/haraka/Haraka/commits?author=mnsilva">1</a>) |
28
- | <img height="80" src="https://avatars.githubusercontent.com/u/6890321?v=4"><br><a href="https://github.com/httpstersk">httpstersk</a> (<a href="https://github.com/haraka/Haraka/commits?author=httpstersk">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/28440072?v=4"><br><a href="https://github.com/leadbi">leadbi</a> (<a href="https://github.com/haraka/Haraka/commits?author=leadbi">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/22004482?v=4"><br><a href="https://github.com/kajes">kajes</a> (<a href="https://github.com/haraka/Haraka/commits?author=kajes">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/51789698?v=4"><br><a href="https://github.com/Young-Lord">Young-Lord</a> (<a href="https://github.com/haraka/Haraka/commits?author=Young-Lord">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/11235022?v=4"><br><a href="https://github.com/kzub">kzub</a> (<a href="https://github.com/haraka/Haraka/commits?author=kzub">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/510957?v=4"><br><a href="https://github.com/kevinmartin">kevinmartin</a> (<a href="https://github.com/haraka/Haraka/commits?author=kevinmartin">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/75720?v=4"><br><a href="https://github.com/kgoess">kgoess</a> (<a href="https://github.com/haraka/Haraka/commits?author=kgoess">1</a>) |
29
- | <img height="80" src="https://avatars.githubusercontent.com/u/5689132?v=4"><br><a href="https://github.com/mr-karan">mr-karan</a> (<a href="https://github.com/haraka/Haraka/commits?author=mr-karan">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/7114909?v=4"><br><a href="https://github.com/tyranron">tyranron</a> (<a href="https://github.com/haraka/Haraka/commits?author=tyranron">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/49093?v=4"><br><a href="https://github.com/jplock">jplock</a> (<a href="https://github.com/haraka/Haraka/commits?author=jplock">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/411338?v=4"><br><a href="https://github.com/josteink">josteink</a> (<a href="https://github.com/haraka/Haraka/commits?author=josteink">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/646768?v=4"><br><a href="https://github.com/nebulade">nebulade</a> (<a href="https://github.com/haraka/Haraka/commits?author=nebulade">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/6860647?v=4"><br><a href="https://github.com/GuroKung">GuroKung</a> (<a href="https://github.com/haraka/Haraka/commits?author=GuroKung">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/2649838?v=4"><br><a href="https://github.com/stanek0j">stanek0j</a> (<a href="https://github.com/haraka/Haraka/commits?author=stanek0j">1</a>) |
30
- | <img height="80" src="https://avatars.githubusercontent.com/u/55651?v=4"><br><a href="https://github.com/jaredj">jaredj</a> (<a href="https://github.com/haraka/Haraka/commits?author=jaredj">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/397735?v=4"><br><a href="https://github.com/jrb">jrb</a> (<a href="https://github.com/haraka/Haraka/commits?author=jrb">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1560587?v=4"><br><a href="https://github.com/jkroepke">jkroepke</a> (<a href="https://github.com/haraka/Haraka/commits?author=jkroepke">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/5376280?v=4"><br><a href="https://github.com/Chopinsky">Chopinsky</a> (<a href="https://github.com/haraka/Haraka/commits?author=Chopinsky">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/195918?v=4"><br><a href="https://github.com/hperrin">hperrin</a> (<a href="https://github.com/haraka/Haraka/commits?author=hperrin">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/376721?v=4"><br><a href="https://github.com/urlund">urlund</a> (<a href="https://github.com/haraka/Haraka/commits?author=urlund">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/7700727?v=4"><br><a href="https://github.com/gwieshammer">gwieshammer</a> (<a href="https://github.com/haraka/Haraka/commits?author=gwieshammer">1</a>) |
31
- | <img height="80" src="https://avatars.githubusercontent.com/u/914107?v=4"><br><a href="https://github.com/gpetrioli">gpetrioli</a> (<a href="https://github.com/haraka/Haraka/commits?author=gpetrioli">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/140875?v=4"><br><a href="https://github.com/fabiob">fabiob</a> (<a href="https://github.com/haraka/Haraka/commits?author=fabiob">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/400795?v=4"><br><a href="https://github.com/felixrabe">felixrabe</a> (<a href="https://github.com/haraka/Haraka/commits?author=felixrabe">1</a>) | | | | |
25
+ | <img height="80" src="https://avatars.githubusercontent.com/u/166466?v=4"><br><a href="https://github.com/dspangenberg">dspangenberg</a> (<a href="https://github.com/haraka/Haraka/commits?author=dspangenberg">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/100674?v=4"><br><a href="https://github.com/d--j">d--j</a> (<a href="https://github.com/haraka/Haraka/commits?author=d--j">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/81616?v=4"><br><a href="https://github.com/damoxc">damoxc</a> (<a href="https://github.com/haraka/Haraka/commits?author=damoxc">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/37262317?v=4"><br><a href="https://github.com/dkmaker">dkmaker</a> (<a href="https://github.com/haraka/Haraka/commits?author=dkmaker">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/805639?v=4"><br><a href="https://github.com/cbestall">cbestall</a> (<a href="https://github.com/haraka/Haraka/commits?author=cbestall">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/962436?v=4"><br><a href="https://github.com/txase">txase</a> (<a href="https://github.com/haraka/Haraka/commits?author=txase">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1430118?v=4"><br><a href="https://github.com/thetrompf">thetrompf</a> (<a href="https://github.com/haraka/Haraka/commits?author=thetrompf">1</a>) |
26
+ | <img height="80" src="https://avatars.githubusercontent.com/u/623363?v=4"><br><a href="https://github.com/bmatson">bmatson</a> (<a href="https://github.com/haraka/Haraka/commits?author=bmatson">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/47733?v=4"><br><a href="https://github.com/ardiesaeidi">ardiesaeidi</a> (<a href="https://github.com/haraka/Haraka/commits?author=ardiesaeidi">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/47601131?v=4"><br><a href="https://github.com/AprilGrimoire">AprilGrimoire</a> (<a href="https://github.com/haraka/Haraka/commits?author=AprilGrimoire">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/14093131?v=4"><br><a href="https://github.com/andbar">andbar</a> (<a href="https://github.com/haraka/Haraka/commits?author=andbar">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/2813838?v=4"><br><a href="https://github.com/amirkarimi">amirkarimi</a> (<a href="https://github.com/haraka/Haraka/commits?author=amirkarimi">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/332898?v=4"><br><a href="https://github.com/alessioalex">alessioalex</a> (<a href="https://github.com/haraka/Haraka/commits?author=alessioalex">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/124756761?v=4"><br><a href="https://github.com/littleslicebigcity">littleslicebigcity</a> (<a href="https://github.com/haraka/Haraka/commits?author=littleslicebigcity">1</a>) |
27
+ | <img height="80" src="https://avatars.githubusercontent.com/u/1177304?v=4"><br><a href="https://github.com/mildsunrise">mildsunrise</a> (<a href="https://github.com/haraka/Haraka/commits?author=mildsunrise">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/30565?v=4"><br><a href="https://github.com/ajimix">ajimix</a> (<a href="https://github.com/haraka/Haraka/commits?author=ajimix">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/58205701?v=4"><br><a href="https://github.com/adarshasp87">adarshasp87</a> (<a href="https://github.com/haraka/Haraka/commits?author=adarshasp87">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/284925?v=4"><br><a href="https://github.com/64kps">64kps</a> (<a href="https://github.com/haraka/Haraka/commits?author=64kps">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/803496?v=4"><br><a href="https://github.com/mskrajnowski">mskrajnowski</a> (<a href="https://github.com/haraka/Haraka/commits?author=mskrajnowski">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/18592942?v=4"><br><a href="https://github.com/mnsilva">mnsilva</a> (<a href="https://github.com/haraka/Haraka/commits?author=mnsilva">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/6890321?v=4"><br><a href="https://github.com/httpstersk">httpstersk</a> (<a href="https://github.com/haraka/Haraka/commits?author=httpstersk">1</a>) |
28
+ | <img height="80" src="https://avatars.githubusercontent.com/u/28440072?v=4"><br><a href="https://github.com/leadbi">leadbi</a> (<a href="https://github.com/haraka/Haraka/commits?author=leadbi">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/22004482?v=4"><br><a href="https://github.com/kajes">kajes</a> (<a href="https://github.com/haraka/Haraka/commits?author=kajes">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/51789698?v=4"><br><a href="https://github.com/Young-Lord">Young-Lord</a> (<a href="https://github.com/haraka/Haraka/commits?author=Young-Lord">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/11235022?v=4"><br><a href="https://github.com/kzub">kzub</a> (<a href="https://github.com/haraka/Haraka/commits?author=kzub">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/510957?v=4"><br><a href="https://github.com/kevinmartin">kevinmartin</a> (<a href="https://github.com/haraka/Haraka/commits?author=kevinmartin">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/75720?v=4"><br><a href="https://github.com/kgoess">kgoess</a> (<a href="https://github.com/haraka/Haraka/commits?author=kgoess">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/5689132?v=4"><br><a href="https://github.com/mr-karan">mr-karan</a> (<a href="https://github.com/haraka/Haraka/commits?author=mr-karan">1</a>) |
29
+ | <img height="80" src="https://avatars.githubusercontent.com/u/7114909?v=4"><br><a href="https://github.com/tyranron">tyranron</a> (<a href="https://github.com/haraka/Haraka/commits?author=tyranron">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/49093?v=4"><br><a href="https://github.com/jplock">jplock</a> (<a href="https://github.com/haraka/Haraka/commits?author=jplock">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/411338?v=4"><br><a href="https://github.com/josteink">josteink</a> (<a href="https://github.com/haraka/Haraka/commits?author=josteink">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/646768?v=4"><br><a href="https://github.com/nebulade">nebulade</a> (<a href="https://github.com/haraka/Haraka/commits?author=nebulade">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/6860647?v=4"><br><a href="https://github.com/GuroKung">GuroKung</a> (<a href="https://github.com/haraka/Haraka/commits?author=GuroKung">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/2649838?v=4"><br><a href="https://github.com/stanek0j">stanek0j</a> (<a href="https://github.com/haraka/Haraka/commits?author=stanek0j">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/55651?v=4"><br><a href="https://github.com/jaredj">jaredj</a> (<a href="https://github.com/haraka/Haraka/commits?author=jaredj">1</a>) |
30
+ | <img height="80" src="https://avatars.githubusercontent.com/u/397735?v=4"><br><a href="https://github.com/jrb">jrb</a> (<a href="https://github.com/haraka/Haraka/commits?author=jrb">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/1560587?v=4"><br><a href="https://github.com/jkroepke">jkroepke</a> (<a href="https://github.com/haraka/Haraka/commits?author=jkroepke">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/5376280?v=4"><br><a href="https://github.com/Chopinsky">Chopinsky</a> (<a href="https://github.com/haraka/Haraka/commits?author=Chopinsky">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/195918?v=4"><br><a href="https://github.com/hperrin">hperrin</a> (<a href="https://github.com/haraka/Haraka/commits?author=hperrin">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/376721?v=4"><br><a href="https://github.com/urlund">urlund</a> (<a href="https://github.com/haraka/Haraka/commits?author=urlund">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/7700727?v=4"><br><a href="https://github.com/gwieshammer">gwieshammer</a> (<a href="https://github.com/haraka/Haraka/commits?author=gwieshammer">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/914107?v=4"><br><a href="https://github.com/gpetrioli">gpetrioli</a> (<a href="https://github.com/haraka/Haraka/commits?author=gpetrioli">1</a>) |
31
+ | <img height="80" src="https://avatars.githubusercontent.com/u/140875?v=4"><br><a href="https://github.com/fabiob">fabiob</a> (<a href="https://github.com/haraka/Haraka/commits?author=fabiob">1</a>) | <img height="80" src="https://avatars.githubusercontent.com/u/400795?v=4"><br><a href="https://github.com/felixrabe">felixrabe</a> (<a href="https://github.com/haraka/Haraka/commits?author=felixrabe">1</a>) | | | | | |
32
32
 
33
33
  <sub>this file is generated by [.release](https://github.com/msimerson/.release).
34
34
  Contribute to this project to get your GitHub profile included here.</sub>
package/Plugins.md CHANGED
@@ -19,123 +19,123 @@ A comprehensive list of known plugins. Create a PR to add yours to these lists.
19
19
 
20
20
  ### Auth Plugins
21
21
 
22
- | Name | Description |
23
- | -------------------------------- | ------------------------------------------------- |
24
- | [auth-enc-file][url-authencflat] | Auth against user/pass in an encrypted file |
25
- | [flat_file][url-authflat] | Auth against user/pass in a file |
26
- | [auth_bridge][url-authbridge] | Auth against remote MTA |
27
- | [auth-imap][url-auth-imap] | Auth against IMAP server |
28
- | [auth_ldap][url-auth-ldap] | Auth against LDAP |
29
- | [auth_proxy][url-authproxy] | Auth against remote MTA |
30
- | [auth_vpopmaild][url-authvpop] | Auth against vpopmaild |
31
- | [dkim][url-dkim] | DKIM sign & verify |
32
- | [dovecot][url-dovecot] | SMTP AUTH & recipient validation against dovecot |
33
- | [LDAP][url-ldap] | Aliases, Auth, and Recipient validation from LDAP |
34
- | [mailauth][url-mailauth] | Email Auth (SPF, DKIM, DMARC, ARC, & BIMI) |
35
- | [opendkim][url-opendkim] | DKIM sign and verify email messages |
36
- | [spf][url-spf] | Perform SPF checks |
22
+ | Name | Description | Published |
23
+ | -------------------------------- | ------------------------------------------------- | --------- |
24
+ | [auth-enc-file][url-authencflat] | Auth against user/pass in an encrypted file | 2018 |
25
+ | [flat_file][url-authflat] | Auth against user/pass in a file | 2026 |
26
+ | [auth_bridge][url-authbridge] | Auth against remote MTA | 2026 |
27
+ | [auth-imap][url-auth-imap] | Auth against IMAP server | 2022 |
28
+ | [auth_ldap][url-auth-ldap] | Auth against LDAP | 2023 |
29
+ | [auth_proxy][url-authproxy] | Auth against remote MTA | 2026 |
30
+ | [auth_vpopmaild][url-authvpop] | Auth against vpopmaild | 2026 |
31
+ | [dkim][url-dkim] | DKIM sign & verify | 2026 |
32
+ | [dovecot][url-dovecot] | SMTP AUTH & recipient validation against dovecot | 2025 |
33
+ | [LDAP][url-ldap] | Aliases, Auth, and Recipient validation from LDAP | 2024 |
34
+ | [mailauth][url-mailauth] | Email Auth (SPF, DKIM, DMARC, ARC, & BIMI) | 2024 |
35
+ | [opendkim][url-opendkim] | DKIM sign and verify email messages | 2018 |
36
+ | [spf][url-spf] | Perform SPF checks | 2026 |
37
37
 
38
38
  ### Enrichment Plugins
39
39
 
40
- | Name | Description |
41
- | ------------------------------ | ------------------------------------------ |
42
- | [ASN][url-asn] | Get ASN info for remote senders |
43
- | [fcrdns][url-fcrdns] | Forward Confirmed reverse DNS |
44
- | [geoip][url-geoip] | get geographic information about mail senders |
45
- | [p0f][url-p0f] | TCP Fingerprinting |
46
- | [karma][url-karma] | Dynamic scoring of incoming connections |
47
- | [known-senders][url-known-senders] | Reward emails from those you send mail to |
48
- | [record_envelope_addresses][url-recordenv] | Adds message headers with ENV recips |
40
+ | Name | Description | Published |
41
+ | ------------------------------------------ | --------------------------------------------- | --------- |
42
+ | [ASN][url-asn] | Get ASN info for remote senders | 2026 |
43
+ | [fcrdns][url-fcrdns] | Forward Confirmed reverse DNS | 2025 |
44
+ | [geoip][url-geoip] | get geographic information about mail senders | 2026 |
45
+ | [p0f][url-p0f] | TCP Fingerprinting | 2025 |
46
+ | [karma][url-karma] | Dynamic scoring of incoming connections | 2026 |
47
+ | [known-senders][url-known-senders] | Reward emails from those you send mail to | 2025 |
48
+ | [record_envelope_addresses][url-recordenv] | Adds message headers with ENV recips | 2026 |
49
49
 
50
50
  ### Filtering Plugins
51
51
 
52
- | Name | Description |
53
- | ------------------------------ | ------------------------------------------ |
54
- | [attachment][url-attach] | Restrict attachment types |
55
- | [block_me][url-blockme] | Populate block list via forwarded emails |
56
- | [avg][url-avg] | AVG antivirus scanner |
57
- | [clamd][url-clamd] | Anti-Virus scanning with ClamAV |
58
- | [data.signatures][url-sigs] | Block emails whose bodies match signatures |
59
- | [dcc][url-dcc] | Distributed Checksum Clearinghouse |
60
- | [dns-list][url-dns-list] | Check against DNS and reputation lists |
61
- | [early_talker][url-early] | Reject remotes that talk early |
62
- | [esets][url-esets] | Virus scanning with ESET Mail Security |
63
- | [greylist][url-greylist] | Greylisting |
64
- | [helo.checks][url-helo] | Validity checks of the HELO string |
65
- | [mail_from.is_resolvable][url-mfres] | Verifies the MAIL FROM domain resolves to a MX |
66
- | [messagesniffer][url-msgsniff] | Anti-spam via [MessageSniffer][url-ms] |
67
- | [milter][url-milter] | milter support |
68
- | [rspamd][url-rspamd] | Scan emails with rspamd |
69
- | [spamassassin][url-spamass] | Scan emails with SpamAssassin |
70
- | [uribl][url-uribl] | Block based on URI blacklists |
52
+ | Name | Description | Published |
53
+ | ------------------------------------ | ---------------------------------------------- | --------- |
54
+ | [attachment][url-attach] | Restrict attachment types | 2026 |
55
+ | [block_me][url-blockme] | Populate block list via forwarded emails | 2026 |
56
+ | [avg][url-avg] | AVG antivirus scanner | 2024 |
57
+ | [clamd][url-clamd] | Anti-Virus scanning with ClamAV | 2025 |
58
+ | [data.signatures][url-sigs] | Block emails whose bodies match signatures | 2026 |
59
+ | [dcc][url-dcc] | Distributed Checksum Clearinghouse | 2025 |
60
+ | [dns-list][url-dns-list] | Check against DNS and reputation lists | 2025 |
61
+ | [early_talker][url-early] | Reject remotes that talk early | 2026 |
62
+ | [esets][url-esets] | Virus scanning with ESET Mail Security | 2025 |
63
+ | [greylist][url-greylist] | Greylisting | 2026 |
64
+ | [helo.checks][url-helo] | Validity checks of the HELO string | 2026 |
65
+ | [mail_from.is_resolvable][url-mfres] | Verifies the MAIL FROM domain resolves to a MX | 2026 |
66
+ | [messagesniffer][url-msgsniff] | Anti-spam via [MessageSniffer][url-ms] | 2025 |
67
+ | [milter][url-milter] | milter support | 2017 |
68
+ | [rspamd][url-rspamd] | Scan emails with rspamd | 2026 |
69
+ | [spamassassin][url-spamass] | Scan emails with SpamAssassin | 2026 |
70
+ | [uribl][url-uribl] | Block based on URI blacklists | 2025 |
71
71
 
72
72
  ### Logging & Telemetry
73
73
 
74
- | Name | Description |
75
- | -------------------------------- | ------------------------------------------------------------------------ |
76
- | [accounting_files][url-acc-files] | Retrieve, Store and Archive custom information of outbound traffic |
77
- | [elasticsearch][url-elastic] | Store message metadata in Elasticsearch |
78
- | [log reader][url-logreader] | extract log entries from the haraka log file |
79
- | [outbound-logger][url-outbound-logger] | JSON logging of outbound email. Logs metadata about delivered/bounced emails |
80
- | [process_title][url-proctitle] | Populate `ps` output with activity counters |
81
- | [syslog][url-syslog] | Log to syslog |
82
- | [watch][url-watch] | Watch live SMTP traffic in a web interface |
74
+ | Name | Description | Published |
75
+ | -------------------------------------------- | ---------------------------------------------------------------------------- | --------- |
76
+ | [accounting_files][url-acc-files] | Retrieve, Store and Archive custom information of outbound traffic | 2017 |
77
+ | [elasticsearch][url-elastic] | Store message metadata in Elasticsearch | 2026 |
78
+ | [log reader][url-logreader] | extract log entries from the haraka log file | 2026 |
79
+ | [outbound-logger][url-outbound-logger] | JSON logging of outbound email. Logs metadata about delivered/bounced emails | — |
80
+ | [process_title][url-proctitle] | Populate `ps` output with activity counters | 2026 |
81
+ | [syslog][url-syslog] | Log to syslog | 2026 |
82
+ | [watch][url-watch] | Watch live SMTP traffic in a web interface | 2026 |
83
83
 
84
84
  ### Queue Plugins
85
85
 
86
- | Name | Description |
87
- | -------------------------------- | ------------------------------------------------------------------------ |
88
- | [discard][url-qdisc] | queues messages to /dev/null |
89
- | [kafka][url-kafka] | Queue inbound mail to a Kafka topic |
90
- | [lmtp][url-qlmtp] | deliver queued messages via LMTP |
91
- | [mongodb][mongo-url] | Queue emails to MongoDB |
92
- | [qmail-queue][url-qmail] | queue to qmail |
93
- | [quarantine][url-qquart] | queue to a quarantine directory |
94
- | [rabbitmq][url-qrabbit] | queue to RabbitMQ |
95
- | [rabbitmq_amqplib][url-qrabbita] | queue to RabbitMQ using amqplib |
96
- | [rails][url-qrails] | queue messages to a Rails app using [Action Mailbox][url-action-mailbox] |
97
- | [smtp_bridge][url-qbridge] | Bridge SMTP sessions to another MTA |
98
- | [smtp_forward][url-qforward] | Forward emails to another MTA |
99
- | [smtp_proxy][url-qproxy] | Proxy SMTP connections to another MTA |
100
- | [wildduck][url-wildduck] | queue messages to Wild Duck |
86
+ | Name | Description | Published |
87
+ | ---------------------------------- | ---------------------------------------------------------------------------- | --------- |
88
+ | [discard][url-qdisc] | queues messages to /dev/null | 2026 |
89
+ | [kafka][url-kafka] | Queue inbound mail to a Kafka topic | 2023 |
90
+ | [lmtp][url-qlmtp] | deliver queued messages via LMTP | 2026 |
91
+ | [mongodb][mongo-url] | Queue emails to MongoDB | 2024 |
92
+ | [qmail-queue][url-qmail] | queue to qmail | 2026 |
93
+ | [quarantine][url-qquart] | queue to a quarantine directory | 2026 |
94
+ | [rabbitmq][url-qrabbit] | queue to RabbitMQ | 2026 |
95
+ | [rabbitmq_amqplib][url-qrabbita] | queue to RabbitMQ using amqplib | — |
96
+ | [rails][url-qrails] | queue messages to a Rails app using [Action Mailbox][url-action-mailbox] | |
97
+ | [smtp_bridge][url-qbridge] | Bridge SMTP sessions to another MTA | 2026 |
98
+ | [smtp_forward][url-qforward] | Forward emails to another MTA | 2026 |
99
+ | [smtp_proxy][url-qproxy] | Proxy SMTP connections to another MTA | 2026 |
100
+ | [wildduck][url-wildduck] | queue messages to Wild Duck | 2026 |
101
101
 
102
102
  ### Recipient Validation
103
103
 
104
- | Name | Description |
105
- | -----------------------------------| ----------------------------------------------------- |
106
- | [dovecot][url-dovecot] | Recipient validation & SMTP AUTH against dovecot |
107
- | [LDAP][url-ldap] | Aliases, Auth, and Recipient validation from LDAP |
108
- | [recipient-routes][url-rroutes] | Route emails based on their recipient(s) |
109
- | [rcpt_to.in_host_list][url-rhost] | Define local email domains in a file |
110
- | [rcpt_to.ldap][url-rcpt-ldap] | Validate recipients against LDAP |
111
- | [rcpt-postgresql][url-postgres] | validate recipients against PostgreSQL |
112
- | [qmail-deliverable][url-rqmd] | Validate recipients against Qmail-Deliverable |
113
- | [vmta][url-vmta] | Virtual MTA management |
114
- | [wildduck][url-wildduck] | provides recipient checks against Wild Duck |
104
+ | Name | Description | Published |
105
+ | ---------------------------------- | ----------------------------------------------------- | --------- |
106
+ | [dovecot][url-dovecot] | Recipient validation & SMTP AUTH against dovecot | 2025 |
107
+ | [LDAP][url-ldap] | Aliases, Auth, and Recipient validation from LDAP | 2024 |
108
+ | [recipient-routes][url-rroutes] | Route emails based on their recipient(s) | 2025 |
109
+ | [rcpt_to.in_host_list][url-rhost] | Define local email domains in a file | 2026 |
110
+ | [rcpt_to.ldap][url-rcpt-ldap] | Validate recipients against LDAP | 2023 |
111
+ | [rcpt-postgresql][url-postgres] | validate recipients against PostgreSQL | 2016 |
112
+ | [qmail-deliverable][url-rqmd] | Validate recipients against Qmail-Deliverable | 2026 |
113
+ | [vmta][url-vmta] | Virtual MTA management | 2017 |
114
+ | [wildduck][url-wildduck] | provides recipient checks against Wild Duck | 2026 |
115
115
 
116
116
  ### Every other Plugin
117
117
 
118
- | Name | Description |
119
- | ------------------------------------------ | --------------------------------------------------------------- |
120
- | [access][url-access] | ACLs based on IPs, domains, email addrs, etc. |
121
- | [aliases][url-aliases] | Email aliases |
122
- | [bounce][url-bounce] | Many options for bounce processing |
123
- | [delay_deny][url-delay] | Delays all pre-DATA 'deny' results |
124
- | [dovecot][url-dovecot] | Recipient validation & SMTP AUTH against dovecot |
125
- | [headers][url-headers] | Inspect and verify various email headers |
126
- | [Limit][url-limit] | Apply many types of limits to SMTP connections |
127
- | [prevent_credential_leaks][url-creds] | Prevent users from emailing their credentials |
128
- | [redis][url-redis] | multi-purpose Redis db connection(s) |
129
- | [relay][url-relay] | Manage relay permissions |
130
- | [reseed_rng][url-rng] | Reseed the RNG |
131
- | [batv-srs][url-batv] | BATV & SRS |
132
- | [srs][url-srs] | Sender Rewriting Scheme |
133
- | [tarpit][url-tarpit] | Slow down connections |
134
- | [tls][url-tls] | Implements TLS |
135
- | [toobusy][url-toobusy] | Defers connections when too busy |
136
- | [xclient][url-xclient] | Implements XCLIENT |
137
- | [save-sent][url-save-sent] | Save sent emails on the serverside to a mailbox of the sender |
138
- | [dropbox][url-dropbox] | Forward incoming emails to configured Dropbox webhook URLs. |
118
+ | Name | Description | Published |
119
+ | ------------------------------------------ | --------------------------------------------------------------- | --------- |
120
+ | [access][url-access] | ACLs based on IPs, domains, email addrs, etc. | 2026 |
121
+ | [aliases][url-aliases] | Email aliases | 2026 |
122
+ | [bounce][url-bounce] | Many options for bounce processing | 2026 |
123
+ | [delay_deny][url-delay] | Delays all pre-DATA 'deny' results | 2026 |
124
+ | [dovecot][url-dovecot] | Recipient validation & SMTP AUTH against dovecot | 2025 |
125
+ | [headers][url-headers] | Inspect and verify various email headers | 2026 |
126
+ | [Limit][url-limit] | Apply many types of limits to SMTP connections | 2025 |
127
+ | [prevent_credential_leaks][url-creds] | Prevent users from emailing their credentials | 2026 |
128
+ | [redis][url-redis] | multi-purpose Redis db connection(s) | 2025 |
129
+ | [relay][url-relay] | Manage relay permissions | 2026 |
130
+ | [reseed_rng][url-rng] | Reseed the RNG | 2026 |
131
+ | [batv-srs][url-batv] | BATV & SRS | 2020 |
132
+ | [srs][url-srs] | Sender Rewriting Scheme | — |
133
+ | [tarpit][url-tarpit] | Slow down connections | 2026 |
134
+ | [tls][url-tls] | Implements TLS | 2026 |
135
+ | [toobusy][url-toobusy] | Defers connections when too busy | 2026 |
136
+ | [xclient][url-xclient] | Implements XCLIENT | 2026 |
137
+ | [save-sent][url-save-sent] | Save sent emails on the serverside to a mailbox of the sender | — |
138
+ | [dropbox][url-dropbox] | Forward incoming emails to configured Dropbox webhook URLs. | — |
139
139
 
140
140
  <!-- URLs tucked safely out of the way -->
141
141
 
@@ -19,3 +19,13 @@ port=2555
19
19
  ; should outbound messages be delivered by smtp_forward?
20
20
  ; see #1472 and #2795
21
21
  ; enable_outbound=false
22
+
23
+ ; Options here override the same option in tls.ini [main]
24
+ [tls]
25
+ ; rejectUnauthorized=true
26
+ ; minVersion=TLSv1.2
27
+ ; ciphers=ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256
28
+ ; key=outbound_tls_key.pem
29
+ ; cert=outbound_tls_cert.pem
30
+ ; no_tls_hosts[]=10.0.0.5
31
+ ; force_tls_hosts[]=mx.example.com
@@ -15,3 +15,13 @@ port=2555
15
15
  ; should outbound messages be delivered by smtp_proxy?
16
16
  ; see https://github.com/haraka/Haraka/issues/1472
17
17
  ; enable_outbound=true
18
+
19
+ ; Options here override the same option in tls.ini [main]
20
+ [tls]
21
+ ; rejectUnauthorized=true
22
+ ; minVersion=TLSv1.2
23
+ ; ciphers=ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256
24
+ ; key=outbound_tls_key.pem
25
+ ; cert=outbound_tls_cert.pem
26
+ ; no_tls_hosts[]=10.0.0.5
27
+ ; force_tls_hosts[]=mx.example.com
package/connection.js CHANGED
@@ -329,7 +329,7 @@ class Connection {
329
329
  } catch (err) {
330
330
  if (err.stack) {
331
331
  this.logerror(`${method} failed: ${err}`)
332
- err.stack.split('\n').forEach(this.logerror)
332
+ for (const line of err.stack.split('\n')) this.logerror(line)
333
333
  } else {
334
334
  this.logerror(`${method} failed: ${err}`)
335
335
  }
@@ -1234,6 +1234,13 @@ class Connection {
1234
1234
  if (!host) {
1235
1235
  return this.respond(501, 'HELO requires domain/address - see RFC-2821 4.1.1.1')
1236
1236
  }
1237
+ // RFC 5321 §4.1.1.1: the domain/address-literal cannot contain
1238
+ // control characters. process_line() only strips the first \r?\n,
1239
+ // so a bare \r could otherwise survive into hello.host and the
1240
+ // generated Received: header / logs (header injection).
1241
+ if (/[\x00-\x1f\x7f]/.test(host)) {
1242
+ return this.respond(501, 'HELO syntax error - see RFC-2821 4.1.1.1')
1243
+ }
1237
1244
 
1238
1245
  this.reset_transaction(() => {
1239
1246
  this.set('hello', 'verb', 'HELO')
@@ -1248,6 +1255,10 @@ class Connection {
1248
1255
  if (!host) {
1249
1256
  return this.respond(501, 'EHLO requires domain/address - see RFC-2821 4.1.1.1')
1250
1257
  }
1258
+ // RFC 5321 §4.1.1.1: reject control chars (see cmd_helo).
1259
+ if (/[\x00-\x1f\x7f]/.test(host)) {
1260
+ return this.respond(501, 'EHLO syntax error - see RFC-2821 4.1.1.1')
1261
+ }
1251
1262
 
1252
1263
  this.reset_transaction(() => {
1253
1264
  this.set('hello', 'verb', 'EHLO')
@@ -1320,10 +1331,10 @@ class Connection {
1320
1331
 
1321
1332
  // Get rest of key=value pairs
1322
1333
  const params = {}
1323
- results.forEach((param) => {
1334
+ for (const param of results) {
1324
1335
  const kv = param.match(/^([^=]+)(?:=(.+))?$/)
1325
1336
  if (kv) params[kv[1].toUpperCase()] = kv[2] || null
1326
- })
1337
+ }
1327
1338
 
1328
1339
  // Parameters are only valid if EHLO was sent
1329
1340
  if (!this.esmtp && Object.keys(params).length > 0) {
@@ -1379,10 +1390,10 @@ class Connection {
1379
1390
 
1380
1391
  // Get rest of key=value pairs
1381
1392
  const params = {}
1382
- results.forEach((param) => {
1393
+ for (const param of results) {
1383
1394
  const kv = param.match(/^([^=]+)(?:=(.+))?$/)
1384
1395
  if (kv) params[kv[1].toUpperCase()] = kv[2] || null
1385
- })
1396
+ }
1386
1397
 
1387
1398
  // Parameters are only valid if EHLO was sent
1388
1399
  if (!this.esmtp && Object.keys(params).length > 0) {
@@ -1433,17 +1444,23 @@ class Connection {
1433
1444
  this.transaction.notes.authentication_results = []
1434
1445
  }
1435
1446
 
1447
+ // Strip CR/LF and other control chars: an attacker-influenced
1448
+ // value (e.g. a failed AUTH username, see auth_base) must not be
1449
+ // able to inject extra header lines into Authentication-Results.
1450
+ // The legitimate folding (;\r\n\t) is added by the join below.
1451
+ const ar_clean = (s) => String(s).replace(/[\x00-\x1f\x7f]/g, '')
1452
+
1436
1453
  // if message, store it in the appropriate note
1437
1454
  if (message) {
1438
1455
  if (has_tran === true) {
1439
- this.transaction.notes.authentication_results.push(message)
1456
+ this.transaction.notes.authentication_results.push(ar_clean(message))
1440
1457
  } else {
1441
- this.notes.authentication_results.push(message)
1458
+ this.notes.authentication_results.push(ar_clean(message))
1442
1459
  }
1443
1460
  }
1444
1461
 
1445
1462
  // assemble the new header
1446
- let header = [this.local.host, ...this.notes.authentication_results]
1463
+ let header = [ar_clean(this.local.host), ...this.notes.authentication_results]
1447
1464
  if (has_tran === true) {
1448
1465
  header = [...header, ...this.transaction.notes.authentication_results]
1449
1466
  }
@@ -38,9 +38,7 @@ Configuration is stored in smtp_forward.ini in the following keys:
38
38
 
39
39
  - enable_tls=[true]
40
40
 
41
- Enable TLS with the forward host (if supported). TLS uses options from the tls plugin. If key and cert are provided in the the outbound section of the tls plugin, that certificate will be used as a TLS Client Certificate.
42
-
43
- This option controls the use of TLS via `STARTTLS`. This plugin does not work with SMTP over TLS.
41
+ Enable opportunistic TLS with the forward host via `STARTTLS` (if the host advertises it). This plugin does not work with implicit SMTP over TLS.
44
42
 
45
43
  - auth_type=[plain\|login]
46
44
 
@@ -69,6 +67,24 @@ Configuration is stored in smtp_forward.ini in the following keys:
69
67
  [example.com]
70
68
  [example.net]
71
69
 
70
+ - [tls]
71
+
72
+ Client STARTTLS options are assembled by merging:
73
+
74
+ 1. `tls.ini` `[main]` — the global Haraka TLS config
75
+ 2. `smtp_forward.ini` `[tls]` — overrides. Anything set here wins.
76
+
77
+ Example `smtp_forward.ini` `[tls]` section:
78
+
79
+ [tls]
80
+ rejectUnauthorized=true
81
+ minVersion=TLSv1.2
82
+ no_tls_hosts[]=10.0.0.5
83
+
84
+ Per-domain `enable_tls=false` still disables STARTTLS for that backend. Per-domain TLS cipher/cert overrides are not currently supported.
85
+
86
+ Changes to `tls.ini` require a Haraka restart to apply to the forward path; changes to `smtp_forward.ini` are picked up by the existing reload hook.
87
+
72
88
  # Per-Domain Configuration
73
89
 
74
90
  More specific forward routes for domains can be defined. The domain is chosen based on the value of the `domain_selector` config variable.
@@ -44,8 +44,7 @@ Configuration is stored in smtp_proxy.ini in the following keys:
44
44
 
45
45
  - enable_tls=[true|yes|1]
46
46
 
47
- Enable TLS with the forward host (if supported). TLS uses options from
48
- the tls plugin.
47
+ Enable opportunistic TLS with the forward host via `STARTTLS` (if the host advertises it).
49
48
 
50
49
  - auth_type=[plain|login]
51
50
 
@@ -58,3 +57,12 @@ Configuration is stored in smtp_proxy.ini in the following keys:
58
57
  - auth_pass=PASSWORD
59
58
 
60
59
  SMTP AUTH password to use.
60
+
61
+ - [tls]
62
+
63
+ Client STARTTLS options are assembled by merging:
64
+
65
+ 1. `tls.ini` `[main]` — the global Haraka TLS config.
66
+ 2. `smtp_proxy.ini` `[tls]` — overrides. Anything set here wins.
67
+
68
+ Changes to `tls.ini` require a Haraka restart to apply to the proxy path; changes to `smtp_proxy.ini` are picked up by the existing reload hook.
package/haraka.js CHANGED
@@ -25,7 +25,7 @@ exports.version = utils.getVersion(__dirname)
25
25
 
26
26
  process.on('uncaughtException', (err) => {
27
27
  if (err.stack) {
28
- err.stack.split('\n').forEach((line) => logger.crit(line))
28
+ for (const line of err.stack.split('\n')) logger.crit(line)
29
29
  } else {
30
30
  logger.crit(`Caught exception: ${JSON.stringify(err)}`)
31
31
  }