sisimai 5.0.3 → 5.2.0

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 (258) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/codecovio.yml +3 -1
  3. data/.github/workflows/rake-test.yml +7 -3
  4. data/ChangeLog.md +136 -0
  5. data/Makefile +4 -2
  6. data/README-JA.md +32 -22
  7. data/README.md +31 -21
  8. data/lib/sisimai/arf.rb +124 -213
  9. data/lib/sisimai/fact/json.rb +2 -2
  10. data/lib/sisimai/fact/yaml.rb +2 -2
  11. data/lib/sisimai/fact.rb +208 -173
  12. data/lib/sisimai/lda.rb +98 -0
  13. data/lib/sisimai/lhost/activehunter.rb +5 -4
  14. data/lib/sisimai/lhost/amazonses.rb +189 -305
  15. data/lib/sisimai/lhost/apachejames.rb +52 -55
  16. data/lib/sisimai/lhost/biglobe.rb +5 -6
  17. data/lib/sisimai/lhost/courier.rb +14 -12
  18. data/lib/sisimai/lhost/domino.rb +29 -29
  19. data/lib/sisimai/lhost/dragonfly.rb +113 -0
  20. data/lib/sisimai/lhost/einsundeins.rb +7 -8
  21. data/lib/sisimai/lhost/exchange2003.rb +10 -11
  22. data/lib/sisimai/lhost/exchange2007.rb +115 -104
  23. data/lib/sisimai/lhost/exim.rb +236 -246
  24. data/lib/sisimai/lhost/ezweb.rb +47 -55
  25. data/lib/sisimai/lhost/fml.rb +6 -7
  26. data/lib/sisimai/lhost/gmail.rb +36 -32
  27. data/lib/sisimai/lhost/gmx.rb +8 -20
  28. data/lib/sisimai/lhost/googlegroups.rb +13 -12
  29. data/lib/sisimai/lhost/googleworkspace.rb +94 -0
  30. data/lib/sisimai/lhost/imailserver.rb +11 -19
  31. data/lib/sisimai/lhost/interscanmss.rb +6 -5
  32. data/lib/sisimai/lhost/kddi.rb +7 -8
  33. data/lib/sisimai/lhost/mailfoundry.rb +6 -9
  34. data/lib/sisimai/lhost/mailmarshalsmtp.rb +6 -6
  35. data/lib/sisimai/lhost/messagingserver.rb +19 -17
  36. data/lib/sisimai/lhost/mfilter.rb +8 -7
  37. data/lib/sisimai/lhost/notes.rb +6 -8
  38. data/lib/sisimai/lhost/opensmtpd.rb +11 -9
  39. data/lib/sisimai/lhost/postfix.rb +29 -31
  40. data/lib/sisimai/lhost/qmail.rb +136 -112
  41. data/lib/sisimai/lhost/sendmail.rb +23 -22
  42. data/lib/sisimai/lhost/v5sendmail.rb +93 -64
  43. data/lib/sisimai/lhost/verizon.rb +6 -6
  44. data/lib/sisimai/lhost/x1.rb +4 -4
  45. data/lib/sisimai/lhost/x2.rb +4 -5
  46. data/lib/sisimai/lhost/x3.rb +5 -5
  47. data/lib/sisimai/lhost/x6.rb +4 -4
  48. data/lib/sisimai/lhost/zoho.rb +6 -6
  49. data/lib/sisimai/lhost.rb +21 -24
  50. data/lib/sisimai/mail/maildir.rb +1 -1
  51. data/lib/sisimai/mail/stdin.rb +1 -1
  52. data/lib/sisimai/message.rb +100 -153
  53. data/lib/sisimai/order.rb +22 -77
  54. data/lib/sisimai/reason/authfailure.rb +1 -4
  55. data/lib/sisimai/reason/badreputation.rb +3 -3
  56. data/lib/sisimai/reason/blocked.rb +7 -10
  57. data/lib/sisimai/reason/contenterror.rb +7 -1
  58. data/lib/sisimai/reason/exceedlimit.rb +1 -4
  59. data/lib/sisimai/reason/failedstarttls.rb +42 -0
  60. data/lib/sisimai/reason/filtered.rb +5 -4
  61. data/lib/sisimai/reason/hasmoved.rb +1 -2
  62. data/lib/sisimai/reason/hostunknown.rb +3 -3
  63. data/lib/sisimai/reason/mailboxfull.rb +2 -4
  64. data/lib/sisimai/reason/mailererror.rb +1 -2
  65. data/lib/sisimai/reason/mesgtoobig.rb +2 -4
  66. data/lib/sisimai/reason/norelaying.rb +3 -3
  67. data/lib/sisimai/reason/notaccept.rb +2 -3
  68. data/lib/sisimai/reason/notcompliantrfc.rb +10 -4
  69. data/lib/sisimai/reason/rejected.rb +2 -1
  70. data/lib/sisimai/reason/requireptr.rb +2 -2
  71. data/lib/sisimai/reason/securityerror.rb +1 -3
  72. data/lib/sisimai/reason/spamdetected.rb +6 -8
  73. data/lib/sisimai/reason/speeding.rb +1 -2
  74. data/lib/sisimai/reason/suppressed.rb +36 -0
  75. data/lib/sisimai/reason/suspend.rb +1 -3
  76. data/lib/sisimai/reason/systemerror.rb +5 -0
  77. data/lib/sisimai/reason/toomanyconn.rb +1 -2
  78. data/lib/sisimai/reason/userunknown.rb +1 -1
  79. data/lib/sisimai/reason/virusdetected.rb +5 -6
  80. data/lib/sisimai/reason.rb +82 -78
  81. data/lib/sisimai/rfc1123.rb +152 -0
  82. data/lib/sisimai/rfc1894.rb +102 -62
  83. data/lib/sisimai/rfc2045.rb +2 -1
  84. data/lib/sisimai/rfc3464/thirdparty.rb +102 -0
  85. data/lib/sisimai/rfc3464.rb +224 -345
  86. data/lib/sisimai/rfc3834.rb +3 -3
  87. data/lib/sisimai/rfc5322.rb +7 -17
  88. data/lib/sisimai/rfc791.rb +69 -0
  89. data/lib/sisimai/rhost/aol.rb +36 -0
  90. data/lib/sisimai/rhost/apple.rb +95 -0
  91. data/lib/sisimai/rhost/cox.rb +84 -34
  92. data/lib/sisimai/rhost/facebook.rb +100 -0
  93. data/lib/sisimai/rhost/franceptt.rb +87 -83
  94. data/lib/sisimai/rhost/godaddy.rb +208 -45
  95. data/lib/sisimai/rhost/google.rb +22 -22
  96. data/lib/sisimai/rhost/gsuite.rb +42 -0
  97. data/lib/sisimai/rhost/iua.rb +5 -5
  98. data/lib/sisimai/rhost/kddi.rb +9 -7
  99. data/lib/sisimai/rhost/messagelabs.rb +37 -0
  100. data/lib/sisimai/rhost/microsoft.rb +60 -54
  101. data/lib/sisimai/rhost/mimecast.rb +44 -31
  102. data/lib/sisimai/rhost/nttdocomo.rb +5 -4
  103. data/lib/sisimai/rhost/outlook.rb +36 -0
  104. data/lib/sisimai/rhost/spectrum.rb +102 -41
  105. data/lib/sisimai/rhost/tencent.rb +48 -26
  106. data/lib/sisimai/rhost/yahooinc.rb +111 -0
  107. data/lib/sisimai/rhost.rb +65 -42
  108. data/lib/sisimai/smtp/command.rb +31 -21
  109. data/lib/sisimai/smtp/failure.rb +103 -0
  110. data/lib/sisimai/smtp/reply.rb +29 -24
  111. data/lib/sisimai/smtp/status.rb +36 -19
  112. data/lib/sisimai/smtp/transcript.rb +18 -18
  113. data/lib/sisimai/string.rb +0 -46
  114. data/lib/sisimai/version.rb +1 -1
  115. data/lib/sisimai.rb +0 -6
  116. data/set-of-emails/maildir/bsd/lhost-dragonfly-01.eml +36 -0
  117. data/set-of-emails/maildir/bsd/lhost-dragonfly-02.eml +32 -0
  118. data/set-of-emails/maildir/bsd/lhost-dragonfly-03.eml +32 -0
  119. data/set-of-emails/maildir/bsd/lhost-dragonfly-04.eml +31 -0
  120. data/set-of-emails/maildir/bsd/lhost-dragonfly-05.eml +32 -0
  121. data/set-of-emails/maildir/bsd/lhost-dragonfly-06.eml +32 -0
  122. data/set-of-emails/maildir/bsd/lhost-dragonfly-07.eml +32 -0
  123. data/set-of-emails/maildir/bsd/lhost-dragonfly-08.eml +32 -0
  124. data/set-of-emails/maildir/bsd/lhost-dragonfly-09.eml +32 -0
  125. data/set-of-emails/maildir/bsd/lhost-dragonfly-10.eml +32 -0
  126. data/set-of-emails/maildir/bsd/lhost-dragonfly-11.eml +32 -0
  127. data/set-of-emails/maildir/bsd/lhost-dragonfly-12.eml +32 -0
  128. data/set-of-emails/maildir/bsd/lhost-dragonfly-13.eml +32 -0
  129. data/set-of-emails/maildir/bsd/lhost-dragonfly-14.eml +32 -0
  130. data/set-of-emails/maildir/bsd/lhost-dragonfly-15.eml +32 -0
  131. data/set-of-emails/maildir/bsd/lhost-dragonfly-16.eml +32 -0
  132. data/set-of-emails/maildir/bsd/lhost-dragonfly-17.eml +32 -0
  133. data/set-of-emails/maildir/bsd/lhost-dragonfly-18.eml +32 -0
  134. data/set-of-emails/maildir/bsd/lhost-dragonfly-19.eml +32 -0
  135. data/set-of-emails/maildir/bsd/lhost-dragonfly-20.eml +32 -0
  136. data/set-of-emails/maildir/bsd/lhost-dragonfly-21.eml +33 -0
  137. data/set-of-emails/maildir/bsd/lhost-dragonfly-22.eml +32 -0
  138. data/set-of-emails/maildir/bsd/lhost-dragonfly-23.eml +32 -0
  139. data/set-of-emails/maildir/bsd/lhost-dragonfly-24.eml +32 -0
  140. data/set-of-emails/maildir/bsd/lhost-dragonfly-25.eml +33 -0
  141. data/set-of-emails/maildir/bsd/lhost-dragonfly-26.eml +33 -0
  142. data/set-of-emails/maildir/bsd/lhost-dragonfly-27.eml +47 -0
  143. data/set-of-emails/maildir/bsd/lhost-dragonfly-28.eml +47 -0
  144. data/set-of-emails/maildir/bsd/lhost-dragonfly-29.eml +32 -0
  145. data/set-of-emails/maildir/bsd/lhost-dragonfly-30.eml +32 -0
  146. data/set-of-emails/maildir/bsd/lhost-opensmtpd-10.eml +58 -0
  147. data/set-of-emails/maildir/bsd/lhost-opensmtpd-11.eml +58 -0
  148. data/set-of-emails/maildir/bsd/lhost-opensmtpd-12.eml +62 -0
  149. data/set-of-emails/maildir/bsd/lhost-opensmtpd-13.eml +62 -0
  150. data/set-of-emails/maildir/bsd/lhost-opensmtpd-14.eml +58 -0
  151. data/set-of-emails/maildir/bsd/lhost-opensmtpd-15.eml +63 -0
  152. data/set-of-emails/maildir/bsd/lhost-opensmtpd-16.eml +62 -0
  153. data/set-of-emails/maildir/bsd/lhost-opensmtpd-17.eml +63 -0
  154. data/set-of-emails/maildir/bsd/lhost-postfix-30.eml +81 -81
  155. data/set-of-emails/maildir/bsd/lhost-qmail-11.eml +29 -0
  156. data/set-of-emails/maildir/bsd/lhost-qmail-12.eml +29 -0
  157. data/set-of-emails/maildir/bsd/lhost-qmail-13.eml +29 -0
  158. data/set-of-emails/maildir/bsd/lhost-qmail-14.eml +34 -0
  159. data/set-of-emails/maildir/bsd/lhost-qmail-15.eml +30 -0
  160. data/set-of-emails/maildir/bsd/lhost-qmail-16.eml +31 -0
  161. data/set-of-emails/maildir/bsd/lhost-qmail-17.eml +38 -0
  162. data/set-of-emails/maildir/bsd/lhost-qmail-18.eml +31 -0
  163. data/set-of-emails/maildir/bsd/lhost-qmail-19.eml +31 -0
  164. data/set-of-emails/maildir/bsd/lhost-qmail-20.eml +46 -0
  165. data/set-of-emails/maildir/bsd/lhost-qmail-21.eml +41 -0
  166. data/set-of-emails/maildir/bsd/lhost-qmail-22.eml +42 -0
  167. data/set-of-emails/maildir/bsd/lhost-qmail-23.eml +43 -0
  168. data/set-of-emails/maildir/bsd/lhost-qmail-24.eml +43 -0
  169. data/set-of-emails/maildir/bsd/lhost-qmail-25.eml +54 -0
  170. data/set-of-emails/maildir/bsd/{lhost-aol-03.eml → rhost-aol-03.eml} +1264 -1264
  171. data/set-of-emails/maildir/bsd/{lhost-aol-04.eml → rhost-aol-04.eml} +1260 -1260
  172. data/set-of-emails/maildir/bsd/{lhost-aol-05.eml → rhost-aol-05.eml} +105 -105
  173. data/set-of-emails/maildir/bsd/{lhost-aol-06.eml → rhost-aol-06.eml} +105 -105
  174. data/set-of-emails/maildir/bsd/rhost-apple-01.eml +79 -0
  175. data/set-of-emails/maildir/bsd/rhost-apple-02.eml +81 -0
  176. data/set-of-emails/maildir/bsd/rhost-apple-03.eml +75 -0
  177. data/set-of-emails/maildir/bsd/rhost-apple-04.eml +74 -0
  178. data/set-of-emails/maildir/bsd/rhost-gsuite-01.eml +189 -0
  179. data/set-of-emails/maildir/bsd/rhost-gsuite-02.eml +180 -0
  180. data/set-of-emails/maildir/bsd/rhost-gsuite-03.eml +251 -0
  181. data/set-of-emails/maildir/bsd/rhost-gsuite-04.eml +211 -0
  182. data/set-of-emails/maildir/bsd/rhost-gsuite-05.eml +226 -0
  183. data/set-of-emails/maildir/bsd/rhost-gsuite-06.eml +257 -0
  184. data/set-of-emails/maildir/bsd/rhost-gsuite-07.eml +289 -0
  185. data/set-of-emails/maildir/bsd/rhost-gsuite-08.eml +231 -0
  186. data/set-of-emails/maildir/bsd/rhost-gsuite-09.eml +231 -0
  187. data/set-of-emails/maildir/bsd/rhost-gsuite-10.eml +254 -0
  188. data/set-of-emails/maildir/bsd/rhost-gsuite-11.eml +228 -0
  189. data/set-of-emails/maildir/bsd/rhost-gsuite-12.eml +271 -0
  190. data/set-of-emails/maildir/bsd/rhost-gsuite-13.eml +261 -0
  191. data/set-of-emails/maildir/bsd/rhost-gsuite-14.eml +273 -0
  192. data/set-of-emails/maildir/bsd/rhost-gsuite-15.eml +229 -0
  193. data/set-of-emails/maildir/bsd/{lhost-messagelabs-01.eml → rhost-messagelabs-01.eml} +93 -93
  194. data/set-of-emails/maildir/bsd/rhost-outlook-01.eml +72 -0
  195. data/set-of-emails/maildir/bsd/rhost-outlook-02.eml +72 -0
  196. data/set-of-emails/maildir/bsd/rhost-outlook-03.eml +72 -0
  197. data/set-of-emails/maildir/bsd/rhost-outlook-04.eml +79 -0
  198. data/set-of-emails/maildir/bsd/rhost-outlook-06.eml +75 -0
  199. data/set-of-emails/maildir/bsd/rhost-outlook-07.eml +70 -0
  200. data/set-of-emails/maildir/bsd/rhost-outlook-08.eml +70 -0
  201. data/set-of-emails/maildir/bsd/rhost-outlook-09.eml +56 -0
  202. data/set-of-emails/maildir/bsd/rhost-yahooinc-01.eml +80 -0
  203. data/set-of-emails/maildir/bsd/rhost-yahooinc-02.eml +83 -0
  204. data/set-of-emails/maildir/bsd/rhost-yahooinc-03.eml +125 -0
  205. data/set-of-emails/maildir/tmp/arf-22.eml +49 -0
  206. data/set-of-emails/maildir/tmp/arf-23.eml +49 -0
  207. data/set-of-emails/maildir/tmp/arf-24.eml +50 -0
  208. data/set-of-emails/maildir/tmp/lhost-exim-07.eml +28 -0
  209. metadata +136 -56
  210. data/lib/sisimai/lhost/amavis.rb +0 -163
  211. data/lib/sisimai/lhost/amazonworkmail.rb +0 -127
  212. data/lib/sisimai/lhost/aol.rb +0 -125
  213. data/lib/sisimai/lhost/barracuda.rb +0 -92
  214. data/lib/sisimai/lhost/bigfoot.rb +0 -125
  215. data/lib/sisimai/lhost/facebook.rb +0 -188
  216. data/lib/sisimai/lhost/gsuite.rb +0 -194
  217. data/lib/sisimai/lhost/mailru.rb +0 -214
  218. data/lib/sisimai/lhost/mcafee.rb +0 -109
  219. data/lib/sisimai/lhost/messagelabs.rb +0 -119
  220. data/lib/sisimai/lhost/mxlogic.rb +0 -198
  221. data/lib/sisimai/lhost/office365.rb +0 -252
  222. data/lib/sisimai/lhost/outlook.rb +0 -129
  223. data/lib/sisimai/lhost/powermta.rb +0 -118
  224. data/lib/sisimai/lhost/receivingses.rb +0 -126
  225. data/lib/sisimai/lhost/sendgrid.rb +0 -150
  226. data/lib/sisimai/lhost/surfcontrol.rb +0 -105
  227. data/lib/sisimai/lhost/x4.rb +0 -269
  228. data/lib/sisimai/lhost/x5.rb +0 -112
  229. data/lib/sisimai/lhost/yahoo.rb +0 -102
  230. data/lib/sisimai/lhost/yandex.rb +0 -118
  231. data/lib/sisimai/mda.rb +0 -121
  232. data/lib/sisimai/smtp/error.rb +0 -119
  233. /data/set-of-emails/maildir/bsd/{lhost-googlegroups-15.eml → lhost-googleworkspace-01.eml} +0 -0
  234. /data/set-of-emails/maildir/bsd/{lhost-x4-08.eml → lhost-x2-06.eml} +0 -0
  235. /data/set-of-emails/maildir/bsd/{lhost-gsuite-01.eml → rfc3464-51.eml} +0 -0
  236. /data/set-of-emails/maildir/bsd/{lhost-gsuite-03.eml → rfc3464-52.eml} +0 -0
  237. /data/set-of-emails/maildir/bsd/{lhost-gsuite-04.eml → rfc3464-53.eml} +0 -0
  238. /data/set-of-emails/maildir/bsd/{lhost-gsuite-05.eml → rfc3464-54.eml} +0 -0
  239. /data/set-of-emails/maildir/bsd/{lhost-gsuite-06.eml → rfc3464-55.eml} +0 -0
  240. /data/set-of-emails/maildir/bsd/{lhost-gsuite-07.eml → rfc3464-56.eml} +0 -0
  241. /data/set-of-emails/maildir/bsd/{lhost-gsuite-08.eml → rfc3464-57.eml} +0 -0
  242. /data/set-of-emails/maildir/bsd/{lhost-gsuite-09.eml → rfc3464-58.eml} +0 -0
  243. /data/set-of-emails/maildir/bsd/{lhost-gsuite-10.eml → rfc3464-59.eml} +0 -0
  244. /data/set-of-emails/maildir/bsd/{lhost-gsuite-11.eml → rfc3464-60.eml} +0 -0
  245. /data/set-of-emails/maildir/bsd/{lhost-gsuite-12.eml → rfc3464-61.eml} +0 -0
  246. /data/set-of-emails/maildir/bsd/{lhost-gsuite-13.eml → rfc3464-62.eml} +0 -0
  247. /data/set-of-emails/maildir/bsd/{lhost-gsuite-14.eml → rfc3464-63.eml} +0 -0
  248. /data/set-of-emails/maildir/bsd/{lhost-gsuite-15.eml → rfc3464-64.eml} +0 -0
  249. /data/set-of-emails/maildir/bsd/{lhost-gsuite-02.eml → rfc3464-65.eml} +0 -0
  250. /data/set-of-emails/maildir/bsd/{lhost-aol-01.eml → rhost-aol-01.eml} +0 -0
  251. /data/set-of-emails/maildir/bsd/{lhost-aol-02.eml → rhost-aol-02.eml} +0 -0
  252. /data/set-of-emails/maildir/bsd/{lhost-facebook-03.eml → rhost-facebook-03.eml} +0 -0
  253. /data/set-of-emails/maildir/bsd/{lhost-facebook-04.eml → rhost-facebook-04.eml} +0 -0
  254. /data/set-of-emails/maildir/bsd/{lhost-messagelabs-02.eml → rhost-messagelabs-02.eml} +0 -0
  255. /data/set-of-emails/maildir/bsd/{lhost-messagelabs-03.eml → rhost-messagelabs-03.eml} +0 -0
  256. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-37.eml +0 -0
  257. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-38.eml +0 -0
  258. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-39.eml +0 -0
