sisimai 5.1.0-java → 5.2.0-java

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 (192) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake-test.yml +1 -1
  3. data/ChangeLog.md +102 -0
  4. data/Makefile +4 -2
  5. data/README-JA.md +23 -16
  6. data/README.md +22 -15
  7. data/lib/sisimai/arf.rb +121 -210
  8. data/lib/sisimai/fact.rb +208 -158
  9. data/lib/sisimai/lda.rb +98 -0
  10. data/lib/sisimai/lhost/activehunter.rb +1 -1
  11. data/lib/sisimai/lhost/amazonses.rb +185 -301
  12. data/lib/sisimai/lhost/apachejames.rb +48 -51
  13. data/lib/sisimai/lhost/biglobe.rb +1 -2
  14. data/lib/sisimai/lhost/courier.rb +10 -8
  15. data/lib/sisimai/lhost/domino.rb +25 -25
  16. data/lib/sisimai/lhost/dragonfly.rb +3 -4
  17. data/lib/sisimai/lhost/einsundeins.rb +3 -4
  18. data/lib/sisimai/lhost/exchange2003.rb +6 -8
  19. data/lib/sisimai/lhost/exchange2007.rb +111 -101
  20. data/lib/sisimai/lhost/exim.rb +232 -242
  21. data/lib/sisimai/lhost/ezweb.rb +43 -51
  22. data/lib/sisimai/lhost/fml.rb +2 -3
  23. data/lib/sisimai/lhost/gmail.rb +32 -28
  24. data/lib/sisimai/lhost/gmx.rb +4 -16
  25. data/lib/sisimai/lhost/googlegroups.rb +9 -8
  26. data/lib/sisimai/lhost/googleworkspace.rb +94 -0
  27. data/lib/sisimai/lhost/imailserver.rb +7 -16
  28. data/lib/sisimai/lhost/interscanmss.rb +1 -1
  29. data/lib/sisimai/lhost/kddi.rb +3 -4
  30. data/lib/sisimai/lhost/mailfoundry.rb +2 -5
  31. data/lib/sisimai/lhost/mailmarshalsmtp.rb +1 -2
  32. data/lib/sisimai/lhost/messagingserver.rb +14 -13
  33. data/lib/sisimai/lhost/mfilter.rb +4 -3
  34. data/lib/sisimai/lhost/notes.rb +2 -4
  35. data/lib/sisimai/lhost/opensmtpd.rb +2 -2
  36. data/lib/sisimai/lhost/postfix.rb +25 -27
  37. data/lib/sisimai/lhost/qmail.rb +130 -106
  38. data/lib/sisimai/lhost/sendmail.rb +19 -18
  39. data/lib/sisimai/lhost/v5sendmail.rb +88 -60
  40. data/lib/sisimai/lhost/verizon.rb +2 -2
  41. data/lib/sisimai/lhost/x1.rb +1 -1
  42. data/lib/sisimai/lhost/x2.rb +1 -2
  43. data/lib/sisimai/lhost/x3.rb +2 -2
  44. data/lib/sisimai/lhost/x6.rb +1 -1
  45. data/lib/sisimai/lhost/zoho.rb +2 -2
  46. data/lib/sisimai/lhost.rb +18 -21
  47. data/lib/sisimai/message.rb +93 -146
  48. data/lib/sisimai/order.rb +21 -77
  49. data/lib/sisimai/reason/authfailure.rb +1 -4
  50. data/lib/sisimai/reason/badreputation.rb +2 -2
  51. data/lib/sisimai/reason/blocked.rb +7 -10
  52. data/lib/sisimai/reason/contenterror.rb +7 -1
  53. data/lib/sisimai/reason/exceedlimit.rb +1 -4
  54. data/lib/sisimai/reason/failedstarttls.rb +42 -0
  55. data/lib/sisimai/reason/filtered.rb +5 -4
  56. data/lib/sisimai/reason/hasmoved.rb +1 -2
  57. data/lib/sisimai/reason/hostunknown.rb +3 -3
  58. data/lib/sisimai/reason/mailboxfull.rb +2 -4
  59. data/lib/sisimai/reason/mailererror.rb +1 -2
  60. data/lib/sisimai/reason/mesgtoobig.rb +2 -4
  61. data/lib/sisimai/reason/norelaying.rb +2 -3
  62. data/lib/sisimai/reason/notaccept.rb +2 -3
  63. data/lib/sisimai/reason/notcompliantrfc.rb +10 -4
  64. data/lib/sisimai/reason/rejected.rb +1 -1
  65. data/lib/sisimai/reason/requireptr.rb +2 -2
  66. data/lib/sisimai/reason/securityerror.rb +1 -3
  67. data/lib/sisimai/reason/spamdetected.rb +6 -8
  68. data/lib/sisimai/reason/speeding.rb +1 -2
  69. data/lib/sisimai/reason/suppressed.rb +36 -0
  70. data/lib/sisimai/reason/suspend.rb +1 -3
  71. data/lib/sisimai/reason/systemerror.rb +5 -0
  72. data/lib/sisimai/reason/toomanyconn.rb +1 -2
  73. data/lib/sisimai/reason/userunknown.rb +1 -1
  74. data/lib/sisimai/reason/virusdetected.rb +5 -6
  75. data/lib/sisimai/reason.rb +77 -73
  76. data/lib/sisimai/rfc1123.rb +152 -0
  77. data/lib/sisimai/rfc1894.rb +102 -62
  78. data/lib/sisimai/rfc2045.rb +2 -1
  79. data/lib/sisimai/rfc3464/thirdparty.rb +102 -0
  80. data/lib/sisimai/rfc3464.rb +222 -343
  81. data/lib/sisimai/rfc3834.rb +1 -1
  82. data/lib/sisimai/rfc5322.rb +7 -17
  83. data/lib/sisimai/rfc791.rb +69 -0
  84. data/lib/sisimai/rhost/aol.rb +36 -0
  85. data/lib/sisimai/rhost/apple.rb +5 -2
  86. data/lib/sisimai/rhost/cox.rb +3 -2
  87. data/lib/sisimai/rhost/facebook.rb +100 -0
  88. data/lib/sisimai/rhost/franceptt.rb +3 -2
  89. data/lib/sisimai/rhost/godaddy.rb +3 -2
  90. data/lib/sisimai/rhost/google.rb +19 -17
  91. data/lib/sisimai/rhost/gsuite.rb +42 -0
  92. data/lib/sisimai/rhost/iua.rb +3 -3
  93. data/lib/sisimai/rhost/kddi.rb +3 -2
  94. data/lib/sisimai/rhost/messagelabs.rb +37 -0
  95. data/lib/sisimai/rhost/microsoft.rb +56 -49
  96. data/lib/sisimai/rhost/mimecast.rb +29 -27
  97. data/lib/sisimai/rhost/nttdocomo.rb +4 -3
  98. data/lib/sisimai/rhost/outlook.rb +36 -0
  99. data/lib/sisimai/rhost/spectrum.rb +3 -2
  100. data/lib/sisimai/rhost/tencent.rb +3 -2
  101. data/lib/sisimai/rhost/yahooinc.rb +4 -3
  102. data/lib/sisimai/rhost.rb +69 -39
  103. data/lib/sisimai/smtp/command.rb +31 -21
  104. data/lib/sisimai/smtp/failure.rb +103 -0
  105. data/lib/sisimai/smtp/reply.rb +29 -25
  106. data/lib/sisimai/smtp/status.rb +36 -19
  107. data/lib/sisimai/smtp/transcript.rb +15 -15
  108. data/lib/sisimai/string.rb +0 -46
  109. data/lib/sisimai/version.rb +1 -1
  110. data/set-of-emails/maildir/bsd/lhost-postfix-30.eml +81 -81
  111. data/set-of-emails/maildir/bsd/{lhost-aol-03.eml → rhost-aol-03.eml} +1264 -1264
  112. data/set-of-emails/maildir/bsd/{lhost-aol-04.eml → rhost-aol-04.eml} +1260 -1260
  113. data/set-of-emails/maildir/bsd/{lhost-aol-05.eml → rhost-aol-05.eml} +105 -105
  114. data/set-of-emails/maildir/bsd/{lhost-aol-06.eml → rhost-aol-06.eml} +105 -105
  115. data/set-of-emails/maildir/bsd/rhost-gsuite-01.eml +189 -0
  116. data/set-of-emails/maildir/bsd/rhost-gsuite-02.eml +180 -0
  117. data/set-of-emails/maildir/bsd/rhost-gsuite-03.eml +251 -0
  118. data/set-of-emails/maildir/bsd/rhost-gsuite-04.eml +211 -0
  119. data/set-of-emails/maildir/bsd/rhost-gsuite-05.eml +226 -0
  120. data/set-of-emails/maildir/bsd/rhost-gsuite-06.eml +257 -0
  121. data/set-of-emails/maildir/bsd/rhost-gsuite-07.eml +289 -0
  122. data/set-of-emails/maildir/bsd/rhost-gsuite-08.eml +231 -0
  123. data/set-of-emails/maildir/bsd/rhost-gsuite-09.eml +231 -0
  124. data/set-of-emails/maildir/bsd/rhost-gsuite-10.eml +254 -0
  125. data/set-of-emails/maildir/bsd/rhost-gsuite-11.eml +228 -0
  126. data/set-of-emails/maildir/bsd/rhost-gsuite-12.eml +271 -0
  127. data/set-of-emails/maildir/bsd/rhost-gsuite-13.eml +261 -0
  128. data/set-of-emails/maildir/bsd/rhost-gsuite-14.eml +273 -0
  129. data/set-of-emails/maildir/bsd/rhost-gsuite-15.eml +229 -0
  130. data/set-of-emails/maildir/bsd/{lhost-messagelabs-01.eml → rhost-messagelabs-01.eml} +93 -93
  131. data/set-of-emails/maildir/bsd/rhost-outlook-01.eml +72 -0
  132. data/set-of-emails/maildir/bsd/rhost-outlook-02.eml +72 -0
  133. data/set-of-emails/maildir/bsd/rhost-outlook-03.eml +72 -0
  134. data/set-of-emails/maildir/bsd/rhost-outlook-04.eml +79 -0
  135. data/set-of-emails/maildir/bsd/rhost-outlook-06.eml +75 -0
  136. data/set-of-emails/maildir/bsd/rhost-outlook-07.eml +70 -0
  137. data/set-of-emails/maildir/bsd/rhost-outlook-08.eml +70 -0
  138. data/set-of-emails/maildir/bsd/rhost-outlook-09.eml +56 -0
  139. data/set-of-emails/maildir/tmp/arf-22.eml +49 -0
  140. data/set-of-emails/maildir/tmp/arf-23.eml +49 -0
  141. data/set-of-emails/maildir/tmp/arf-24.eml +50 -0
  142. data/set-of-emails/maildir/tmp/lhost-exim-07.eml +28 -0
  143. metadata +73 -56
  144. data/lib/sisimai/lhost/amavis.rb +0 -163
  145. data/lib/sisimai/lhost/amazonworkmail.rb +0 -127
  146. data/lib/sisimai/lhost/aol.rb +0 -125
  147. data/lib/sisimai/lhost/barracuda.rb +0 -92
  148. data/lib/sisimai/lhost/bigfoot.rb +0 -125
  149. data/lib/sisimai/lhost/facebook.rb +0 -188
  150. data/lib/sisimai/lhost/gsuite.rb +0 -194
  151. data/lib/sisimai/lhost/mailru.rb +0 -214
  152. data/lib/sisimai/lhost/mcafee.rb +0 -109
  153. data/lib/sisimai/lhost/messagelabs.rb +0 -120
  154. data/lib/sisimai/lhost/mxlogic.rb +0 -198
  155. data/lib/sisimai/lhost/office365.rb +0 -252
  156. data/lib/sisimai/lhost/outlook.rb +0 -129
  157. data/lib/sisimai/lhost/powermta.rb +0 -118
  158. data/lib/sisimai/lhost/receivingses.rb +0 -126
  159. data/lib/sisimai/lhost/sendgrid.rb +0 -150
  160. data/lib/sisimai/lhost/surfcontrol.rb +0 -105
  161. data/lib/sisimai/lhost/x4.rb +0 -269
  162. data/lib/sisimai/lhost/x5.rb +0 -112
  163. data/lib/sisimai/lhost/yahoo.rb +0 -102
  164. data/lib/sisimai/lhost/yandex.rb +0 -118
  165. data/lib/sisimai/mda.rb +0 -121
  166. data/lib/sisimai/smtp/error.rb +0 -119
  167. /data/set-of-emails/maildir/bsd/{lhost-googlegroups-15.eml → lhost-googleworkspace-01.eml} +0 -0
  168. /data/set-of-emails/maildir/bsd/{lhost-x4-08.eml → lhost-x2-06.eml} +0 -0
  169. /data/set-of-emails/maildir/bsd/{lhost-gsuite-01.eml → rfc3464-51.eml} +0 -0
  170. /data/set-of-emails/maildir/bsd/{lhost-gsuite-03.eml → rfc3464-52.eml} +0 -0
  171. /data/set-of-emails/maildir/bsd/{lhost-gsuite-04.eml → rfc3464-53.eml} +0 -0
  172. /data/set-of-emails/maildir/bsd/{lhost-gsuite-05.eml → rfc3464-54.eml} +0 -0
  173. /data/set-of-emails/maildir/bsd/{lhost-gsuite-06.eml → rfc3464-55.eml} +0 -0
  174. /data/set-of-emails/maildir/bsd/{lhost-gsuite-07.eml → rfc3464-56.eml} +0 -0
  175. /data/set-of-emails/maildir/bsd/{lhost-gsuite-08.eml → rfc3464-57.eml} +0 -0
  176. /data/set-of-emails/maildir/bsd/{lhost-gsuite-09.eml → rfc3464-58.eml} +0 -0
  177. /data/set-of-emails/maildir/bsd/{lhost-gsuite-10.eml → rfc3464-59.eml} +0 -0
  178. /data/set-of-emails/maildir/bsd/{lhost-gsuite-11.eml → rfc3464-60.eml} +0 -0
  179. /data/set-of-emails/maildir/bsd/{lhost-gsuite-12.eml → rfc3464-61.eml} +0 -0
  180. /data/set-of-emails/maildir/bsd/{lhost-gsuite-13.eml → rfc3464-62.eml} +0 -0
  181. /data/set-of-emails/maildir/bsd/{lhost-gsuite-14.eml → rfc3464-63.eml} +0 -0
  182. /data/set-of-emails/maildir/bsd/{lhost-gsuite-15.eml → rfc3464-64.eml} +0 -0
  183. /data/set-of-emails/maildir/bsd/{lhost-gsuite-02.eml → rfc3464-65.eml} +0 -0
  184. /data/set-of-emails/maildir/bsd/{lhost-aol-01.eml → rhost-aol-01.eml} +0 -0
  185. /data/set-of-emails/maildir/bsd/{lhost-aol-02.eml → rhost-aol-02.eml} +0 -0
  186. /data/set-of-emails/maildir/bsd/{lhost-facebook-03.eml → rhost-facebook-03.eml} +0 -0
  187. /data/set-of-emails/maildir/bsd/{lhost-facebook-04.eml → rhost-facebook-04.eml} +0 -0
  188. /data/set-of-emails/maildir/bsd/{lhost-messagelabs-02.eml → rhost-messagelabs-02.eml} +0 -0
  189. /data/set-of-emails/maildir/bsd/{lhost-messagelabs-03.eml → rhost-messagelabs-03.eml} +0 -0
  190. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-37.eml +0 -0
  191. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-38.eml +0 -0
  192. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-39.eml +0 -0
