Haraka 2.8.28 → 3.0.1

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 (135) hide show
  1. package/.eslintrc.yaml +2 -10
  2. package/Changes.md +84 -2
  3. package/Dockerfile +1 -1
  4. package/Plugins.md +9 -4
  5. package/README.md +2 -6
  6. package/bin/haraka +5 -4
  7. package/config/outbound.ini +0 -7
  8. package/config/plugins +1 -1
  9. package/config/smtp.ini +1 -1
  10. package/config/smtp_forward.ini +2 -8
  11. package/config/smtp_proxy.ini +0 -6
  12. package/connection.js +178 -204
  13. package/coverage/lcov.info +13863 -0
  14. package/coverage/tmp/coverage-42958-1658373250585-0.json +1 -0
  15. package/coverage/tmp/coverage-42961-1658373250529-0.json +1 -0
  16. package/dkim.js +66 -73
  17. package/docs/Body.md +1 -22
  18. package/docs/CoreConfig.md +2 -2
  19. package/docs/Header.md +1 -47
  20. package/docs/Outbound.md +8 -36
  21. package/endpoint.js +1 -1
  22. package/haraka.js +1 -1
  23. package/host_pool.js +8 -12
  24. package/logger.js +25 -32
  25. package/outbound/client_pool.js +11 -153
  26. package/outbound/config.js +5 -11
  27. package/outbound/hmail.js +109 -143
  28. package/outbound/index.js +13 -25
  29. package/outbound/mx_lookup.js +10 -7
  30. package/outbound/queue.js +8 -12
  31. package/outbound/timer_queue.js +2 -4
  32. package/outbound/tls.js +17 -18
  33. package/outbound/todo.js +1 -0
  34. package/package.json +57 -55
  35. package/plugins/auth/auth_base.js +39 -63
  36. package/plugins/auth/auth_bridge.js +3 -4
  37. package/plugins/auth/auth_proxy.js +16 -16
  38. package/plugins/auth/auth_vpopmaild.js +30 -37
  39. package/plugins/auth/flat_file.js +9 -13
  40. package/plugins/avg.js +9 -11
  41. package/plugins/backscatterer.js +1 -1
  42. package/plugins/block_me.js +2 -6
  43. package/plugins/bounce.js +106 -124
  44. package/plugins/clamd.js +59 -63
  45. package/plugins/data.signatures.js +6 -6
  46. package/plugins/data.uribl.js +1 -415
  47. package/plugins/delay_deny.js +19 -20
  48. package/plugins/dkim_sign.js +56 -62
  49. package/plugins/dkim_verify.js +9 -8
  50. package/plugins/dns_list_base.js +43 -42
  51. package/plugins/dnsbl.js +41 -46
  52. package/plugins/dnswl.js +23 -26
  53. package/plugins/early_talker.js +24 -28
  54. package/plugins/esets.js +8 -11
  55. package/plugins/greylist.js +161 -190
  56. package/plugins/helo.checks.js +175 -197
  57. package/plugins/mail_from.is_resolvable.js +38 -38
  58. package/plugins/messagesniffer.js +33 -40
  59. package/plugins/prevent_credential_leaks.js +7 -5
  60. package/plugins/process_title.js +16 -17
  61. package/plugins/queue/deliver.js +2 -2
  62. package/plugins/queue/lmtp.js +5 -6
  63. package/plugins/queue/qmail-queue.js +11 -13
  64. package/plugins/queue/quarantine.js +25 -34
  65. package/plugins/queue/rabbitmq.js +3 -2
  66. package/plugins/queue/rabbitmq_amqplib.js +9 -9
  67. package/plugins/queue/smtp_bridge.js +5 -4
  68. package/plugins/queue/smtp_forward.js +81 -89
  69. package/plugins/queue/smtp_proxy.js +21 -22
  70. package/plugins/queue/test.js +2 -1
  71. package/plugins/rcpt_to.host_list_base.js +20 -30
  72. package/plugins/rcpt_to.in_host_list.js +12 -14
  73. package/plugins/rcpt_to.max_count.js +7 -5
  74. package/plugins/record_envelope_addresses.js +4 -6
  75. package/plugins/relay.js +64 -74
  76. package/plugins/reseed_rng.js +1 -2
  77. package/plugins/spamassassin.js +56 -68
  78. package/plugins/status.js +2 -3
  79. package/plugins/tarpit.js +8 -11
  80. package/plugins/tls.js +14 -17
  81. package/plugins/toobusy.js +6 -8
  82. package/plugins/xclient.js +14 -25
  83. package/plugins.js +24 -29
  84. package/rfc1869.js +2 -2
  85. package/server.js +3 -13
  86. package/smtp_client.js +138 -215
  87. package/tests/config/smtp_forward.ini +0 -6
  88. package/tests/fixtures/line_socket.js +1 -1
  89. package/tests/fixtures/util_hmailitem.js +5 -7
  90. package/tests/fixtures/vm_harness.js +2 -2
  91. package/tests/host_pool.js +13 -14
  92. package/tests/installation/plugins/inherits.js +1 -2
  93. package/tests/logger.js +2 -2
  94. package/tests/plugins/bounce.js +6 -8
  95. package/tests/plugins/dkim_signer.js +7 -7
  96. package/tests/plugins/dns_list_base.js +7 -7
  97. package/tests/plugins/helo.checks.js +1 -1
  98. package/tests/plugins/mail_from.is_resolvable.js +10 -54
  99. package/tests/plugins/queue/smtp_forward.js +11 -11
  100. package/tests/plugins/rcpt_to.host_list_base.js +1 -1
  101. package/tests/plugins/rcpt_to.in_host_list.js +1 -1
  102. package/tests/plugins/spamassassin.js +1 -1
  103. package/tests/queue/multibyte +0 -0
  104. package/tests/queue/plain +0 -0
  105. package/tests/rfc1869.js +4 -1
  106. package/tests/server.js +15 -9
  107. package/tests/smtp_client/auth.js +4 -14
  108. package/tests/smtp_client/basic.js +5 -15
  109. package/tests/smtp_client.js +7 -3
  110. package/tests/transaction.js +72 -19
  111. package/tls_socket.js +75 -85
  112. package/transaction.js +7 -9
  113. package/attachment_stream.js +0 -118
  114. package/bin/spf +0 -48
  115. package/chunkemitter.js +0 -75
  116. package/config/data.uribl.excludes +0 -202
  117. package/config/data.uribl.ini +0 -37
  118. package/config/spf.ini +0 -1
  119. package/docs/plugins/attachment.md +0 -92
  120. package/docs/plugins/data.uribl.md +0 -120
  121. package/docs/plugins/spf.md +0 -142
  122. package/mailbody.js +0 -502
  123. package/mailheader.js +0 -304
  124. package/messagestream.js +0 -441
  125. package/plugins/aliases.js +0 -120
  126. package/plugins/attachment.js +0 -503
  127. package/plugins/connect.p0f.js +0 -5
  128. package/plugins/spf.js +0 -327
  129. package/spf.js +0 -689
  130. package/tests/mailbody.js +0 -348
  131. package/tests/mailheader.js +0 -138
  132. package/tests/messagestream.js +0 -34
  133. package/tests/plugins/aliases.js +0 -376
  134. package/tests/plugins/spf.js +0 -251
  135. package/tests/spf.js +0 -96