@@ -0,0 +1,103 @@
1
+ module Sisimai
2
+ module SMTP
3
+ # Sisimai::SMTP::Failure is utilities for checking SMTP Errors from error message text.
4
+ module Failure
5
+ class << self
6
+ require 'sisimai/smtp/reply'
7
+ require 'sisimai/smtp/status'
8
+
9
+ # Returns true if the given string indicates a permanent error
10
+ # @param [String] argv1 String including SMTP Status code
11
+ # @return [Boolean] true: Permanet error
12
+ # false: Is not a permanent error
13
+ # @since v4.17.3
14
+ def is_permanent(argv1 = '')
15
+ return false unless argv1
16
+ return false unless argv1.size > 0
17
+
18
+ statuscode = Sisimai::SMTP::Status.find(argv1)
19
+ statuscode = Sisimai::SMTP::Reply.find(argv1) if statuscode.empty?
20
+ return true if statuscode[0, 1] == "5"
21
+ return true if argv1.downcase.include?(' permanent ')
22
+ return false
23
+ end
24
+
25
+ # Returns true if the given string indicates a temporary error
26
+ # @param [String] argv1 String including SMTP Status code
27
+ # @return [Boolean] true: Temporary error
28
+ # false: is not a temporary error
29
+ # @since v5.2.0
30
+ def is_temporary(argv1 = '')
31
+ return false unless argv1
32
+ return false unless argv1.size > 0
33
+
34
+ statuscode = Sisimai::SMTP::Status.find(argv1);
35
+ statuscode = Sisimai::SMTP::Reply.find(argv1) if statuscode.empty?
36
+ issuedcode = argv1.downcase
37
+
38
+ return true if statuscode[0, 1] == "4"
39
+ return true if issuedcode.include?(' temporar')
40
+ return true if issuedcode.include?(' persistent')
41
+ return false
42
+ end
43
+
44
+ # Checks the reason sisimai detected is a hard bounce or not
45
+ # @param [String] argv1 Detected bounce reason
46
+ # @param [String] argv2 String including SMTP Status code
47
+ # @return [Boolean] true: is a hard bounce
48
+ def is_hardbounce(argv1 = '', argv2 = '')
49
+ return false unless argv1
50
+ return false unless argv1.size > 0
51
+
52
+ return false if argv1 == "undefined" || argv1 == "onhold"
53
+ return false if argv1 == "delivered" || argv1 == "feedback" || argv1 == "vacation"
54
+ return true if argv1 == "hasmoved" || argv1 == "userunknown" || argv1 == "hostunknown"
55
+ return false if argv1 != "notaccept"
56
+
57
+ # NotAccept: 5xx => hard bounce, 4xx => soft bounce
58
+ hardbounce = false
59
+ if argv2.size > 0
60
+ # Check the 2nd argument(a status code or a reply code)
61
+ cv = Sisimai::SMTP::Status.find(argv2, "")
62
+ cv = Sisimai::SMTP::Reply.find(argv2, "") if cv.empty?
63
+
64
+ # The SMTP status code or the SMTP reply code starts with "5"
65
+ # Deal as a hard bounce when the error message does not indicate a temporary error
66
+ hardbounce = true if cv[0, 1] == "5" || Sisimai::SMTP::Failure.is_temporary(argv2) == false
67
+ else
68
+ # Deal "NotAccept" as a hard bounce when the 2nd argument is empty
69
+ hardbounce = true
70
+ end
71
+ return hardbounce
72
+ end
73
+
74
+ # Checks the reason sisimai detected is a soft bounce or not
75
+ # @param [String] argv1 Detected bounce reason
76
+ # @param [String] argv2 String including SMTP Status code
77
+ # @return [Boolean] true: is a soft bounce
78
+ def is_softbounce(argv1 = '', argv2 = '')
79
+ return false unless argv1
80
+ return false unless argv1.size > 0
81
+
82
+ return false if argv1 == "delivered" || argv1 == "feedback" || argv1 == "vacation"
83
+ return false if argv1 == "hasmoved" || argv1 == "userunknown" || argv1 == "hostunknown"
84
+ return true if argv1 == "undefined" || argv1 == "onhold"
85
+ return true if argv1 != "notaccept"
86
+
87
+ # NotAccept: 5xx => hard bounce, 4xx => soft bounce
88
+ softbounce = false
89
+ if argv2.size > 0
90
+ # Check the 2nd argument(a status code or a reply code)
91
+ cv = Sisimai::SMTP::Status.find(argv2, "")
92
+ cv = Sisimai::SMTP::Reply.find(argv2, "") if cv.empty?
93
+
94
+ # The SMTP status code or the SMTP reply code starts with "4"
95
+ softbounce = true if cv[0, 1] == "4"
96
+ end
97
+ return softbounce
98
+ end
99
+
100
+ end
101
+ end
102
+ end
103
+ end
@@ -1,4 +1,5 @@
1
1
  # http://www.ietf.org/rfc/rfc5321.txt