@@ -1,7 +1,7 @@
1
1
  module Sisimai
2
2
  module Rhost
3
3
  # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Fact object as an argument
4
- # of get() method when the value of "rhost" of the object is *.protection.outlook.com. This class
4
+ # of find() method when the value of "rhost" of the object is *.protection.outlook.com. This class
5
5
  # is called only Sisimai::Fact class.
6
6
  #
7
7
  # https://technet.microsoft.com/en-us/library/bb232118
@@ -16,43 +16,10 @@ module Sisimai
16
16
  # - The sending message sent over IPv6 must pass either SPF or DKIM.
17
17
  ['4.7.26', 0, 0, 'must pass either spf or dkim validation, this message is not signed'],
18
18
 
19
- # - Records are DNSSEC authentic, but one or multiple of these scenarios occurred:
20
- # - The destination mail server's certificate doesn't match with what is expected per
21
- # the authentic TLSA record.
22
- # - Authentic TLSA record is misconfigured.
23
- # - Destination domain is being attacked.
24
- # - Any other DANE failure.
25
- # - This message usually indicates an issue on the destination email server. Check the
26
- # validity of recipient address and determine if the destination server is configured
27
- # correctly to receive messages.
28
- # - For more information about DANE, see: https://datatracker.ietf.org/doc/html/rfc7671
29
- ['4.7.323', 0, 0, 'tlsa-invalid: The domain failed dane validation'],
30
- ['5.7.323', 0, 0, 'tlsa-invalid: The domain failed dane validation'],
31
-
32
- # - The destination domain indicated it was DNSSEC-authentic, but Exchange Online was
33
- # not able to verify it as DNSSEC-authentic.
34
- ['4.7.324', 0, 0, 'dnssec-invalid: destination domain returned invalid dnssec records'],
35
- ['5.7.324', 0, 0, 'dnssec-invalid: destination domain returned invalid dnssec records'],
36
-
37
- # - This happens when the presented certificate identities (CN and SAN) of a destina-
38
- # tion SMTP target host don't match any of the domains or MX host.
39
- # - This message usually indicates an issue on the destination email server. Check the
40
- # validity of recipient address and determine if the destination server is configured
41
- # correctly to receive messages. For more information, see How SMTP DNS-based Authen-
42
- # tication of Named Entities (DANE) works to secure email communications.
43
- ['4.7.325', 0, 0, 'certificate-host-mismatch: remote certificate must have a common name or subject alternative name matching the hostname (dane)'],
44
- ['5.7.325', 0, 0, 'certificate-host-mismatch: remote certificate must have a common name or subject alternative name matching the hostname (dane)'],
45
-
46
19
  # - The destination email system uses SPF to validate inbound mail, and there's a prob-