package/connection.js CHANGED
@@ -15,7 +15,7 @@ const constants = require('haraka-constants');
15
15
  const net_utils = require('haraka-net-utils');
16
16
  const Notes = require('haraka-notes');
17
17
  const utils = require('haraka-utils');
18
- const Address = require('address-rfc2821').Address;
18
+ const { Address } = require('address-rfc2821');
19
19
  const ResultStore = require('haraka-results');
20
20
 
21
21
  // Haraka libs
@@ -187,6 +187,12 @@ class Connection {
187
187
  });
188
188
 
189
189
  self.client.on('timeout', () => {
190
+ // FIN has sent, when timeout just destroy socket
191
+ if (self.state >= states.DISCONNECTED) {
192
+ self.client.destroy();
193
+ self.loginfo(`timeout, destroy socket (state:${self.state})`)
194
+ return;
195
+ }
190
196
  if (self.state >= states.DISCONNECTING) return;
191
197
  self.respond(421, 'timeout', () => {
192
198
  self.fail('client connection timed out', log_data);
@@ -243,6 +249,7 @@ class Connection {
243
249
  let loc = this;
244
250
  for (let i=0; i < path_parts.length; i++) {
245
251
  const part = path_parts[i];
252
+ if (part === "__proto__" || part === "constructor") continue;
246
253
 
247
254
  // while another part remains
248
255
  if (i < (path_parts.length - 1)) {
@@ -300,7 +307,6 @@ class Connection {
300
307
  return this._relaying;
301
308
  }
302
309
  process_line (line) {
303
- const self = this;
304
310
 
305
311
  if (this.state >= states.DISCONNECTING) {
306
312
  if (logger.would_log(logger.LOGPROTOCOL)) {
@@ -358,15 +364,14 @@ class Connection {
358
364
  }
359
365
  catch (err) {
360
366
  if (err.stack) {
361
- const c = this;
362
- c.logerror(`${method} failed: ${err}`);
363
- err.stack.split("\n").forEach(c.logerror);
367
+ this.logerror(`${method} failed: ${err}`);
368
+ err.stack.split("\n").forEach(this.logerror);
364
369
  }
365
370
  else {
366
371
  this.logerror(`${method} failed: ${err}`);
367
372
  }
368
373
  this.respond(421, "Internal Server Error", () => {
369
- self.disconnect();
374
+ this.disconnect();
370
375
  });
371
376
  }
372
377
  }
@@ -409,7 +414,6 @@ class Connection {
409
414
  this._process_data();
410
415
  }
411
416
  _process_data () {
412
- const self = this;
413
417
  // We *must* detect disconnected connections here as the state
414
418
  // only transitions to states.CMD in the respond function below.
415
419
  // Otherwise if multiple commands are pipelined and then the
@@ -447,7 +451,7 @@ class Connection {
447
451
  this.logdebug('[early_talker]', { state: this.state, esmtp: this.esmtp, line: this_line });
448
452
  }
449
453
  this.early_talker = true;
450
- setImmediate(() => { self._process_data() });
454
+ setImmediate(() => { this._process_data() });
451
455
  break;
452
456
  }
453
457
  else if ((this.state === states.PAUSE || this.state === states.PAUSE_SMTP) && this.esmtp) {
@@ -487,7 +491,7 @@ class Connection {
487
491
  this.logdebug('[early_talker]', { state: this.state, esmtp: this.esmtp, line: this_line });
488
492
  }
489
493
  this.early_talker = true;
490
- setImmediate(() => { self._process_data() });
494
+ setImmediate(() => { this._process_data() });
491
495
  }
492
496
  break;
493
497
  }
@@ -504,7 +508,7 @@ class Connection {
504
508
  this.client.pause();
505
509
  this.current_data = null;
506
510
  return this.respond(521, "Command line too long", () => {
507
- self.disconnect();
511
+ this.disconnect();
508
512
  });
509
513
  }
510
514
  else {
@@ -598,11 +602,10 @@ class Connection {
598
602
  }
599
603
  disconnect () {
600
604
  if (this.state >= states.DISCONNECTING) return;
601
- const self = this;
602
- self.state = states.DISCONNECTING;
603
- self.current_data = null; // don't process any more data we have already received
605
+ this.state = states.DISCONNECTING;
606
+ this.current_data = null; // don't process any more data we have already received
604
607
  this.reset_transaction(() => {
605
- plugins.run_hooks('disconnect', self);
608
+ plugins.run_hooks('disconnect', this);
606
609
  });
607
610
  }
608
611
  disconnect_respond () {
@@ -632,9 +635,8 @@ class Connection {
632
635
  this.client.end();
633
636
  }
634
637
  get_capabilities () {
635
- const capabilities = [];
636
638
 
637
- return capabilities;
639
+ return [];
638
640
  }
639
641
  tran_uuid () {
640
642
  this.tran_count++;
@@ -665,17 +667,16 @@ class Connection {
665
667
  this.resume();
666
668
  }
667
669
  init_transaction (cb) {
668
- const self = this;
669
670
  this.reset_transaction(() => {
670
- self.transaction = trans.createTransaction(self.tran_uuid(), self.cfg);
671
+ this.transaction = trans.createTransaction(this.tran_uuid(), this.cfg);
671
672
  // Catch any errors from the message_stream
672
- self.transaction.message_stream.on('error', (err) => {
673
- self.logcrit(`message_stream error: ${err.message}`);
674
- self.respond('421', 'Internal Server Error', () => {
675
- self.disconnect();
673
+ this.transaction.message_stream.on('error', (err) => {
674
+ this.logcrit(`message_stream error: ${err.message}`);
675
+ this.respond('421', 'Internal Server Error', () => {
676
+ this.disconnect();
676
677
  });
677
678
  });
678
- self.transaction.results = new ResultStore(self);
679
+ this.transaction.results = new ResultStore(this);
679
680
  if (cb) cb();
680
681
  });
681
682
  }
@@ -687,21 +688,19 @@ class Connection {
687
688
  this.respond(code, msg);
688
689
  }
689
690
  pause () {
690
- const self = this;
691
- if (self.state >= states.DISCONNECTING) return;
692
- self.client.pause();
693
- if (self.state !== states.PAUSE_DATA) self.prev_state = self.state;
694
- self.state = states.PAUSE_DATA;
691
+ if (this.state >= states.DISCONNECTING) return;
692
+ this.client.pause();
693
+ if (this.state !== states.PAUSE_DATA) this.prev_state = this.state;
694
+ this.state = states.PAUSE_DATA;
695
695
  }
696
696
  resume () {
697
- const self = this;
698
- if (self.state >= states.DISCONNECTING) return;
699
- self.client.resume();
700
- if (self.prev_state) {
701
- self.state = self.prev_state;
702
- self.prev_state = null;
697
+ if (this.state >= states.DISCONNECTING) return;
698
+ this.client.resume();
699
+ if (this.prev_state) {
700
+ this.state = this.prev_state;
701
+ this.prev_state = null;
703
702
  }
704
- setImmediate(() => self._process_data());
703
+ setImmediate(() => this._process_data());
705
704
  }
706
705
  /////////////////////////////////////////////////////////////////////////////
707
706
  // SMTP Responses
@@ -711,7 +710,6 @@ class Connection {
711
710
  plugins.run_hooks('lookup_rdns', this);
712
711
  }
713
712
  lookup_rdns_respond (retval, msg) {
714
- const self = this;
715
713
  switch (retval) {
716
714
  case constants.ok:
717
715
  this.set('remote', 'host', (msg || 'Unknown'));
@@ -724,7 +722,7 @@ class Connection {
724
722
  case constants.denydisconnect:
725
723
  case constants.disconnect:
726
724
  this.respond(554, msg || "rDNS Lookup Failed", () => {
727
- self.disconnect();
725
+ this.disconnect();
728
726
  });
729
727
  break;
730
728
  case constants.denysoft:
@@ -732,12 +730,12 @@ class Connection {
732
730
  break;
733
731
  case constants.denysoftdisconnect:
734
732
  this.respond(421, msg || "rDNS Temporary Failure", () => {
735
- self.disconnect();
733
+ this.disconnect();
736
734
  });
737
735
  break;
738
736
  default:
739
737
  dns.reverse(this.remote.ip, (err, domains) => {
740
- self.rdns_response(err, domains);
738
+ this.rdns_response(err, domains);
741
739
  });
742
740
  }
743
741
  }
@@ -761,7 +759,6 @@ class Connection {
761
759
  plugins.run_hooks('connect', this);
762
760
  }
763
761
  unrecognized_command_respond (retval, msg) {
764
- const self = this;
765
762
  switch (retval) {
766
763
  case constants.ok:
767
764
  // response already sent, cool...
@@ -775,7 +772,7 @@ class Connection {
775
772
  case constants.denydisconnect:
776
773
  case constants.denysoftdisconnect:
777
774
  this.respond(retval === constants.denydisconnect ? 521 : 421, msg || "Unrecognized command", () => {
778
- self.disconnect();
775
+ this.disconnect();
779
776
  });
780
777
  break;
781
778
  default:
@@ -784,7 +781,6 @@ class Connection {
784
781
  }
785
782
  }
786
783
  connect_respond (retval, msg) {
787
- const self = this;
788
784
  // RFC 5321 Section 4.3.2 states that the only valid SMTP codes here are:
789
785
  // 220 = Service ready
790
786
  // 554 = Transaction failed (no SMTP service here)
@@ -796,7 +792,7 @@ class Connection {
796
792
  case constants.denydisconnect:
797
793
  case constants.disconnect:
798
794
  this.respond(554, msg || "Your mail is not welcome here", () => {
799
- self.disconnect();
795
+ this.disconnect();
800
796
  });
801
797
  break;
802
798
  case constants.denysoft:
@@ -804,7 +800,7 @@ class Connection {
804
800
  break;
805
801
  case constants.denysoftdisconnect:
806
802
  this.respond(421, msg || "Come back later", () => {
807
- self.disconnect();
803
+ this.disconnect();
808
804
  });
809
805
  break;
810
806
  default: {
@@ -840,28 +836,27 @@ class Connection {
840
836
  }
841
837
  }
842
838
  helo_respond (retval, msg) {
843
- const self = this;
844
839
  switch (retval) {
845
840
  case constants.deny:
846
841
  this.respond(550, msg || "HELO denied", () => {
847
- self.set('hello', 'verb', null);
848
- self.set('hello', 'host', null);
842
+ this.set('hello', 'verb', null);
843
+ this.set('hello', 'host', null);
849
844
  });
850
845
  break;
851
846
  case constants.denydisconnect:
852
847
  this.respond(550, msg || "HELO denied", () => {
853
- self.disconnect();
848
+ this.disconnect();
854
849
  });
855
850
  break;
856
851
  case constants.denysoft:
857
852
  this.respond(450, msg || "HELO denied", () => {
858
- self.set('hello', 'verb', null);
859
- self.set('hello', 'host', null);
853
+ this.set('hello', 'verb', null);
854
+ this.set('hello', 'host', null);
860
855
  });
861
856
  break;
862
857
  case constants.denysoftdisconnect:
863
858
  this.respond(450, msg || "HELO denied", () => {
864
- self.disconnect();
859
+ this.disconnect();
865
860
  });
866
861
  break;
867
862
  default:
@@ -871,29 +866,28 @@ class Connection {
871
866
  }
872
867
  }
873
868
  ehlo_respond (retval, msg) {
874
- const self = this;
875
869
 
876
870
  switch (retval) {
877
871
  case constants.deny:
878
872
  this.respond(550, msg || "EHLO denied", () => {
879
- self.set('hello', 'verb', null);
880
- self.set('hello', 'host', null);
873
+ this.set('hello', 'verb', null);
874
+ this.set('hello', 'host', null);
881
875
  });
882
876
  break;
883
877
  case constants.denydisconnect:
884
878
  this.respond(550, msg || "EHLO denied", () => {
885
- self.disconnect();
879
+ this.disconnect();
886
880
  });
887
881
  break;
888
882
  case constants.denysoft:
889
883
  this.respond(450, msg || "EHLO denied", () => {
890
- self.set('hello', 'verb', null);
891
- self.set('hello', 'host', null);
884
+ this.set('hello', 'verb', null);
885
+ this.set('hello', 'host', null);
892
886
  });
893
887
  break;
894
888
  case constants.denysoftdisconnect:
895
889
  this.respond(450, msg || "EHLO denied", () => {
896
- self.disconnect();
890
+ this.disconnect();
897
891
  });
898
892
  break;
899
893
  default: {
@@ -923,32 +917,30 @@ class Connection {
923
917
  this.respond(250, this.capabilities);
924
918
  }
925
919
  quit_respond (retval, msg) {
926
- const self = this;
927
920
  this.respond(221, msg || `${this.local.host} ${this.connection_close_message}`, () => {
928
- self.disconnect();
921
+ this.disconnect();
929
922
  });
930
923
  }
931
924
  vrfy_respond (retval, msg) {
932
- const self = this;
933
925
  switch (retval) {
934
926
  case constants.deny:
935
927
  this.respond(550, msg || "Access Denied", () => {
936
- self.reset_transaction();
928
+ this.reset_transaction();
937
929
  });
938
930
  break;
939
931
  case constants.denydisconnect:
940
932
  this.respond(550, msg || "Access Denied", () => {
941
- self.disconnect();
933
+ this.disconnect();
942
934
  });
943
935
  break;
944
936
  case constants.denysoft:
945
937
  this.respond(450, msg || "Lookup Failed", () => {
946
- self.reset_transaction();
938
+ this.reset_transaction();
947
939
  });
948
940
  break;
949
941
  case constants.denysoftdisconnect:
950
942
  this.respond(450, msg || "Lookup Failed", () => {
951
- self.disconnect();
943
+ this.disconnect();
952
944
  });
953
945
  break;
954
946
  case constants.ok:
@@ -959,14 +951,13 @@ class Connection {
959
951
  }
960
952
  }
961
953
  noop_respond (retval, msg) {
962
- const self = this;
963
954
  switch (retval) {
964
955
  case constants.deny:
965
956
  this.respond(500, msg || "Stop wasting my time");
966
957
  break;
967
958
  case constants.denydisconnect:
968
959
  this.respond(500, msg || "Stop wasting my time", () => {
969
- self.disconnect();
960
+ this.disconnect();
970
961
  });
971
962
  break;
972
963
  default:
@@ -974,10 +965,8 @@ class Connection {
974
965
  }
975
966
  }
976
967
  rset_respond (retval, msg) {
977
- // We ignore any plugin responses
978
- const self = this;
979
968
  this.respond(250, "OK", () => {
980
- self.reset_transaction();
969
+ this.reset_transaction();
981
970
  })
982
971
  }
983
972
  mail_respond (retval, msg) {
@@ -1062,9 +1051,8 @@ class Connection {
1062
1051
  this.transaction.results.push({name: 'rcpt_to'}, { recipient });
1063
1052
  }
1064
1053
  rcpt_ok_respond (retval, msg) {
1065
- const self = this;
1066
1054
  if (!this.transaction) {
1067
- self.results.add(this, {err: 'rcpt_ok_respond found no transaction'});
1055
+ this.results.add(this, {err: 'rcpt_ok_respond found no transaction'});
1068
1056
  return;
1069
1057
  }
1070
1058
  if (!msg) msg = this.last_rcpt_msg;
@@ -1082,31 +1070,31 @@ class Connection {
1082
1070
  switch (retval) {
1083
1071
  case constants.deny:
1084
1072
  this.respond(550, msg || `${dmsg} denied`, () => {
1085
- self.rcpt_incr(rcpt, 'reject', msg, retval);
1086
- self.transaction.rcpt_to.pop();
1073
+ this.rcpt_incr(rcpt, 'reject', msg, retval);
1074
+ this.transaction.rcpt_to.pop();
1087
1075
  });
1088
1076
  break;
1089
1077
  case constants.denydisconnect:
1090
1078
  this.respond(550, msg || `${dmsg} denied`, () => {
1091
- self.rcpt_incr(rcpt, 'reject', msg, retval);
1092
- self.disconnect();
1079
+ this.rcpt_incr(rcpt, 'reject', msg, retval);
1080
+ this.disconnect();
1093
1081
  });
1094
1082
  break;
1095
1083
  case constants.denysoft:
1096
1084
  this.respond(450, msg || `${dmsg} denied`, () => {
1097
- self.rcpt_incr(rcpt, 'tempfail', msg, retval);
1098
- self.transaction.rcpt_to.pop();
1085
+ this.rcpt_incr(rcpt, 'tempfail', msg, retval);
1086
+ this.transaction.rcpt_to.pop();
1099
1087
  });
1100
1088
  break;
1101
1089
  case constants.denysoftdisconnect:
1102
1090
  this.respond(450, msg || `${dmsg} denied`, () => {
1103
- self.rcpt_incr(rcpt, 'tempfail', msg, retval);
1104
- self.disconnect();
1091
+ this.rcpt_incr(rcpt, 'tempfail', msg, retval);
1092
+ this.disconnect();
1105
1093
  });
1106
1094
  break;
1107
1095
  default:
1108
1096
  this.respond(250, msg || `${dmsg} OK`, () => {
1109
- self.rcpt_incr(rcpt, 'accept', msg, retval);
1097
+ this.rcpt_incr(rcpt, 'accept', msg, retval);
1110
1098
  });
1111
1099
  }
1112
1100
  }
@@ -1115,7 +1103,6 @@ class Connection {
1115
1103
  retval = constants.ok;
1116
1104
  }
1117
1105
 
1118
- const self = this;
1119
1106
  if (!this.transaction) {
1120
1107
  this.results.add(this, {err: 'rcpt_respond found no transaction'});
1121
1108
  return;
@@ -1135,26 +1122,26 @@ class Connection {
1135
1122
  switch (retval) {
1136
1123
  case constants.deny:
1137
1124
  this.respond(550, msg || `${dmsg} denied`, () => {
1138
- self.rcpt_incr(rcpt, 'reject', msg, retval);
1139
- self.transaction.rcpt_to.pop();
1125
+ this.rcpt_incr(rcpt, 'reject', msg, retval);
1126
+ this.transaction.rcpt_to.pop();
1140
1127
  });
1141
1128
  break;
1142
1129
  case constants.denydisconnect:
1143
1130
  this.respond(550, msg || `${dmsg} denied`, () => {
1144
- self.rcpt_incr(rcpt, 'reject', msg, retval);
1145
- self.disconnect();
1131
+ this.rcpt_incr(rcpt, 'reject', msg, retval);
1132
+ this.disconnect();
1146
1133
  });
1147
1134
  break;
1148
1135
  case constants.denysoft:
1149
1136
  this.respond(450, msg || `${dmsg} denied`, () => {
1150
- self.rcpt_incr(rcpt, 'tempfail', msg, retval);
1151
- self.transaction.rcpt_to.pop();
1137
+ this.rcpt_incr(rcpt, 'tempfail', msg, retval);
1138
+ this.transaction.rcpt_to.pop();
1152
1139
  });
1153
1140
  break;
1154
1141
  case constants.denysoftdisconnect:
1155
1142
  this.respond(450, msg || `${dmsg} denied`, () => {
1156
- self.rcpt_incr(rcpt, 'tempfail', msg, retval);
1157
- self.disconnect();
1143
+ this.rcpt_incr(rcpt, 'tempfail', msg, retval);
1144
+ this.disconnect();
1158
1145
  });
1159
1146
  break;
1160
1147
  case constants.ok:
@@ -1168,8 +1155,8 @@ class Connection {
1168
1155
  }
1169
1156
  const rej_msg = `I cannot deliver mail for ${rcpt.format()}`;
1170
1157
  this.respond(550, rej_msg, () => {
1171
- self.rcpt_incr(rcpt, 'reject', rej_msg, retval);
1172
- self.transaction.rcpt_to.pop();
1158
+ this.rcpt_incr(rcpt, 'reject', rej_msg, retval);
1159
+ this.transaction.rcpt_to.pop();
1173
1160
  });
1174
1161
  }
1175
1162
  }
@@ -1178,7 +1165,6 @@ class Connection {
1178
1165
  // HAProxy support
1179
1166
 
1180
1167
  cmd_proxy (line) {
1181
- const self = this;
1182
1168
 
1183
1169
  if (!this.proxy.allowed) {
1184
1170
  this.respond(421, `PROXY not allowed from ${this.remote.ip}`);
@@ -1234,24 +1220,23 @@ class Connection {
1234
1220
  };
1235
1221
 
1236
1222
  this.reset_transaction(() => {
1237
- self.set('proxy.ip', self.remote.ip);
1238
- self.set('proxy.type', 'haproxy');
1239
- self.relaying = false;
1240
- self.set('local.ip', dst_ip);
1241
- self.set('local.port', parseInt(dst_port, 10));
1242
- self.set('remote.ip', src_ip);
1243
- self.set('remote.port', parseInt(src_port, 10));
1244
- self.set('remote.host', null);
1245
- self.set('hello.host', null);
1246
- plugins.run_hooks('connect_init', self);
1223
+ this.set('proxy.ip', this.remote.ip);
1224
+ this.set('proxy.type', 'haproxy');
1225
+ this.relaying = false;
1226
+ this.set('local.ip', dst_ip);
1227
+ this.set('local.port', parseInt(dst_port, 10));
1228
+ this.set('remote.ip', src_ip);
1229
+ this.set('remote.port', parseInt(src_port, 10));
1230
+ this.set('remote.host', null);
1231
+ this.set('hello.host', null);
1232
+ plugins.run_hooks('connect_init', this);
1247
1233
  });
1248
1234
  }
1249
1235
  /////////////////////////////////////////////////////////////////////////////
1250
1236
  // SMTP Commands
1251
1237
 
1252
1238
  cmd_internalcmd (line) {
1253
- const self = this;
1254
- if (!self.remote.is_local) {
1239
+ if (!this.remote.is_local) {
1255
1240
  return this.respond(501, "INTERNALCMD not allowed remotely");
1256
1241
  }
1257
1242
  const results = (String(line)).split(/ +/);
@@ -1276,7 +1261,6 @@ class Connection {
1276
1261
  return this.respond(250, "Command sent for execution. Check Haraka logs for results.");
1277
1262
  }
1278
1263
  cmd_helo (line) {
1279
- const self = this;
1280
1264
  const results = (String(line)).split(/ +/);
1281
1265
  const host = results[0];
1282
1266
  if (!host) {
@@ -1284,14 +1268,13 @@ class Connection {
1284
1268
  }
1285
1269
 
1286
1270
  this.reset_transaction(() => {
1287
- self.set('hello', 'verb', 'HELO');
1288
- self.set('hello', 'host', host);
1289
- self.results.add({ name: 'helo' }, self.hello);
1290
- plugins.run_hooks('helo', self, host);
1271
+ this.set('hello', 'verb', 'HELO');
1272
+ this.set('hello', 'host', host);
1273
+ this.results.add({ name: 'helo' }, this.hello);
1274
+ plugins.run_hooks('helo', this, host);
1291
1275
  });
1292
1276
  }
1293
1277
  cmd_ehlo (line) {
1294
- const self = this;
1295
1278
  const results = (String(line)).split(/ +/);
1296
1279
  const host = results[0];
1297
1280
  if (!host) {
@@ -1299,10 +1282,10 @@ class Connection {
1299
1282
  }
1300
1283
 
1301
1284
  this.reset_transaction(() => {
1302
- self.set('hello', 'verb', 'EHLO');
1303
- self.set('hello', 'host', host);
1304
- self.results.add({ name: 'helo' }, self.hello);
1305
- plugins.run_hooks('ehlo', self, host);
1285
+ this.set('hello', 'verb', 'EHLO');
1286
+ this.set('hello', 'host', host);
1287
+ this.results.add({ name: 'helo' }, this.hello);
1288
+ plugins.run_hooks('ehlo', this, host);
1306
1289
  });
1307
1290
  }
1308
1291
  cmd_quit (args) {
@@ -1377,20 +1360,19 @@ class Connection {
1377
1360
  }
1378
1361
 
1379
1362
  // Handle SIZE extension
1380
- if (params && params.SIZE && params.SIZE > 0) {
1363
+ if (params?.SIZE && params.SIZE > 0) {
1381
1364
  if (this.max_bytes > 0 && params.SIZE > this.max_bytes) {
1382
1365
  return this.respond(550, 'Message too big!');
1383
1366
  }
1384
1367
  }
1385
1368
 
1386
- const self = this;
1387
1369
  this.init_transaction(() => {
1388
- self.transaction.mail_from = from;
1389
- if (self.hello.verb == 'HELO') {
1390
- self.transaction.encoding = 'binary';
1391
- self.encoding = 'binary';
1370
+ this.transaction.mail_from = from;
1371
+ if (this.hello.verb == 'HELO') {
1372
+ this.transaction.encoding = 'binary';
1373
+ this.encoding = 'binary';
1392
1374
  }
1393
- plugins.run_hooks('mail', self, [from, params]);
1375
+ plugins.run_hooks('mail', this, [from, params]);
1394
1376
  });
1395
1377
  }
1396
1378
  cmd_rcpt (line) {
@@ -1466,7 +1448,7 @@ class Connection {
1466
1448
  }
1467
1449
  auth_results (message) {
1468
1450
  // http://tools.ietf.org/search/rfc7001
1469
- const has_tran = !!((this.transaction && this.transaction.notes));
1451
+ const has_tran = !!((this.transaction?.notes));
1470
1452
 
1471
1453
  // initialize connection note
1472
1454
  if (!this.notes.authentication_results) {
@@ -1503,8 +1485,8 @@ class Connection {
1503
1485
  const ars = this.transaction.header.get_all('Authentication-Results');
1504
1486
  if (ars.length === 0) return;
1505
1487
 
1506
- for (let i=0; i < ars.length; i++) {
1507
- this.transaction.add_header('Original-Authentication-Results', ars[i]);
1488
+ for (const element of ars) {
1489
+ this.transaction.add_header('Original-Authentication-Results', element);
1508
1490
  }
1509
1491
  this.transaction.remove_header('Authentication-Results');
1510
1492
  this.logdebug("Authentication-Results moved to Original-Authentication-Results");
@@ -1534,27 +1516,26 @@ class Connection {
1534
1516
  plugins.run_hooks('data', this);
1535
1517
  }
1536
1518
  data_respond (retval, msg) {
1537
- const self = this;
1538
1519
  let cont = 0;
1539
1520
  switch (retval) {
1540
1521
  case constants.deny:
1541
1522
  this.respond(554, msg || "Message denied", () => {
1542
- self.reset_transaction();
1523
+ this.reset_transaction();
1543
1524
  });
1544
1525
  break;
1545
1526
  case constants.denydisconnect:
1546
1527
  this.respond(554, msg || "Message denied", () => {
1547
- self.disconnect();
1528
+ this.disconnect();
1548
1529
  });
1549
1530
  break;
1550
1531
  case constants.denysoft:
1551
1532
  this.respond(451, msg || "Message denied", () => {
1552
- self.reset_transaction();
1533
+ this.reset_transaction();
1553
1534
  });
1554
1535
  break;
1555
1536
  case constants.denysoftdisconnect:
1556
1537
  this.respond(451, msg || "Message denied", () => {
1557
- self.disconnect();
1538
+ this.disconnect();
1558
1539
  });
1559
1540
  break;
1560
1541
  default:
@@ -1565,12 +1546,11 @@ class Connection {
1565
1546
  // We already checked for MAIL/RCPT in cmd_data
1566
1547
  this.respond(354, "go ahead, make my day", () => {
1567
1548
  // OK... now we get the data
1568
- self.state = states.DATA;
1569
- self.transaction.data_bytes = 0;
1549
+ this.state = states.DATA;
1550
+ this.transaction.data_bytes = 0;
1570
1551
  });
1571
1552
  }
1572
1553
  accumulate_data (line) {
1573
- const self = this;
1574
1554
 
1575
1555
  this.transaction.data_bytes += line.length;
1576
1556
 
@@ -1579,7 +1559,7 @@ class Connection {
1579
1559
  line[0] === 0x2e &&
1580
1560
  line[1] === 0x0d &&
1581
1561
  line[2] === 0x0a) {
1582
- self.data_done();
1562
+ this.data_done();
1583
1563
  return;
1584
1564
  }
1585
1565
 
@@ -1589,7 +1569,7 @@ class Connection {
1589
1569
  line[1] === 0x0a) {
1590
1570
  this.lognotice('Client sent bare line-feed - .\\n rather than .\\r\\n');
1591
1571
  this.respond(451, "Bare line-feed; see http://haraka.github.io/barelf/", () => {
1592
- self.reset_transaction();
1572
+ this.reset_transaction();
1593
1573
  });
1594
1574
  return;
1595
1575
  }
@@ -1602,7 +1582,7 @@ class Connection {
1602
1582
  if (this.transaction.mime_part_count >= this.max_mime_parts) {
1603
1583
  this.logcrit("Possible DoS attempt - too many MIME parts");
1604
1584
  this.respond(554, "Transaction failed due to too many MIME parts", () => {
1605
- self.disconnect();
1585
+ this.disconnect();
1606
1586
  });
1607
1587
  return;
1608
1588
  }
@@ -1610,7 +1590,6 @@ class Connection {
1610
1590
  this.transaction.add_data(line);
1611
1591
  }
1612
1592
  data_done () {
1613
- const self = this;
1614
1593
  this.pause();
1615
1594
  this.totalbytes += this.transaction.data_bytes;
1616
1595
 
@@ -1624,7 +1603,7 @@ class Connection {
1624
1603
  if (this.transaction.header.get_all('received').length > this.cfg.headers.max_received) {
1625
1604
  this.logerror("Incoming message had too many Received headers");
1626
1605
  this.respond(550, "Too many received headers - possible mail loop", () => {
1627
- self.reset_transaction();
1606
+ this.reset_transaction();
1628
1607
  });
1629
1608
  return;
1630
1609
  }
@@ -1645,12 +1624,12 @@ class Connection {
1645
1624
  this.transaction.end_data(() => {
1646
1625
  // As this will be called asynchronously,
1647
1626
  // make sure we still have a transaction.
1648
- if (!self.transaction) return;
1627
+ if (!this.transaction) return;
1649
1628
  // Record the start time of this hook as we can't take too long
1650
1629
  // as the client will typically hang up after 2 to 3 minutes
1651
1630
  // despite the RFC mandating that 10 minutes should be allowed.
1652
- self.transaction.data_post_start = Date.now();
1653
- plugins.run_hooks('data_post', self);
1631
+ this.transaction.data_post_start = Date.now();
1632
+ plugins.run_hooks('data_post', this);
1654
1633
  });
1655
1634
  }
1656
1635
  data_post_respond (retval, msg) {
@@ -1673,34 +1652,33 @@ class Connection {
1673
1652
  this.transaction.remove_header('Authentication-Results');
1674
1653
  this.transaction.add_leading_header('Authentication-Results', ar_field);
1675
1654
  }
1676
- const self = this;
1677
1655
  switch (retval) {
1678
1656
  case constants.deny:
1679
1657
  this.respond(550, msg || "Message denied", () => {
1680
- self.msg_count.reject++;
1681
- self.transaction.msg_status = 'rejected';
1682
- self.reset_transaction(() => self.resume());
1658
+ this.msg_count.reject++;
1659
+ this.transaction.msg_status = 'rejected';
1660
+ this.reset_transaction(() => this.resume());
1683
1661
  });
1684
1662
  break;
1685
1663
  case constants.denydisconnect:
1686
1664
  this.respond(550, msg || "Message denied",() => {
1687
- self.msg_count.reject++;
1688
- self.transaction.msg_status = 'rejected';
1689
- self.disconnect();
1665
+ this.msg_count.reject++;
1666
+ this.transaction.msg_status = 'rejected';
1667
+ this.disconnect();
1690
1668
  });
1691
1669
  break;
1692
1670
  case constants.denysoft:
1693
1671
  this.respond(450, msg || "Message denied temporarily", () => {
1694
- self.msg_count.tempfail++;
1695
- self.transaction.msg_status = 'deferred';
1696
- self.reset_transaction(() => self.resume());
1672
+ this.msg_count.tempfail++;
1673
+ this.transaction.msg_status = 'deferred';
1674
+ this.reset_transaction(() => this.resume());
1697
1675
  });
1698
1676
  break;
1699
1677
  case constants.denysoftdisconnect:
1700
1678
  this.respond(450, msg || "Message denied temporarily",() => {
1701
- self.msg_count.tempfail++;
1702
- self.transaction.msg_status = 'deferred';
1703
- self.disconnect();
1679
+ this.msg_count.tempfail++;
1680
+ this.transaction.msg_status = 'deferred';
1681
+ this.disconnect();
1704
1682
  });
1705
1683
  break;
1706
1684
  default:
@@ -1713,10 +1691,9 @@ class Connection {
1713
1691
  }
1714
1692
  }
1715
1693
  max_data_exceeded_respond (retval, msg) {
1716
- const self = this;
1717
1694
  // TODO: Maybe figure out what to do with other return codes
1718
1695
  this.respond(retval === constants.denysoft ? 450 : 550, "Message too big!", () => {
1719
- self.reset_transaction();
1696
+ this.reset_transaction();
1720
1697
  });
1721
1698
  }
1722
1699
  queue_msg (retval, msg) {
@@ -1755,7 +1732,6 @@ class Connection {
1755
1732
  }
1756
1733
  }
1757
1734
  queue_outbound_respond (retval, msg) {
1758
- const self = this;
1759
1735
  if (!msg) msg = this.queue_msg(retval, msg) || 'Message Queued';
1760
1736
  this.store_queue_result(retval, msg);
1761
1737
  msg = `${msg} (${this.transaction.uuid})`;
@@ -1774,57 +1750,57 @@ class Connection {
1774
1750
  break;
1775
1751
  case constants.deny:
1776
1752
  this.respond(550, msg, () => {
1777
- self.msg_count.reject++;
1778
- self.transaction.msg_status = 'rejected';
1779
- self.reset_transaction(() => self.resume());
1753
+ this.msg_count.reject++;
1754
+ this.transaction.msg_status = 'rejected';
1755
+ this.reset_transaction(() => this.resume());
1780
1756
  });
1781
1757
  break;
1782
1758
  case constants.denydisconnect:
1783
1759
  this.respond(550, msg, () => {
1784
- self.msg_count.reject++;
1785
- self.transaction.msg_status = 'rejected';
1786
- self.disconnect();
1760
+ this.msg_count.reject++;
1761
+ this.transaction.msg_status = 'rejected';
1762
+ this.disconnect();
1787
1763
  });
1788
1764
  break;
1789
1765
  case constants.denysoft:
1790
1766
  this.respond(450, msg, () => {
1791
- self.msg_count.tempfail++;
1792
- self.transaction.msg_status = 'deferred';
1793
- self.reset_transaction(() => self.resume());
1767
+ this.msg_count.tempfail++;
1768
+ this.transaction.msg_status = 'deferred';
1769
+ this.reset_transaction(() => this.resume());
1794
1770
  });
1795
1771
  break;
1796
1772
  case constants.denysoftdisconnect:
1797
1773
  this.respond(450, msg, () => {
1798
- self.msg_count.tempfail++;
1799
- self.transaction.msg_status = 'deferred';
1800
- self.disconnect();
1774
+ this.msg_count.tempfail++;
1775
+ this.transaction.msg_status = 'deferred';
1776
+ this.disconnect();
1801
1777
  });
1802
1778
  break;
1803
1779
  default:
1804
1780
  outbound.send_email(this.transaction, (retval2, msg2) => {
1805
- if (!msg2) msg2 = self.queue_msg(retval2, msg);
1781
+ if (!msg2) msg2 = this.queue_msg(retval2, msg);
1806
1782
  switch (retval2) {
1807
1783
  case constants.ok:
1808
- if (!msg2) msg2 = self.queue_msg(retval2, msg2);
1809
- plugins.run_hooks('queue_ok', self, msg2);
1784
+ if (!msg2) msg2 = this.queue_msg(retval2, msg2);
1785
+ plugins.run_hooks('queue_ok', this, msg2);
1810
1786
  break;
1811
1787
  case constants.deny:
1812
- if (!msg2) msg2 = self.queue_msg(retval2, msg2);
1813
- self.respond(550, msg2, () => {
1814
- self.msg_count.reject++;
1815
- self.transaction.msg_status = 'rejected';
1816
- self.reset_transaction(() => {
1817
- self.resume();
1788
+ if (!msg2) msg2 = this.queue_msg(retval2, msg2);
1789
+ this.respond(550, msg2, () => {
1790
+ this.msg_count.reject++;
1791
+ this.transaction.msg_status = 'rejected';
1792
+ this.reset_transaction(() => {
1793
+ this.resume();
1818
1794
  });
1819
1795
  });
1820
1796
  break;
1821
1797
  default:
1822
- self.logerror(`Unrecognized response from outbound layer: ${retval2} : ${msg2}`);
1823
- self.respond(550, msg2 || "Internal Server Error", () => {
1824
- self.msg_count.reject++;
1825
- self.transaction.msg_status = 'rejected';
1826
- self.reset_transaction(() => {
1827
- self.resume();
1798
+ this.logerror(`Unrecognized response from outbound layer: ${retval2} : ${msg2}`);
1799
+ this.respond(550, msg2 || "Internal Server Error", () => {
1800
+ this.msg_count.reject++;
1801
+ this.transaction.msg_status = 'rejected';
1802
+ this.reset_transaction(() => {
1803
+ this.resume();
1828
1804
  });
1829
1805
  });
1830
1806
  }
@@ -1832,7 +1808,6 @@ class Connection {
1832
1808
  }
1833
1809
  }
1834
1810
  queue_respond (retval, msg) {
1835
- const self = this;
1836
1811
  if (!msg) msg = this.queue_msg(retval, msg);
1837
1812
  this.store_queue_result(retval, msg);
1838
1813
  msg = `${msg} (${this.transaction.uuid})`;
@@ -1852,44 +1827,43 @@ class Connection {
1852
1827
  break;
1853
1828
  case constants.deny:
1854
1829
  this.respond(550, msg, () => {
1855
- self.msg_count.reject++;
1856
- self.transaction.msg_status = 'rejected';
1857
- self.reset_transaction(() => self.resume());
1830
+ this.msg_count.reject++;
1831
+ this.transaction.msg_status = 'rejected';
1832
+ this.reset_transaction(() => this.resume());
1858
1833
  });
1859
1834
  break;
1860
1835
  case constants.denydisconnect:
1861
1836
  this.respond(550, msg, () => {
1862
- self.msg_count.reject++;
1863
- self.transaction.msg_status = 'rejected';
1864
- self.disconnect();
1837
+ this.msg_count.reject++;
1838
+ this.transaction.msg_status = 'rejected';
1839
+ this.disconnect();
1865
1840
  });
1866
1841
  break;
1867
1842
  case constants.denysoft:
1868
1843
  this.respond(450, msg, () => {
1869
- self.msg_count.tempfail++;
1870
- self.transaction.msg_status = 'deferred';
1871
- self.reset_transaction(() => self.resume());
1844
+ this.msg_count.tempfail++;
1845
+ this.transaction.msg_status = 'deferred';
1846
+ this.reset_transaction(() => this.resume());
1872
1847
  });
1873
1848
  break;
1874
1849
  case constants.denysoftdisconnect:
1875
1850
  this.respond(450, msg, () => {
1876
- self.msg_count.tempfail++;
1877
- self.transaction.msg_status = 'deferred';
1878
- self.disconnect();
1851
+ this.msg_count.tempfail++;
1852
+ this.transaction.msg_status = 'deferred';
1853
+ this.disconnect();
1879
1854
  });
1880
1855
  break;
1881
1856
  default:
1882
1857
  if (!msg) msg = 'Queuing declined or disabled, try later';
1883
1858
  this.respond(451, msg, () => {
1884
- self.msg_count.tempfail++;
1885
- self.transaction.msg_status = 'deferred';
1886
- self.reset_transaction(() => self.resume());
1859
+ this.msg_count.tempfail++;
1860
+ this.transaction.msg_status = 'deferred';
1861
+ this.reset_transaction(() => this.resume());
1887
1862
  });
1888
1863
  break;
1889
1864
  }
1890
1865
  }
1891
1866
  queue_ok_respond (retval, msg, params) {
1892
- const self = this;
1893
1867
  // This hook is common to both hook_queue and hook_queue_outbound
1894
1868
  // retval and msg are ignored in this hook so we always log OK
1895
1869
  this.lognotice(
@@ -1901,9 +1875,9 @@ class Connection {
1901
1875
  );
1902
1876
 
1903
1877
  this.respond(250, params, () => {
1904
- self.msg_count.accept++;
1905
- if (self.transaction) self.transaction.msg_status = 'accepted';
1906
- self.reset_transaction(() => self.resume());
1878
+ this.msg_count.accept++;
1879
+ if (this.transaction) this.transaction.msg_status = 'accepted';
1880
+ this.reset_transaction(() => this.resume());
1907
1881
  });
1908
1882
  }
1909
1883
  }