2
+ # -------------------------------------------------------------------------------------------------
2
3
  # 4.2.1. Reply Code Severities and Theory
3
4
  #
4
5
  # There are four values for the first digit of the reply code:
@@ -103,31 +104,32 @@ module Sisimai
103
104
  # 554 Transaction failed (Or, in the case of a connection-opening response, "No SMTP service here")
104
105
  # 555 MAIL FROM/RCPT TO parameters not recognized or not implemented
105
106
  # 556 Domain does not accept mail (See RFC7504)
107
+ # 557 draft-moore-email-addrquery-01
106
108
  '550', '552', '553', '551', '521', '525', '502', '520', '523', '524', '530', '533', '534',
107
- '535', '538', '551', '555', '556', '554', '500', '501', '502', '503', '504',
109
+ '535', '538', '551', '555', '556', '554', '557', '500', '501', '502', '503', '504',
108
110
  ].freeze
109
111
  CodeOfSMTP = { '2' => ReplyCode2, '4' => ReplyCode4, '5' => ReplyCode5 }.freeze
110
112
 
111
113
  # Check whether a reply code is a valid code or not
112
114
  # @param [String] argv1 Reply Code(DSN)
113
- # @return [Boolean] 0 = Invalid reply code, 1 = Valid reply code
115
+ # @return [Boolean] false = Invalid reply code, true = Valid reply code
114
116
  # @see code