47
20
  # lem with your SPF configuration.
48
21
  ['5.7.23', 0, 0, 'the message was rejected because of sender policy framework violation'],
49
22
 
50
- # - DNSSEC checks have passed, yet upon establishing the connection the destination
51
- # mail server provides a certificate that is expired.
52
- # - A valid X.509 certificate that isn't expired must be presented. X.509 certificates
53
- # must be renewed after their expiration, commonly annually.
54
- ['5.7.322', 0, 0, "certificate-expired: destination mail server's certificate is expired"],
55
-
56
23
  # - Access denied, sending domain [$SenderDomain] does not pass DMARC verification
57
24
  # - The sender's domain in the 5322.From address doesn't pass DMARC.
58
25
  ['5.7.509', 0, 0, 'does not pass dmarc verification'],
@@ -136,7 +103,6 @@ module Sisimai
136
103
 
137
104
  # Previous versions of Exchange Server ------------------------------------------------
138
105
  ['5.5.4', 0, 0, 'invalid domain name'],
139
- ['5.7.51', 0, 0, 'restrictdomainstoipaddresses or restrictdomainstocertificate'],
140
106
 
141
107
  # Undocumented error messages ---------------------------------------------------------
142
108
  # - 550 5.7.1 Unfortunately, messages from [10.0.2.5] weren't sent. Please contact your
@@ -216,6 +182,53 @@ module Sisimai
216
182
  # couldn't be delivered to the original sender.
217
183
  ['5.4.300', 0, 0, 'message expired'],
218
184
  ],
185
+ 'failedstarttls' => [
186
+ # Exchange Online ---------------------------------------------------------------------
187
+ # - DNSSEC checks have passed, yet upon connection, destination mail server doesn't re-
188
+ # spond to the STARTTLS command. The destination server responds to the STARTTLS com-
189
+ # mand, but the TLS handshake fails.
190
+ # - This message usually indicates an issue on the destination email server. Check the
191
+ # validity of the recipient address. Determine if the destination server is configur-
192
+ # ed correctly to receive the messages.
193
+ ['4.4.317', 0, 0, 'starttls is required to send mail'],
194
+ ['5.4.317', 0, 0, 'starttls is required to send mail'],
195
+
196
+ # - DNSSEC checks have passed, yet upon establishing the connection the destination
197
+ # mail server provides a certificate that is expired.
198
+ # - A valid X.509 certificate that isn't expired must be presented. X.509 certificates
199
+ # must be renewed after their expiration, commonly annually.
200
+ ['5.7.51', 0, 0, 'restrictdomainstoipaddresses or restrictdomainstocertificate'],
201
+ ['4.7.321', 0, 0, 'starttls-not-supported: destination mail server must support tls to receive mail'],
202
+ ['5.7.321', 0, 0, 'starttls-not-supported: destination mail server must support tls to receive mail'],
203
+ ['5.7.322', 0, 0, "certificate-expired: destination mail server's certificate is expired"],
204
+
205
+ # - Records are DNSSEC authentic, but one or multiple of these scenarios occurred:
206
+ # - The destination mail server's certificate doesn't match with what is expected per
207
+ # the authentic TLSA record.
208
+ # - Authentic TLSA record is misconfigured.
209
+ # - Destination domain is being attacked.
210
+ # - Any other DANE failure.
211
+ # - This message usually indicates an issue on the destination email server. Check the
212
+ # validity of recipient address and determine if the destination server is configured
213
+ # correctly to receive messages.
214
+ # - For more information about DANE, see: https://datatracker.ietf.org/doc/html/rfc7671
215
+ ['4.7.323', 0, 0, 'tlsa-invalid: The domain failed dane validation'],
216
+ ['5.7.323', 0, 0, 'tlsa-invalid: The domain failed dane validation'],
217
+
218
+ # - The destination domain indicated it was DNSSEC-authentic, but Exchange Online was
219
+ # not able to verify it as DNSSEC-authentic.
220
+ ['4.7.324', 0, 0, 'dnssec-invalid: destination domain returned invalid dnssec records'],
221
+ ['5.7.324', 0, 0, 'dnssec-invalid: destination domain returned invalid dnssec records'],
222
+
223
+ # - This happens when the presented certificate identities (CN and SAN) of a destina-
224
+ # tion SMTP target host don't match any of the domains or MX host.
225
+ # - This message usually indicates an issue on the destination email server. Check the
226
+ # validity of recipient address and determine if the destination server is configured
227
+ # correctly to receive messages. For more information, see How SMTP DNS-based Authen-
228
+ # tication of Named Entities (DANE) works to secure email communications.
229
+ ['4.7.325', 0, 0, 'certificate-host-mismatch: remote certificate must have a common name or subject alternative name matching the hostname (dane)'],
230
+ ['5.7.325', 0, 0, 'certificate-host-mismatch: remote certificate must have a common name or subject alternative name matching the hostname (dane)'],
231
+ ],
219
232
  'mailboxfull' => [
220
233
  # Exchange Server 2019 ----------------------------------------------------------------
221
234
  # - The recipient's mailbox has exceeded its storage quota and is no longer able to ac-
@@ -328,6 +341,7 @@ module Sisimai
328
341
  ],