115
117
  # @since v5.0.0
116
118
  def test(argv1 = '')
117
- return nil if argv1.empty?
119
+ return false if argv1.empty?
118
120
 
119
121
  reply = argv1.to_i
120
122
  first = (reply / 100).to_i
121
123
 
122
- return false if reply < 200
123
- return false if reply > 599
124
+ return false if reply < 211
125
+ return false if reply > 557
124
126
  return false if reply % 100 > 59
125
127
 
126
128
  if first == 2
127
129
  # 2yz
128
- return false if reply < 211
129
- return false if reply > 252
130
- return false if reply > 221 && reply < 250
130
+ return true if reply == 235 # 235 is a valid code for AUTH (RFC4954)
131
+ return false if reply > 253 # The maximum code of 2xy is 253 (RFC5248)
132
+ return false if reply > 221 && reply < 250 # There is no reply code between 221 and 250
131
133
  return true
132
134
  end
133
135
 
@@ -146,34 +148,37 @@ module Sisimai
146
148
  # @return [String] SMTP Reply Code
147
149
  # [Nil] The first argument did not include SMTP Reply Code value
148
150
  def find(argv1 = '', argv2 = '0')
149
- return nil if argv1.to_s.size < 3
150
- return nil if argv1.upcase.include?('X-UNIX')
151
+ return "" if argv1.to_s.size < 3
152
+ return "" if argv1.upcase.include?('X-UNIX')
151
153
 