329
342
  'notaccept' => [
330
343
  ['4.3.2', 0, 0, 'system not accepting network messages'],
344
+ ['4.4.4', 0, 0, 'hosted tenant which has no mail-enabled subscriptions'],
331
345
 
332
346
  # Exchange Server 2019 ----------------------------------------------------------------
333
347
  # - You're using the ABP Routing agent, and the recipient isn't a member of the global
@@ -448,19 +462,6 @@ module Sisimai
448
462
  ['5.7.3', 0, 0, 'cannot achieve exchange server authentication'],
449
463
  ['5.7.3', 0, 0, 'not authorized'],
450
464
 
451
- # Exchange Online ---------------------------------------------------------------------
452
- # - DNSSEC checks have passed, yet upon connection, destination mail server doesn't re-
453
- # spond to the STARTTLS command. The destination server responds to the STARTTLS com-
454
- # mand, but the TLS handshake fails.
455
- # - This message usually indicates an issue on the destination email server. Check the
456
- # validity of the recipient address. Determine if the destination server is configur-
457
- # ed correctly to receive the messages.
458
- ['4.4.317', 0, 0, 'starttls is required to send mail'],
459
- ['5.4.317', 0, 0, 'starttls is required to send mail'],
460
-
461
- ['4.7.321', 0, 0, 'starttls-not-supported: destination mail server must support tls to receive mail'],
462
- ['5.7.321', 0, 0, 'starttls-not-supported: destination mail server must support tls to receive mail'],
463
-
464
465
  # - The sending email system didn't authenticate with the receiving email system. The
465
466
  # receiving email system requires authentication before message submission.
466
467
  # - This error occurs when the receiving server must be authenticated before message
@@ -644,6 +645,12 @@ module Sisimai
644
645
  # envelope recipients into smaller chunks (chunking) and resend the message.
645
646
  ['4.5.3', 0, 0, 'too many recipients'],
646
647
 
648
+ # - 451 4.7.652 The mail server [192.0.2.251] has exceeded the maximum number of
649
+ # connections. (S3115) [Name=Protocol Filter Agent][AGT=PFA][MxId=11BA9B3FA168ABBF]
650
+ # [BN3PEPF0000B370.namprd21.prod.outlook.com 2025-02-20T14:30:32.425Z 08DD4D9FD5AFF45C]
651
+ # (in reply to MAIL FROM command))
652
+ ["4.7.652", 0, 0, "has exceeded the maximum number of connections"],
653
+
647
654
  # Previous versions of Exchange Server ------------------------------------------------
648
655
  ['5.2.122', 0, 0, 'the recipient has exceeded their limit for'],
649
656
  ],
@@ -714,7 +721,7 @@ module Sisimai
714
721
  # @param [Sisimai::Fact] argvs Decoded email object
715
722
  # @return [String] The bounce reason for Exchange Online
716
723
  # @since v4.17.2
717
- def get(argvs)
724
+ def find(argvs)
718
725
  return '' if argvs['deliverystatus'].empty?
719
726
  return '' unless Sisimai::SMTP::Status.test(argvs['deliverystatus'])
720
727
 
@@ -1,7 +1,7 @@
1
1
  module Sisimai
2
2
  module Rhost
3
3
  # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Fact object as an argu-
4
- # ment of get() method when the value of "rhost" of the object is "*.mimecast.com". This class
4
+ # ment of find() method when the value of "rhost" of the object is "*.mimecast.com". This class
5
5
  # is called only Sisimai::Fact class.
6
6
  module Mimecast
7
7
  class << self
@@ -76,6 +76,32 @@ module Sisimai
76
76
  # Discontinue journaling old messages past the expiry threshold.
77
77
  [550, 'Journal messages past the expiration'],
78
78
  ],
79
+ 'failedstarttls' => [
80
+ # - This email has been sent using SMTP, but TLS is required by policy.
81
+ # - Delete or change the Secure Receipt or Secure Delivery policy enforcing TLS.
82
+ # Alternatively, ensure the certificates on the mail server haven't expired. If using
83
+ # a proxy server, ensure it isn't intercepting the traffic and modifying encryption
84
+ # parameters.
85
+ [553, 'this route requires encryption (tls)'],
86
+
87
+ # - A TLS connection has been attempted using a TLS version that is lower than TLS 1.2.
88
+ # - Delete or change the Secure Receipt or Secure Delivery policy enforcing TLS.
89
+ # Alternatively, ensure the mail server attempting to connect is using the appropri-
90
+ # ate version of TLS.
91
+ [553, 'this route requires tls version 1.2 or greater'],
92
+
93
+ # - A secure connection was attempted using ciphers that do not meet the configured ci-
94
+ # pher strength.
95
+ # - Delete or change the Secure Receipt or Secure Delivery policy enforcing TLS. Alter-
96
+ # natively, ensure the certificates on the mail server haven't expired. If using a
97
+ # proxy server, ensure it isn't intercepting the traffic and modifying encryption
98
+ # parameters.
99
+ [553, 'this route requires high-strength ciphers'],
100
+
101
+ # - Validation on your umbrella account's domain name does not conform to your DNS.
102
+ # - Check you DNS has the required umbrella accounts listed as comma-separated values.
103
+ [554, 'configuration is invalid for this certificate'],
104
+ ],
79
105
  'mesgtoobig' => [
80
106
  # - The email size either exceeds an Email Size Limit policy or is larger than the
81
107
  # Mimecast service limit. The default is 100 MB for the Legacy MTA, and 200 MB for
@@ -172,31 +198,6 @@ module Sisimai
172
198
  [535, 'incorrect authentication data'],
173
199
  [550, 'submitter failed to disabled'],
174
200
  [550, 'submitter failed to authenticate'],
175
-
176
- # - This email has been sent using SMTP, but TLS is required by policy.
177
- # - Delete or change the Secure Receipt or Secure Delivery policy enforcing TLS.
178
- # Alternatively, ensure the certificates on the mail server haven't expired. If using
179
- # a proxy server, ensure it isn't intercepting the traffic and modifying encryption
180
- # parameters.
181
- [553, 'this route requires encryption (tls)'],
182
-
183
- # - A TLS connection has been attempted using a TLS version that is lower than TLS 1.2.
184
- # - Delete or change the Secure Receipt or Secure Delivery policy enforcing TLS.
185
- # Alternatively, ensure the mail server attempting to connect is using the appropri-
186
- # ate version of TLS.
187
- [553, 'this route requires tls version 1.2 or greater'],
188
-
189
- # - A secure connection was attempted using ciphers that do not meet the configured ci-
190
- # pher strength.
191
- # - Delete or change the Secure Receipt or Secure Delivery policy enforcing TLS. Alter-
192
- # natively, ensure the certificates on the mail server haven't expired. If using a
193
- # proxy server, ensure it isn't intercepting the traffic and modifying encryption
194
- # parameters.
195
- [553, 'this route requires high-strength ciphers'],
196
-
197
- # - Validation on your umbrella account's domain name does not conform to your DNS.
198
- # - Check you DNS has the required umbrella accounts listed as comma-separated values.
199
- [554, 'configuration is invalid for this certificate'],
200
201
  ],