154
+ esmtperror = ' ' + argv1 + ' '
155
+ esmtpreply = ''
152
156
  statuscode = argv2[0, 1]
153
157
  replycodes = if statuscode == '5' || statuscode == '4' || statuscode == '2'
154
158
  CodeOfSMTP[statuscode]
155
159
  else
156
160
  [*CodeOfSMTP['5'], *CodeOfSMTP['4'], *CodeOfSMTP['2']]
157
161
  end
158
- esmtperror = ' ' + argv1 + ' '
159
- esmtpreply = '' # SMTP Reply Code
160
- replyindex = 0 # A position of SMTP reply code found by the index()
161
- formerchar = 0 # a character that is one character before the SMTP reply code
162
- latterchar = 0 # a character that is one character after the SMTP reply code
163
162
 
164
163
  replycodes.each do |e|
165
164
  # Try to find an SMTP Reply Code from the given string
166
- replyindex = esmtperror.index(e); next unless replyindex
167
- formerchar = esmtperror[replyindex - 1, 1].ord || 0
168
- latterchar = esmtperror[replyindex + 3, 1].ord || 0
165
+ appearance = esmtperror.index(e); next if appearance.nil?
166
+ startingat = 1
167
+ mesglength = esmtperror.size
169
168
 
170
- next if formerchar > 45 && formerchar < 58
171
- next if latterchar > 45 && latterchar < 58
172
- esmtpreply = e
173
- break
174
- end
169
+ while startingat + 3 < mesglength
170
+ # Find all the reply code in the error message
171
+ replyindex = esmtperror.index(e, startingat); break if replyindex.nil?
172
+ formerchar = esmtperror[replyindex - 1, 1].ord || 0
173
+ latterchar = esmtperror[replyindex + 3, 1].ord || 0
175
174
 
176
- return nil if esmtpreply.empty?
175
+ if formerchar > 45 && formerchar < 58 then startingat += 3; next; end
176
+ if latterchar > 45 && latterchar < 58 then startingat += 3; next; end
177
+ esmtpreply = e
178
+ break
179
+ end
180
+ break if esmtpreply != ""
181
+ end
177
182
  return esmtpreply
178
183
  end
179
184
 
@@ -479,6 +479,8 @@ module Sisimai
479
479
  # reason from D.S.N. value, and getting D.S.N. from the text including D.S.N.
480
480
  module Status
481
481
  class << self