201
202
  'systemerror' => [
202
203
  # - The Mimecast server is under maximum load.
@@ -281,7 +282,8 @@ module Sisimai
281
282
  # Detect bounce reason from Mimecast
282
283
  # @param [Sisimai::Fact] argvs Decoded email object
283
284
  # @return [String] The bounce reason for mimecast.com
284
- def get(argvs)
285
+ def find(argvs)
286
+ return argvs['reason'] unless argvs['reason'].empty?
285
287
  return '' unless Sisimai::SMTP::Reply.test(argvs['replycode'])
286
288
 
287
289
  issuedcode = argvs['diagnosticcode'].downcase || ''
@@ -1,7 +1,7 @@
1
1
  module Sisimai
2
2
  module Rhost
3
3
  # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Fact object as an argument
4
- # of get() method when the value of "rhost" of the object is "mfsmax.docomo.ne.jp". This class
4
+ # of find() method when the value of "rhost" of the object is "mfsmax.docomo.ne.jp". This class
5
5
  # is called only Sisimai::Fact class.
6
6
  module NTTDOCOMO
7
7
  class << self
@@ -14,9 +14,10 @@ module Sisimai
14
14
  # Detect bounce reason from NTT DOCOMO
15
15
  # @param [Sisimai::Fact] argvs Decoded email object
16
16
  # @return [String] The bounce reason for docomo.ne.jp
17
- def get(argvs)
17
+ def find(argvs)
18
+ return argvs['reason'] unless argvs['reason'].empty?
18
19
  statuscode = argvs['deliverystatus'] || ''
19
- thecommand = argvs['smtpcommand'] || ''
20
+ thecommand = argvs['command'] || ''
20
21
  esmtperror = argvs['diagnosticcode'].downcase || ''
21
22
  reasontext = ''
22
23
 
@@ -0,0 +1,36 @@
1
+ module Sisimai
2
+ module Rhost
3
+ # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Fact object as an argument
4
+ # of find() method when the value of "rhost" of the object is "*.hotmail.com". This class is called
5
+ # only from Sisimai::Fact class.
6
+ module Outlook
7
+ class << self
8
+ MessagesOf = {
9
+ "hostunknown" => ["The mail could not be delivered to the recipient because the domain is not reachable"],
10
+ "userunknown" => ["Requested action not taken: mailbox unavailable"],
11
+ }.freeze
12
+
13
+ # Detect bounce reason from Microsoft Outlook.com: https://www.outlook.com/
14
+ # @param [Sisimai::Fact] argvs Decoded email object
15
+ # @return [String] The bounce reason for Outlook
16
+ # @since v5.2.0
17
+ def find(argvs)
18
+ return "" if argvs["diagnosticcode"].empty?
19
+ issuedcode = argvs["diagnosticcode"]
20
+ reasontext = ""
21
+
22
+ MessagesOf.each_key do |e|
23
+ # Try to match the error message with message patterns defined in $MessagesOf
24
+ next unless MessagesOf[e].any? { |a| issuedcode.include?(a) }
25
+ reasontext = e
26
+ break
27
+ end
28
+
29
+ return reasontext
30
+ end
31
+
32
+ end
33
+ end
34
+ end
35
+ end
36
+
@@ -1,7 +1,7 @@
1
1
  module Sisimai
2
2
  module Rhost
3
3
  # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Fact object as an argument
4
- # of get() method when the value of "destination" of the object is "charter.net". This class is
4
+ # of find() method when the value of "destination" of the object is "charter.net". This class is
5
5
  # called only Sisimai::Fact class.
6
6
  module Spectrum
7
7
  class << self
@@ -100,7 +100,8 @@ module Sisimai
100
100
  # @param [Sisimai::Fact] argvs Decoded email object
101
101
  # @return [String, Nil] The bounce reason at Spectrum
102
102
  # @since v4.25.8
103
- def get(argvs)
103
+ def find(argvs)
104
+ return argvs['reason'] unless argvs['reason'].empty?
104
105
  issuedcode = argvs['diagnosticcode']
105
106
  reasontext = ''
106
107
  codenumber = if cv = issuedcode.match(/AUP#[-A-Za-z]*(\d{4})/) then cv[1].to_i else 0 end
@@ -1,7 +1,7 @@
1
1
  module Sisimai
2
2
  module Rhost
3
3
  # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Fact object as an argument
4
- # of get() method when the value of "rhost" of the object is "mx*.qq.com". This class is called
4
+ # of find() method when the value of "rhost" of the object is "mx*.qq.com". This class is called
5
5
  # only Sisimai::Fact class.
6
6
  module Tencent
7
7
  class << self
@@ -49,7 +49,8 @@ module Sisimai
49
49
  # Detect bounce reason from Tencent QQ
50
50
  # @param [Sisimai::Fact] argvs Decoded email object
51
51
  # @return [String] The bounce reason at Tencent QQ
52
- def get(argvs)
52
+ def find(argvs)
53
+ return argvs['reason'] unless argvs['reason'].empty?
53
54
  issuedcode = argvs['diagnosticcode'].downcase
54
55
  reasontext = ''
55
56
 
@@ -1,7 +1,7 @@
1
1
  module Sisimai
2
2
  module Rhost
3
3
  # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Fact object as an argument
4
- # of get() method when the value of "destination" of the object is "*.yahoodns.net".
4
+ # of find() method when the value of "destination" of the object is "*.yahoodns.net".
5
5
  # This class is called only Sisimai::Fact class.
6
6
  module YahooInc
7
7
  class << self
@@ -23,7 +23,7 @@ module Sisimai
23
23
  # - 550 relaying denied for <***@yahoo.com>
24
24
  'relaying denied for ',
25
25
  ],
26
- 'notcomplaintrfc' => ['headers are not rfc compliant'],
26
+ 'notcompliantrfc' => ['headers are not rfc compliant'],
27
27
  'policyviolation' => [
28
28
  # - 554 Message not allowed - [PH01] Email not accepted for policy reasons.
29
29
  # Please visit https://postmaster.yahooinc.com/error-codes
@@ -87,7 +87,8 @@ module Sisimai
87
87
  # https://smtpfieldmanual.com/provider/yahoo
88
88
  # https://www.postmastery.com/yahoo-postmaster/
89
89
  # @since v5.1.0
90
- def get(argvs)
90
+ def find(argvs)
91
+ return argvs['reason'] unless argvs['reason'].empty?
91
92
  issuedcode = argvs['diagnosticcode'].downcase
92
93
  reasontext = ''
93
94
 
data/lib/sisimai/rhost.rb CHANGED
@@ -1,54 +1,84 @@
1
1
  module Sisimai
2
2
  # Sisimai::Rhost detects the bounce reason from the content of Sisimai::Fact object as an argument
3
- # of get() method when the value of rhost of the object is listed in the results of Sisimai::Rhost
3
+ # of find() method when the value of rhost of the object is listed in the results of Sisimai::Rhost
4
4
  # ->list method. This class is called only Sisimai::Fact class.
5
5
  module Rhost
6
6
  class << self
7
7
  RhostClass = {
8
- 'Apple' => ['.mail.icloud.com', '.apple.com', '.me.com'],
9
- 'Cox' => ['cox.net'],
10
- 'FrancePTT' => ['.laposte.net', '.orange.fr', '.wanadoo.fr'],
11
- 'GoDaddy' => ['smtp.secureserver.net', 'mailstore1.secureserver.net'],
12
- 'Google' => ['aspmx.l.google.com', 'gmail-smtp-in.l.google.com'],
13
- 'IUA' => ['.email.ua'],
14
- 'KDDI' => ['.ezweb.ne.jp', 'msmx.au.com'],
15
- 'Microsoft' => ['.prod.outlook.com', '.protection.outlook.com'],
16
- 'Mimecast' => ['.mimecast.com'],
17
- 'NTTDOCOMO' => ['mfsmax.docomo.ne.jp'],
18
- 'Spectrum' => ['charter.net'],
19
- 'Tencent' => ['.qq.com'],
20
- 'YahooInc' => ['.yahoodns.net'],
8
+ "Aol" => [".mail.aol.com", ".mx.aol.com"],
9
+ "Apple" => [".mail.icloud.com", ".apple.com", ".me.com"],
10
+ "Cox" => ["cox.net"],
11
+ "Facebook" => [".facebook.com"],
12
+ "FrancePTT" => [".laposte.net", ".orange.fr", ".wanadoo.fr"],
13
+ "GoDaddy" => ["smtp.secureserver.net", "mailstore1.secureserver.net"],
14
+ "Google" => ["aspmx.l.google.com", "gmail-smtp-in.l.google.com"],
15
+ "GSuite" => ["googlemail.com"],
16
+ "IUA" => [".email.ua"],
17
+ "KDDI" => [".ezweb.ne.jp", "msmx.au.com"],
18
+ "MessageLabs" => [".messagelabs.com"],
19
+ "Microsoft" => [".prod.outlook.com", ".protection.outlook.com", ".onmicrosoft.com", ".exchangelabs.com"],
20
+ "Mimecast" => [".mimecast.com"],
21
+ "NTTDOCOMO" => ["mfsmax.docomo.ne.jp"],
22
+ "Outlook" => [".hotmail.com"],
23
+ "Spectrum" => ["charter.net"],
24
+ "Tencent" => [".qq.com"],
25
+ "YahooInc" => [".yahoodns.net"],
21
26
  }.freeze
22
27
 
28
+ # Returns the rhost class name
29
+ # @param [Hash] argvs Decoded email data
30
+ # @return [String] rhost class name
31
+ def name(argvs)
32
+ return "" if argvs.nil?
33
+
34
+ rhostclass = ""
35
+ clienthost = argvs["lhost"].downcase
36
+ remotehost = argvs["rhost"].downcase
37
+ domainpart = argvs["destination"].downcase
38
+
39
+ catch :FINDRHOST do
40
+ # Try to match the hostname patterns with the following order:
41
+ # 1. destination: The domain part of the recipient address
42
+ # 2. rhost: remote hostname
43
+ # 3. lhost: local MTA hostname
44
+ RhostClass.each_key do |e|
45
+ # Try to match the domain part of the recipient address with each value of RhostClass
46
+ next unless RhostClass[e].any? { |a| a.end_with?(domainpart) }
47
+ rhostclass = e
48
+ throw :FINDRHOST
49
+ end
50
+
51
+ RhostClass.each_key do |e|
52
+ # Try to match the remote host with each value of RhostClass
53
+ next unless RhostClass[e].any? { |a| remotehost.end_with?(a) }
54
+ rhostclass = e
55
+ throw :FINDRHOST
56
+ end
57
+
58
+ # Neither the remote host nor the destination did not matched with any value of RhostClass
59
+ RhostClass.each_key do |e|
60
+ # Try to match the client host with each value of RhostClass
61
+ next unless RhostClass[e].any? { |a| clienthost.end_with?(a) }
62
+ rhostclass = e
63
+ throw :FINDRHOST
64
+ end
65
+ end
66
+ return rhostclass
67
+ end
68
+
23
69
  # Detect the bounce reason from certain remote hosts
24
70
  # @param [Hash] argvs Decoded email data
25
71
  # @return [String] The value of bounce reason
26
- def get(argvs)
27
- return nil if argvs['diagnosticcode'].empty?
28
-
29
- remotehost = argvs['rhost'].downcase
30
- domainpart = argvs['destination'].downcase
31
- return nil if (remotehost + domainpart).empty?
32
-
33
- rhostmatch = nil
34
- rhostclass = ''
35
- modulename = ''
36
-
37
- RhostClass.each_key do |e|
38
- # Try to match with each value of RhostClass
39
- rhostmatch = true if RhostClass[e].any? { |a| remotehost.end_with?(a) }
40
- rhostmatch ||= true if RhostClass[e].any? { |a| domainpart.end_with?(a) }
41
- next unless rhostmatch
42
-
43
- modulename = 'Sisimai::Rhost::' << e
44
- rhostclass = 'sisimai/rhost/' << e.downcase
45
- break
46
- end
47
- return nil if rhostclass.empty?
72
+ def find(argvs)
73
+ return "" if argvs.nil?
74
+
75
+ rhostclass = name(argvs); return "" if rhostclass.empty?
76
+ modulepath = "sisimai/rhost/" << rhostclass.downcase; require modulepath
77
+ modulename = "Sisimai::Rhost::" << rhostclass
48
78
 
49
- require rhostclass
50
- reasontext = Module.const_get(modulename).get(argvs)
51
- return nil if reasontext.empty?
79
+ #rhostclass = "sisimai/rhost/" << modulename.downcase.split("::")[2]; require rhostclass
80
+ reasontext = Module.const_get(modulename).find(argvs)
81
+ return "" if reasontext.empty?
52
82
  return reasontext
53
83
  end
54
84
  end
@@ -3,9 +3,14 @@ module Sisimai
3
3
  # Sisimai::SMTP::Transcript is an SMTP Command related utilities
4
4
  module Command
5
5
  class << self
6
+ Availables = [
7
+ "HELO", "EHLO", "MAIL", "RCPT", "DATA", "QUIT", "RSET", "NOOP", "VRFY", "ETRN", "EXPN",
8
+ "HELP", "AUTH", "STARTTLS", "XFORWARD",
9
+ "CONN", # CONN is a pseudo SMTP command used only in Sisimai
10
+ ].freeze
6
11
  Detectable = [
7
- 'HELO', 'EHLO', 'STARTTLS', 'AUTH PLAIN', 'AUTH LOGIN', 'AUTH CRAM-', 'AUTH DIGEST-',
8
- 'MAIL F', 'RCPT', 'RCPT T', 'DATA', 'QUIT', 'XFORWARD',
12
+ "HELO", "EHLO", "STARTTLS", "AUTH PLAIN", "AUTH LOGIN", "AUTH CRAM-", "AUTH DIGEST-",
13
+ "MAIL F", "RCPT", "RCPT T", "DATA", "QUIT", "XFORWARD",
9
14
  ].freeze
10
15
 
11
16
  # Check that an SMTP command in the argument is valid or not
@@ -13,43 +18,48 @@ module Sisimai
13
18
  # @return [Boolean] 0: Is not a valid SMTP command, 1: Is a valid SMTP command
14
19
  # @since v5.0.0
15
20
  def test(argv0 = '')
16
- return nil if argv0.empty?
17
- return nil if argv0.size < 4
18
-
19
- comm0 = %w[HELO EHLO MAIL RCPT DATA QUIT RSET NOOP VRFY ETRN EXPN HELP]
20
- comm1 = %w[AUTH STARTTLS XFORWARD]
21
- return true if comm0.any? { |a| argv0.include?(a) }
22
- return true if comm1.any? { |a| argv0.include?(a) }
23
- return true if argv0.include?('CONN') # CONN is a pseudo SMTP command used only in Sisimai
21
+ return false if argv0.nil? || argv0.empty? || argv0.size < 4
22
+ return true if Availables.any? { |a| argv0.include?(a) }
24
23
  return false
25
24
  end
26
25
 
27
26
  # Pick an SMTP command from the given string
28
27
  # @param [String] argv0 A transcript text MTA returned
29
28
  # @return [String] An SMTP command
30
- # @return [undef] Failed to find an SMTP command or the 1st argument is missing
31
29
  # @since v5.0.0
32
30
  def find(argv0 = '')
33
- return nil unless Sisimai::SMTP::Command.test(argv0)
31
+ return "" unless Sisimai::SMTP::Command.test(argv0)
34
32
 
35
- stringsize = argv0.size
36
- commandmap = { 'STAR' => 'STARTTLS', 'XFOR' => 'XFORWARD' }
33
+ issuedcode = " " + argv0.downcase + " "
34
+ commandmap = { "STAR" => "STARTTLS", "XFOR" => "XFORWARD" }
37
35
  commandset = []
38
- previouspp = 0
39
36
 
40
37
  Detectable.each do |e|
41
38
  # Find an SMTP command from the given string
42
- p0 = argv0.index(e, previouspp)
43
- next unless p0
44
- next if p0 + 4 > stringsize
45
- previouspp = p0
39
+ p0 = argv0.index(e); next unless p0
40
+ if e.include?(" ") == false
41
+ # For example, "RCPT T" does not appear in an email address or a domain name
42
+ cx = true; while true do
43
+ # Exclude an SMTP command in the part of an email address, a domain name, such as
44
+ # DATABASE@EXAMPLE.JP, EMAIL.EXAMPLE.COM, and so on.
45
+ ca = issuedcode[p0, 1].ord
46
+ cz = issuedcode[p0 + e.size + 1, 1].ord
47
+
48
+ break if ca > 47 && ca < 58 || cz > 47 && cz < 58; # 0-9
49
+ break if ca > 63 && ca < 91 || cz > 63 && cz < 91; # @-Z
50
+ break if ca > 96 && ca < 123 || cz > 96 && cz < 123; # `-z
51
+ cx = false; break
52
+ end
53
+ next if cx == true
54
+ end
46
55
 
47
- cv = argv0[p0, 4]; next if commandset.include?(cv)
56
+ # There is the same command in the "commanset" or nor
57
+ cv = e[0, 4]; next if commandset.any? { |a| cv.start_with?(a) }
48
58
  cv = commandmap[cv] if commandmap.has_key?(cv)
49
59
  commandset << cv
50
60
  end
51
61
 
52
- return nil if commandset.empty?
62
+ return "" if commandset.empty?
53
63
  return commandset.pop
54
64
  end
55
65
  end