482
+ require "sisimai/rfc791"
483
+
482
484
  CodePatterns = [
483
485
  %r/[ ]?[(][#]([45][.]\d[.]\d+)[)]?[ ]?/, # #5.5.1
484
486
  %r/\b\d{3}[- ][#]?([45][.]\d[.]\d+)\b/, # 550-5.1.1 OR 550 5.5.1
@@ -492,7 +494,7 @@ module Sisimai
492
494
  '4.1.7' => 'rejected', # Bad sender's mailbox address syntax
493
495
  '4.1.8' => 'rejected', # Bad sender's system address
494
496
  '4.1.9' => 'systemerror', # Message relayed to non-compliant mailer
495
- '4.2.1' => 'suspend', # Mailbox disabled, not accepting messages
497
+ '4.2.1' => 'blocked', # Mailbox disabled, not accepting messages
496
498
  '4.2.2' => 'mailboxfull', # Mailbox full
497
499
  '4.2.3' => 'exceedlimit', # Message length exceeds administrative limit
498
500
  '4.2.4' => 'filtered', # Mailing list expansion problem
@@ -595,47 +597,53 @@ module Sisimai
595
597
  '5.7.27' => 'notaccept', # MX resource record of a destination host is Null MX: RFC7505
596
598
  '5.7.28' => 'spamdetected', # The message appears to be part of a mail flood of similar abusive messages.
597
599
  '5.7.29' => 'authfailure', # This status code may be returned when a message fails ARC validation.
598
- '5.7.30' => 'securityerror', # REQUIRETLS support required
600
+ '5.7.30' => 'failedstarttls', # REQUIRETLS support required
599
601
  }.freeze
600
602
 
601
603
  InternalCode = {
602
604
  :temporary => {
603
- 'authfailure' => '4.0.972',
605
+ 'authfailure' => '4.0.926',
604
606
  'badreputation' => '4.0.975',
605
607
  'blocked' => '4.0.971',
606
608
  'contenterror' => '4.0.960',
607
- # 'exceedlimit' => '4.0.923',
609
+ 'exceedlimit' => '4.0.923',
608
610
  'expired' => '4.0.947',
611
+ 'failedstarttls' => '4.0.976',
609
612
  'filtered' => '4.0.924',
610
613
  # 'hasmoved' => '4.0.916',
611
614
  # 'hostunknown' => '4.0.912',
612
615
  'mailboxfull' => '4.0.922',
613
- # 'mailererror' => '4.0.939',
614
- # 'mesgtoobig' => '4.0.934',
616
+ 'mailererror' => '4.0.939',
617
+ 'mesgtoobig' => '4.0.934',
615
618
  'networkerror' => '4.0.944',
616
- # 'norelaying' => '4.0.909',
619
+ 'norelaying' => '4.0.909',
617
620
  'notaccept' => '4.0.932',
618
621
  'notcompliantrfc' => '4.0.974',
619
622
  'onhold' => '4.0.901',
623
+ 'policyviolaton' => '4.0.972',
620
624
  'rejected' => '4.0.918',
621
625
  'requireptr' => '4.0.973',
622
626
  'securityerror' => '4.0.970',
623
627
  'spamdetected' => '4.0.980',
624
628
  'speeding' => '4.0.946',
625
- # 'suspend' => '4.0.921',
629
+ 'suppressed' => '4.0.903',
630
+ 'suspend' => '4.0.921',
626
631
  'systemerror' => '4.0.930',
627
632
  'systemfull' => '4.0.931',
633
+ 'syntaxerror' => '4.0.902',
628
634
  'toomanyconn' => '4.0.945',
629
635
  # 'userunknown' => '4.0.911',
630
636
  'undefined' => '4.0.900',
637
+ 'virusdetected' => '4.0.981',
631
638
  },
632
639
  :permanent => {
633
- 'authfailure' => '5.0.972',
640
+ 'authfailure' => '5.0.926',
634
641
  'badreputation' => '5.0.975',
635
642
  'blocked' => '5.0.971',
636
643
  'contenterror' => '5.0.960',
637
644
  'exceedlimit' => '5.0.923',
638
645
  'expired' => '5.0.947',
646
+ 'failedstarttls' => '5.0.976',
639
647
  'filtered' => '5.0.910',
640
648
  'hasmoved' => '5.0.916',
641
649
  'hostunknown' => '5.0.912',
@@ -653,6 +661,7 @@ module Sisimai
653
661
  'securityerror' => '5.0.970',
654
662
  'spamdetected' => '5.0.980',
655
663
  'speeding' => '5.0.946',
664
+ 'suppressed' => '5.0.903',
656
665
  'suspend' => '5.0.921',
657
666
  'systemerror' => '5.0.930',
658
667
  'systemfull' => '5.0.931',
@@ -660,7 +669,7 @@ module Sisimai
660
669
  'toomanyconn' => '5.0.945',
661
670
  'userunknown' => '5.0.911',
662
671
  'undefined' => '5.0.900',
663
- 'virusdetected' => '5.0.971',
672
+ 'virusdetected' => '5.0.981',
664
673
  },
665
674
  }.freeze
666
675
 
@@ -696,7 +705,7 @@ module Sisimai
696
705
  # @see code
697
706
  # @since v5.0.0
698
707
  def test(argv1 = '')
699
- return nil if argv1.to_s.empty?
708
+ return false if argv1.to_s.empty?
700
709
  return false if argv1.size < 5
701
710
  return false if argv1.size > 7
702
711
 
@@ -717,8 +726,8 @@ module Sisimai
717
726
  # @param [String] argv2 An SMTP Reply Code or 2 or 4 or 5
718
727
  # @return [String, Nil] An SMTP Status Code
719
728
  def find(argv1 = nil, argv2 = '0')
720
- return nil if argv1.to_s.empty?
721
- return nil if argv1.size < 7
729
+ return "" if argv1.to_s.empty?
730
+ return "" if argv1.size < 7
722
731
 
723
732
  givenclass = argv2[0, 1]
724
733
  eestatuses = if givenclass == '2' || givenclass == '4' || givenclass == '5'
@@ -729,7 +738,7 @@ module Sisimai
729
738
  esmtperror = ' ' + argv1 + ' '
730
739
  lookingfor = []
731
740
 
732
- Sisimai::String.ipv4(esmtperror).each do |e|
741
+ Sisimai::RFC791.find(esmtperror).each do |e|
733
742
  # Rewrite an IPv4 address in the given string(argv1) with '***.***.***.***'
734
743
  p0 = esmtperror.index(e) || next
735
744
  esmtperror[p0, e.size] = '***.***.***.***'
@@ -745,7 +754,7 @@ module Sisimai
745
754
  p1 = p0 + 5
746
755
  end
747
756
  end
748
- return nil if lookingfor.size == 0
757
+ return "" if lookingfor.size == 0
749
758
 
750
759
  statuscode = [] # List of SMTP Status Code, Keep the order of appearances
751
760
  anotherone = '' # Alternative code
@@ -811,10 +820,13 @@ module Sisimai
811
820
  next if characters[6] > 47 && characters[6] < 58
812
821
  statuscode << readbuffer
813
822
  end
814
-
815
823
  statuscode << anotherone if anotherone.size > 0
816
- return nil if statuscode.size == 0
817
- return statuscode.shift
824
+ return "" if statuscode.size == 0
825
+
826
+ # Select one from picked status codes
827
+ cv = statuscode.shift; statuscode.each { |e| cv = Sisimai::SMTP::Status.prefer(cv, e, "") }
828
+
829
+ return cv
818
830
  end
819
831
 
820
832
  # Return the preferred value selected from the arguments
@@ -860,11 +872,16 @@ module Sisimai
860
872
 
861
873
  return statuscode if zeroindex2['error'] > 0 # An SMTP status code is "X.0.0"
862
874
  return codeinmesg if statuscode == '4.4.7' # "4.4.7" is an ambiguous code
875
+ return codeinmesg if statuscode == '4.7.0' # "4.7.0" indicates "too many errors"
863
876
  return codeinmesg if statuscode.start_with?('5.3.') # "5.3.Z" is an error of a system
877
+ return codeinmesg if statuscode.end_with?('.5.1') # "X.5.1" indicates an invalid command
878
+ return codeinmesg if statuscode.end_with?('.5.2') # "X.5.2" indicates a syntax error
879
+ return codeinmesg if statuscode.end_with?('.5.4') # "X.5.4" indicates an invalid command arguments
880
+ return codeinmesg if statuscode.end_with?('.5.5') # "X.5.5" indicates a wrong protocol version
864
881
 
865
882
  if statuscode == '5.1.1'
866
883
  # "5.1.1" is a code of "userunknown"
867
- return statuscode if zeroindex1['error'] > 0
884
+ return statuscode if codeinmesg.start_with?('5.5.') || zeroindex1['error'] > 0
868
885
  return codeinmesg
869
886
 
870
887
  elsif statuscode == '5.1.3'
@@ -1,17 +1,17 @@
1
1
  module Sisimai
2
2
  module SMTP
3
- # Sisimai::SMTP::Transcript is a parser for transcript logs of SMTP session
3
+ # Sisimai::SMTP::Transcript is a decoder for the transcript logs of the SMTP session
4
4
  module Transcript
5
5
  class << self
6
6
  require 'sisimai/smtp/reply'
7
7
  require 'sisimai/smtp/status'
8
8
 
9
- # Parse a transcript of an SMTP session and makes structured data
9
+ # @abstract decodes the transcript of the SMTP session and makes structured data
10
10
  # @param [String] argv0 A transcript text MTA returned
11
11
  # @param [String] argv1 A label string of a SMTP client
12
12
  # @apram [String] argv2 A label string of a SMTP server
13
13
  # @return [Array] Structured data
14
- # [Nil] Failed to parse or the 1st argument is missing
14
+ # [Nil] Failed to decode or the 1st argument is missing
15
15
  # @since v5.0.0
16
16
  def rise(argv0 = '', argv1 = '>>>', argv2 = '<<<')
17
17
  return nil if argv0.size == 0
@@ -34,18 +34,17 @@ module Sisimai
34
34
  }
35
35
  }
36
36
  end
37
- parameters = '' # Command parameters of MAIL, RCPT
38
- cursession = nil # Current session for $esmtp
39
37
 
40
38
  cv = ''
41
- p0 = argv0.index('<<<') || -1 # Server response
39
+ cx = nil # Current session for esmtp
42
40
  p1 = argv0.index('>>>') || -1 # Sent command
43
- if p0 < p1
41
+ p2 = argv0.index('<<<') || -1 # Server response
42
+ if p2 < p1
44
43
  # An SMTP server response starting with '<<<' is the first
45
44
  esmtp << table.call
46
- cursession = esmtp[-1]
47
- cursession['command'] = 'CONN'
48
- argv0 = argv0[p0, argv0.size] if p0 > -1
45
+ cx = esmtp[-1]
46
+ cx['command'] = 'CONN'
47
+ argv0 = argv0[p2, argv0.size] if p2 > -1
49
48
  else
50
49
  # An SMTP command starting with '>>>' is the first
51
50
  argv0 = argv0[p1, argv0.size] if p1 > -1
@@ -63,17 +62,18 @@ module Sisimai
63
62
  # >>> SMTP Command
64
63
  thecommand = cv[1]
65
64
  commandarg = cv[2]
65
+ parameters = ''
66
66
 
67
67
  esmtp << table.call
68
- cursession = esmtp[-1]
69
- cursession['command'] = thecommand.upcase
68
+ cx = esmtp[-1]
69
+ cx['command'] = thecommand.upcase
70
70
 
71
71
  if thecommand =~ /\A(?:MAIL|RCPT|XFORWARD)/
72
72
  # MAIL or RCPT
73
73
  if cv = commandarg.match(/\A(?:FROM|TO):[ ]*<(.+[@].+)>[ ]*(.*)\z/)
74
74
  # >>> MAIL FROM: <neko@example.com> SIZE=65535
75
75
  # >>> RCPT TO: <kijitora@example.org>
76
- cursession['argument'] = cv[1]
76
+ cx['argument'] = cv[1]
77
77
  parameters = cv[2]
78
78
 
79
79
  else
@@ -87,11 +87,11 @@ module Sisimai
87
87
 
88
88
  parameters.split(" ").each do |p|
89
89
  # SIZE=22022, PROTO=SMTP, and so on
90
- if cv = p.match(/\A([^ =]+)=([^ =]+)\z/) then cursession['parameter'][cv[1].downcase] = cv[2] end
90
+ if cv = p.match(/\A([^ =]+)=([^ =]+)\z/) then cx['parameter'][cv[1].downcase] = cv[2] end
91
91
  end
92
92
  else
93
93
  # HELO, EHLO, AUTH, DATA, QUIT or Other SMTP command
94
- cursession['argument'] = commandarg
94
+ cx['argument'] = commandarg
95
95
  end
96
96
  end
97
97
  else
@@ -101,9 +101,9 @@ module Sisimai
101
101
  e = e[4, e.size]
102
102
 
103
103
  e.sub!(/\A<<<[ ]/, '')
104
- if cv = e.match(/\A([2-5]\d\d)[ ]/) then cursession['response']['reply'] = cv[1] end
105
- if cv = e.match(/\A[245]\d\d[ ]([245][.]\d{1,3}[.]\d{1,3})[ ]/) then cursession['response']['status'] = cv[1] end
106
- cursession['response']['text'] << e
104
+ if cv = e.match(/\A([2-5]\d\d)[ ]/) then cx['response']['reply'] = cv[1] end
105
+ if cv = e.match(/\A[245]\d\d[ ]([245][.]\d{1,3}[.]\d{1,3})[ ]/) then cx['response']['status'] = cv[1] end
106
+ cx['response']['text'] << e
107
107
  end
108
108
  end
109
109
 
@@ -75,52 +75,6 @@ module Sisimai
75
75
  return false
76
76
  end
77
77
 
78
- # Find an IPv4 address from the given string
79
- # @param [String] argv1 String including an IPv4 address
80
- # @return [Array] List of IPv4 addresses
81
- # @since v5.0.0
82
- def ipv4(argv0)
83
- return nil if argv0.to_s.empty?
84
- return [] if argv0.size < 7
85
-
86
- ipv4a = []
87
- %w|( ) [ ]|.each do |e|
88
- # Rewrite: "mx.example.jp[192.0.2.1]" => "mx.example.jp 192.0.2.1"
89
- p0 = argv0.index(e); next unless p0
90
- argv0[p0, 1] = ' '
91
- end
92
-
93
- argv0.split(' ').each do |e|
94
- # Find string including an IPv4 address
95
- next unless e.index('.') # IPv4 address must include "." character
96
-
97
- lx = e.size; next if lx < 7 || lx > 17 # 0.0.0.0 = 7, [255.255.255.255] = 17
98
- cu = 0 # Cursor for seeking each octet of an IPv4 address
99
- as = '' # ASCII Code of each character
100
- eo = '' # Buffer of each octet of IPv4 Address
101
-
102
- while cu < lx
103
- # Check whether each character is a number or "." or not
104
- as = e[cu, 1].ord
105
- cu += 1
106
-
107
- if as < 48 || as > 57
108
- # The character is not a number(0-9)
109
- break if as != 46 # The character is not "."
110
- next if eo == '' # The current buffer is empty
111
- break if eo.to_i > 255 # The current buffer is greater than 255
112
- eo = ''
113
- next
114
- end
115
- eo << as.chr
116
- break if eo.to_i > 255
117
- end
118
- ipv4a << e if eo.size > 0 && eo.to_i < 256
119
- end
120
-
121
- return ipv4a
122
- end
123
-
124
78
  # Convert given HTML text to plain text
125
79
  # @param [String] argv1 HTML text
126
80
  # @param [Boolean] loose Loose check flag
@@ -1,4 +1,4 @@
1
1
  # Define the version number of Sisimai
2
2
  module Sisimai
3
- VERSION = '5.0.3'.freeze
3
+ VERSION = '5.2.0'.freeze
4
4
  end
data/lib/sisimai.rb CHANGED
@@ -7,12 +7,6 @@ module Sisimai
7
7
  def version(); return Sisimai::VERSION; end
8
8
  def libname(); return 'Sisimai'; end
9
9
 
10
- # Emulate "rise" method for the backward compatible
11
- def make(argv0, **argv1)
12
- warn ' ***warning: Sisimai.make will be removed at v5.1.0. Use Sisimai.rise instead';
13
- return Sisimai.rise(argv0, **argv1)
14
- end
15
-
16
10
  # Wrapper method for decoding mailbox/maidir
17
11
  # @param [String] argv0 Path to mbox or Maildir/
18
12
  # @param [Hash] argv0 or Hash (decoded JSON)
@@ -0,0 +1,36 @@
1
+ Received: from MAILER-DAEMON
2
+ id e0720
3
+ by df.example.jp (DragonFly Mail Agent v0.13);
4
+ Tue, 11 Jun 2024 18:02:02 +0900
5
+ X-Original-To: <pseudo-local-part@google.example.com>
6
+ From: MAILER-DAEMON <>
7
+ To: kijitora@df.example.jp
8
+ Subject: Mail delivery failed
9
+ Message-Id: <e0720@df.example.jp>
10
+ Date: Tue, 11 Jun 2024 18:02:02 +0900
11
+
12
+ This is the DragonFly Mail Agent v0.13 at df.example.jp.
13
+
14
+ There was an error delivering your mail to <pseudo-local-part@google.example.com>.
15
+
16
+ gmail-smtp-in.l.google.com [74.125.203.27] did not like our final DATA:
17
+ 550-5.7.26 Unauthenticated email from example.jp is not accepted due to domain's
18
+ 550-5.7.26 DMARC policy. Please contact the administrator of example.jp domain if
19
+ 550-5.7.26 this was a legitimate mail. To learn about the DMARC initiative, go
20
+ 550-5.7.26 to
21
+ 550 5.7.26 https://support.google.com/mail/?p=DmarcRejection 98e67ed59e1d1-2c2d0e28189si6418580a91.13 - gsmtp
22
+
23
+ Message headers follow.
24
+
25
+ Received: from root (uid 0)
26
+ (envelope-from kijitora@df.example.jp)
27
+ id e06d1
28
+ by df.example.jp (DragonFly Mail Agent v0.13);
29
+ Tue, 11 Jun 2024 18:02:00 +0900
30
+ Subject: Nyaan 01
31
+ To: <pseudo-local-part@google.example.com>
32
+ User-Agent: mail (GNU Mailutils 3.14)
33
+ Date: Tue, 11 Jun 2024 18:02:00 +0900
34
+ Message-Id: <66681288.e06d1.3824794@df.example.jp>
35
+ From: <kijitora@df.example.jp>
36
+
@@ -0,0 +1,32 @@
1
+ Received: from MAILER-DAEMON
2
+ id e0720
3
+ by df.example.jp (DragonFly Mail Agent v0.13);
4
+ Tue, 11 Jun 2024 18:04:02 +0900
5
+ X-Original-To: <pseudo-local-part@outlook.example.com>
6
+ From: MAILER-DAEMON <>
7
+ To: kijitora@df.example.jp
8
+ Subject: Mail delivery failed
9
+ Message-Id: <e0720@df.example.jp>
10
+ Date: Tue, 11 Jun 2024 18:04:02 +0900
11
+
12
+ This is the DragonFly Mail Agent v0.13 at df.example.jp.
13
+
14
+ There was an error delivering your mail to <pseudo-local-part@outlook.example.com>.
15
+
16
+ outlook-com.olc.protection.outlook.com [52.101.42.17] did not like our final DATA:
17
+ 550 5.7.509 Access denied, sending domain [DF.EXAMPLE.JP] does not pass DMARC verification and has a DMARC policy of reject. [TYCP286MB3363.JPNP286.PROD.OUTLOOK.COM 2024-06-11T09:04:02.679Z 08DC8850F12E1502] [MW4PR04CA0381.namprd04.prod.outlook.com 2024-06-11T09:04:02.743Z 08DC87B4931D8FD2] [CO1PEPF000066EC.namprd05.prod.outlook.com 2024-06-11T09:04:02.731Z 08DC89E7235090DB]
18
+
19
+ Message headers follow.
20
+
21
+ Received: from root (uid 0)
22
+ (envelope-from kijitora@df.example.jp)
23
+ id e06d1
24
+ by df.example.jp (DragonFly Mail Agent v0.13);
25
+ Tue, 11 Jun 2024 18:04:00 +0900
26
+ Subject: Nyaan 01
27
+ To: <pseudo-local-part@outlook.example.com>
28
+ User-Agent: mail (GNU Mailutils 3.14)
29
+ Date: Tue, 11 Jun 2024 18:04:00 +0900
30
+ Message-Id: <66681300.e06d1.6964aaf9@df.example.jp>
31
+ From: <kijitora@df.example.jp>
32
+
@@ -0,0 +1,32 @@
1
+ Received: from MAILER-DAEMON
2
+ id e0720
3
+ by df.example.jp (DragonFly Mail Agent v0.13);
4
+ Tue, 11 Jun 2024 18:09:35 +0900
5
+ X-Original-To: <pseudo-local-part@yahoo-inc.example.com>
6
+ From: MAILER-DAEMON <>
7
+ To: kijitora@df.example.jp
8
+ Subject: Mail delivery failed
9
+ Message-Id: <e0720@df.example.jp>
10
+ Date: Tue, 11 Jun 2024 18:09:35 +0900
11
+
12
+ This is the DragonFly Mail Agent v0.13 at df.example.jp.
13
+
14
+ There was an error delivering your mail to <pseudo-local-part@yahoo-inc.example.com>.
15
+
16
+ mta5.am0.yahoodns.net [67.195.204.79] did not like our final DATA:
17
+ 554 5.7.9 Message not accepted for policy reasons. See https://senders.yahooinc.com/error-codes
18
+
19
+ Message headers follow.
20
+
21
+ Received: from root (uid 0)
22
+ (envelope-from kijitora@df.example.jp)
23
+ id e06d1
24
+ by df.example.jp (DragonFly Mail Agent v0.13);
25
+ Tue, 11 Jun 2024 18:09:33 +0900
26
+ Subject: Nyaan 01
27
+ To: <pseudo-local-part@yahoo-inc.example.com>
28
+ User-Agent: mail (GNU Mailutils 3.14)
29
+ Date: Tue, 11 Jun 2024 18:09:33 +0900
30
+ Message-Id: <6668144d.e06d1.1bdca37a@df.example.jp>
31
+ From: <kijitora@df.example.jp>
32
+