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
@@ -1,188 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::Facebook parses a bounce email which created by Facebook. Methods in the module
3
- # are called from only Sisimai::Message.
4
- module Facebook
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Content-Disposition: inline'].freeze
10
- StartingOf = { message: ['This message was created automatically by Facebook.'] }.freeze
11
- ReFailures = {
12
- # http://postmaster.facebook.com/response_codes
13
- # NOT TESTD EXCEPT RCP-P2
14
- 'userunknown' => [
15
- 'RCP-P1', # The attempted recipient address does not exist.
16
- 'INT-P1', # The attempted recipient address does not exist.
17
- 'INT-P3', # The attempted recpient group address does not exist.
18
- 'INT-P4', # The attempted recipient address does not exist.
19
- ],
20
- 'filtered' => [
21
- 'RCP-P2', # The attempted recipient's preferences prevent messages from being delivered.
22
- 'RCP-P3', # The attempted recipient's privacy settings blocked the delivery.
23
- ],
24
- 'mesgtoobig' => [
25
- 'MSG-P1', # The message exceeds Facebook's maximum allowed size.
26
- 'INT-P2', # The message exceeds Facebook's maximum allowed size.
27
- ],
28
- 'contenterror' => [
29
- 'MSG-P2', # The message contains an attachment type that Facebook does not accept.
30
- 'MSG-P3', # The message contains multiple instances of a header field that can only be present once. Please see RFC 5322, section 3.6 for more information
31
- 'POL-P6', # The message contains a url that has been blocked by Facebook.
32
- 'POL-P7', # The message does not comply with Facebook's abuse policies and will not be accepted.
33
- ],
34
- 'securityerror' => [
35
- 'POL-P1', # Your mail server's IP Address is listed on the Spamhaus PBL.
36
- 'POL-P2', # Facebook will no longer accept mail from your mail server's IP Address.
37
- 'POL-P5', # The message contains a virus.
38
- 'POL-P7', # The message does not comply with Facebook's Domain Authentication requirements.
39
- ],
40
- 'notaccept' => [
41
- 'POL-P3', # Facebook is not accepting messages from your mail server. This will persist for 4 to 8 hours.
42
- 'POL-P4', # Facebook is not accepting messages from your mail server. This will persist for 24 to 48 hours.
43
- 'POL-T1', # Facebook is not accepting messages from your mail server, but they may be retried later. This will persist for 1 to 2 hours.
44
- 'POL-T2', # Facebook is not accepting messages from your mail server, but they may be retried later. This will persist for 4 to 8 hours.
45
- 'POL-T3', # Facebook is not accepting messages from your mail server, but they may be retried later. This will persist for 24 to 48 hours.
46
- ],
47
- 'rejected' => [
48
- 'DNS-P1', # Your SMTP MAIL FROM domain does not exist.
49
- 'DNS-P2', # Your SMTP MAIL FROM domain does not have an MX record.
50
- 'DNS-T1', # Your SMTP MAIL FROM domain exists but does not currently resolve.
51
- 'DNS-P3', # Your mail server does not have a reverse DNS record.
52
- 'DNS-T2', # You mail server's reverse DNS record does not currently resolve.
53
- ],
54
- 'systemerror' => [
55
- 'CON-T1', # Facebook's mail server currently has too many connections open to allow another one.
56
- ],
57
- 'toomanyconn' => [
58
- 'CON-T3', # Your mail server has opened too many new connections to Facebook's mail servers in a short period of time.
59
- ],
60
- 'suspend' => [
61
- 'RCP-T4', # The attempted recipient address is currently deactivated. The user may or may not reactivate it.
62
- ],
63
- 'undefined' => [
64
- 'RCP-T1', # The attempted recipient address is not currently available due to an internal system issue. This is a temporary condition.
65
- 'MSG-T1', # The number of recipients on the message exceeds Facebook's allowed maximum.
66
- 'CON-T2', # Your mail server currently has too many connections open to Facebook's mail servers.
67
- 'CON-T4', # Your mail server has exceeded the maximum number of recipients for its current connection.
68
- ],
69
- }.freeze
70
-
71
- # Parse bounce messages from Facebook
72
- # @param [Hash] mhead Message headers of a bounce email
73
- # @param [String] mbody Message body of a bounce email
74
- # @return [Hash] Bounce data list and message/rfc822 part
75
- # @return [Nil] it failed to parse or the arguments are missing
76
- def inquire(mhead, mbody)
77
- return nil unless mhead['from'] == 'Facebook <mailer-daemon@mx.facebook.com>'
78
- return nil unless mhead['subject'] == 'Sorry, your message could not be delivered'
79
-
80
- fieldtable = Sisimai::RFC1894.FIELDTABLE
81
- permessage = {} # (Hash) Store values of each Per-Message field
82
-
83
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
84
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
85
- bodyslices = emailparts[0].split("\n")
86
- readslices = ['']
87
- readcursor = 0 # (Integer) Points the current cursor position
88
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
89
- fbresponse = '' # (String) Response code from Facebook
90
- v = nil
91
-
92
- while e = bodyslices.shift do
93
- # Read error messages and delivery status lines from the head of the email to the previous
94
- # line of the beginning of the original message.
95
- readslices << e # Save the current line for the next loop
96
-
97
- if readcursor == 0
98
- # Beginning of the bounce message or message/delivery-status part
99
- readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
100
- next
101
- end
102
- next if (readcursor & Indicators[:deliverystatus]) == 0
103
- next if e.empty?
104
-
105
- if f = Sisimai::RFC1894.match(e)
106
- # "e" matched with any field defined in RFC3464
107
- o = Sisimai::RFC1894.field(e) || next
108
- v = dscontents[-1]
109
-
110
- if o[-1] == 'addr'
111
- # Final-Recipient: rfc822; kijitora@example.jp
112
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
113
- if o[0] == 'final-recipient'
114
- # Final-Recipient: rfc822; kijitora@example.jp
115
- if v['recipient']
116
- # There are multiple recipient addresses in the message body.
117
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
118
- v = dscontents[-1]
119
- end
120
- v['recipient'] = o[2]
121
- recipients += 1
122
- else
123
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
124
- v['alias'] = o[2]
125
- end
126
- elsif o[-1] == 'code'
127
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
128
- v['spec'] = o[1]
129
- v['diagnosis'] = o[2]
130
- else
131
- # Other DSN fields defined in RFC3464
132
- next unless fieldtable[o[0]]
133
- v[fieldtable[o[0]]] = o[2]
134
-
135
- next unless f
136
- permessage[fieldtable[o[0]]] = o[2]
137
- end
138
- else
139
- # Continued line of the value of Diagnostic-Code field
140
- next unless readslices[-2].start_with?('Diagnostic-Code:')
141
- next unless e.start_with?(' ')
142
- v['diagnosis'] << ' ' << e[e.rindex(' ') + 1, e.size]
143
- readslices[-1] = 'Diagnostic-Code: ' << e
144
- end
145
- end
146
- return nil unless recipients > 0
147
-
148
- dscontents.each do |e|
149
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
150
-
151
- p0 = e['diagnosis'].index('-') || -1
152
- fbresponse = e['diagnosis'][p0 - 3, 6] if p0 > 0
153
-
154
- catch :SESSION do
155
- ReFailures.each_key do |r|
156
- # Verify each regular expression of session errors
157
- ReFailures[r].each do |rr|
158
- # Check each regular expression
159
- next unless fbresponse == rr
160
- e['reason'] = r
161
- throw :SESSION
162
- end
163
- end
164
- end
165
-
166
- # http://postmaster.facebook.com/response_codes
167
- # Facebook System Resource Issues
168
- # These codes indicate a temporary issue internal to Facebook's
169
- # system. Administrators observing these issues are not required to
170
- # take any action to correct them.
171
- next if e['reason']
172
-
173
- # * INT-Tx
174
- #
175
- # https://groups.google.com/forum/#!topic/cdmix/eXfi4ddgYLQ
176
- # This block has not been tested because we have no email sample
177
- # including "INT-T?" error code.
178
- next unless fbresponse.start_with?('INT-T')
179
- e['reason'] = 'systemerror'
180
- end
181
-
182
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
183
- end
184
- def description; return 'Facebook: https://www.facebook.com'; end
185
- end
186
- end
187
- end
188
-
@@ -1,194 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::GSuite parses a bounce email which created by G Suite. Methods in the module are
3
- # called from only Sisimai::Message.
4
- module GSuite
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Content-Type: message/rfc822', 'Content-Type: text/rfc822-headers'].freeze
10
- MarkingsOf = {
11
- message: ['** '],
12
- error: ['The response was:', 'The response from the remote server was:'],
13
- }.freeze
14
- MessagesOf = {
15
- 'userunknown' => ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
16
- 'notaccept' => ['Null MX'],
17
- 'networkerror' => [' had no relevant answers.', ' responded with code NXDOMAIN'],
18
- }.freeze
19
-
20
- # Parse bounce messages from G Suite (Transfer from G Suite to a destinaion host)
21
- # @param [Hash] mhead Message headers of a bounce email
22
- # @param [String] mbody Message body of a bounce email
23
- # @return [Hash] Bounce data list and message/rfc822 part
24
- # @return [Nil] it failed to parse or the arguments are missing
25
- def inquire(mhead, mbody)
26
- return nil unless mhead['from'].end_with?('<mailer-daemon@googlemail.com>')
27
- return nil unless mhead['subject'].start_with?('Delivery Status Notification')
28
- return nil unless mhead['x-gm-message-state']
29
-
30
- fieldtable = Sisimai::RFC1894.FIELDTABLE
31
- permessage = {} # (Hash) Store values of each Per-Message field
32
-
33
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
34
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
35
- bodyslices = emailparts[0].split("\n")
36
- readcursor = 0 # (Integer) Points the current cursor position
37
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
38
- endoferror = false # (Integer) Flag for a blank line after error messages
39
- anotherset = {} # (Hash) Another error information
40
- emptylines = 0 # (Integer) The number of empty lines
41
- v = nil
42
-
43
- while e = bodyslices.shift do
44
- # Read error messages and delivery status lines from the head of the email to the previous
45
- # line of the beginning of the original message.
46
- if readcursor == 0
47
- # Beginning of the bounce message or message/delivery-status part
48
- readcursor |= Indicators[:deliverystatus] if MarkingsOf[:message].any? { |a| e.start_with?(a) }
49
- end
50
- next if (readcursor & Indicators[:deliverystatus]) == 0
51
-
52
- if f = Sisimai::RFC1894.match(e)
53
- # "e" matched with any field defined in RFC3464
54
- next unless o = Sisimai::RFC1894.field(e)
55
- v = dscontents[-1]
56
-
57
- if o[-1] == 'addr'
58
- # Final-Recipient: rfc822; kijitora@example.jp
59
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
60
- if o[0] == 'final-recipient'
61
- # Final-Recipient: rfc822; kijitora@example.jp
62
- if v['recipient']
63
- # There are multiple recipient addresses in the message body.
64
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
65
- v = dscontents[-1]
66
- end
67
- v['recipient'] = o[2]
68
- recipients += 1
69
- else
70
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
71
- v['alias'] = o[2]
72
- end
73
- elsif o[-1] == 'code'
74
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
75
- v['spec'] = o[1]
76
- v['diagnosis'] = o[2]
77
- else
78
- # Other DSN fields defined in RFC3464
79
- next unless fieldtable[o[0]]
80
- v[fieldtable[o[0]]] = o[2]
81
-
82
- if fieldtable[o[0]] == 'lhost'
83
- # Do not set an email address as a hostname in "lhost" value
84
- v['lhost'] = '' if v['lhost'].include?('@')
85
- end
86
-
87
- next unless f
88
- permessage[fieldtable[o[0]]] = o[2]
89
- end
90
- else
91
- # The line does not begin with a DSN field defined in RFC3464 Append error messages continued
92
- # from the previous line
93
- if endoferror == false && v && ! v['diagnosis'].to_s.empty?
94
- endoferror ||= true if e.empty?
95
-
96
- next if endoferror
97
- next unless e.start_with?(' ')
98
- v['diagnosis'] << e
99
-
100
- elsif MarkingsOf[:error].any? { |a| e.start_with?(a) }
101
- # Detect SMTP session error or connection error
102
- # The response from the remote server was:
103
- anotherset['diagnosis'] << ' ' << e
104
- else
105
- # ** Address not found **
106
- #
107
- # Your message wasn't delivered to * because the address couldn't be found.
108
- # Check for typos or unnecessary spaces and try again.
109
- #
110
- # The response from the remote server was:
111
- # 550 #5.1.0 Address rejected.
112
- next if e.start_with?('Content-Type:')
113
- if anotherset['diagnosis']
114
- # Continued error messages from the previous line like "550 #5.1.0 Address rejected."
115
- next if emptylines > 5
116
- if e.empty?
117
- # Count and next()
118
- emptylines += 1
119
- next
120
- end
121
- anotherset['diagnosis'] << ' ' << e
122
- else
123
- # ** Address not found **
124
- #
125
- # Your message wasn't delivered to * because the address couldn't be found.
126
- # Check for typos or unnecessary spaces and try again.
127
- next if e.empty?
128
- next unless MarkingsOf[:message].any? { |a| e.start_with?(a) }
129
- anotherset['diagnosis'] = e
130
- end
131
- end
132
- end
133
- end
134
- return nil unless recipients > 0
135
-
136
- dscontents.each do |e|
137
- # Set default values if each value is empty.
138
- permessage.each_key { |a| e[a] ||= permessage[a] || '' }
139
-
140
- if anotherset['diagnosis']
141
- # Copy alternative error message
142
- e['diagnosis'] = anotherset['diagnosis'] unless e['diagnosis']
143
-
144
- if e['diagnosis'].include?(' ') == false && e['diagnosis'].to_i > 0
145
- e['diagnosis'] = anotherset['diagnosis']
146
- else
147
- # More detailed error message is in "anotherset"
148
- as = nil # status
149
- ar = nil # replycode
150
-
151
- e['status'] ||= ''
152
- e['replycode'] ||= ''
153
-
154
- if e['status'] == '' || e['status'].start_with?('4.0.0', '5.0.0')
155
- # Check the value of D.S.N. in anotherset
156
- as = Sisimai::SMTP::Status.find(anotherset['diagnosis'])
157
- if as && as[-3, 3] != '0.0'
158
- # The D.S.N. is neither an empty nor *.0.0
159
- e['status'] = as
160
- end
161
- end
162
-
163
- if e['replycode'].empty? || e['replycode'].start_with?('400', '500')
164
- # Check the value of SMTP reply code in anotherset
165
- ar = Sisimai::SMTP::Reply.find(anotherset['diagnosis'])
166
- if ar && ar[-2, 2].to_i != 0
167
- # The SMTP reply code is neither an empty nor *00
168
- e['replycode'] = ar
169
- end
170
- end
171
-
172
- if (as || ar) && (anotherset['diagnosis'].size > e['diagnosis'].size)
173
- # Update the error message in e['diagnosis']
174
- e['diagnosis'] = anotherset['diagnosis']
175
- end
176
- end
177
- end
178
-
179
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
180
- MessagesOf.each_key do |r|
181
- # Guess an reason of the bounce
182
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
183
- e['reason'] = r
184
- break
185
- end
186
- end
187
-
188
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
189
- end
190
- def description; return 'G Suite: https://gsuite.google.com'; end
191
- end
192
- end
193
- end
194
-
@@ -1,214 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::MailRu parses a bounce email which created by @mail.ru. Methods in the module are
3
- # called from only Sisimai::Message.
4
- module MailRu
5
- class << self
6
- # Based on Sisimai::Lhost::Exim
7
- require 'sisimai/lhost'
8
-
9
- Indicators = Sisimai::Lhost.INDICATORS
10
- Boundaries = ['------ This is a copy of the message, including all the headers. ------'].freeze
11
- StartingOf = { message: ['This message was created automatically by mail delivery software.'] }.freeze
12
- ReCommands = [
13
- %r/SMTP error from remote (?:mail server|mailer) after ([A-Za-z]{4})/,
14
- %r/SMTP error from remote (?:mail server|mailer) after end of ([A-Za-z]{4})/,
15
- ].freeze
16
- MessagesOf = {
17
- 'expired' => [
18
- 'retry timeout exceeded',
19
- 'No action is required on your part',
20
- ],
21
- 'userunknown' => ['user not found'],
22
- 'hostunknown' => [
23
- 'all host address lookups failed permanently',
24
- 'all relevant MX records point to non-existent hosts',
25
- 'Unrouteable address',
26
- ],
27
- 'mailboxfull' => ['mailbox is full', 'error: quota exceed'],
28
- 'notaccept' => [
29
- 'an MX or SRV record indicated no SMTP service',
30
- 'no host found for existing SMTP connection',
31
- ],
32
- 'syntaxerror' => [
33
- 'angle-brackets nested too deep',
34
- 'expected word or "<"',
35
- 'domain missing in source-routed address',
36
- 'malformed address:',
37
- ],
38
- 'systemerror' => [
39
- 'delivery to file forbidden',
40
- 'delivery to pipe forbidden',
41
- 'local delivery failed',
42
- 'LMTP error after ',
43
- ],
44
- 'contenterror' => ['Too many "Received" headers'],
45
- }.freeze
46
-
47
- # Parse bounce messages from @mail.ru
48
- # @param [Hash] mhead Message headers of a bounce email
49
- # @param [String] mbody Message body of a bounce email
50
- # @return [Hash] Bounce data list and message/rfc822 part
51
- # @return [Nil] it failed to parse or the arguments are missing
52
- def inquire(mhead, mbody)
53
- mfrom = mhead['from'].downcase
54
- msgid = mhead['message-id'] ? mhead['message-id'].downcase : ''
55
- match = 0
56
- match += 1 if mfrom.include?('mailer-daemon@') && mfrom.include?('mail.ru')
57
- match += 1 if msgid.end_with?('.mail.ru>', 'smailru.net>')
58
- match += 1 if [
59
- 'Delivery Status Notification',
60
- 'Mail delivery failed',
61
- 'Mail failure',
62
- 'Message frozen',
63
- 'Warning: message ',
64
- 'error(s) in forwarding or filtering'].any? { |a| mhead['subject'].include?(a) }
65
- return nil unless match > 2
66
-
67
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
68
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
69
- bodyslices = emailparts[0].split("\n")
70
- readcursor = 0 # (Integer) Points the current cursor position
71
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
72
- v = nil
73
-
74
- while e = bodyslices.shift do
75
- # Read error messages and delivery status lines from the head of the email to the previous
76
- # line of the beginning of the original message.
77
- if readcursor == 0
78
- # Beginning of the bounce message or delivery status part
79
- readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
80
- next
81
- end
82
- next if (readcursor & Indicators[:deliverystatus]) == 0
83
- next if e.empty?
84
-
85
- # Это письмо создано автоматически
86
- # сервером Mail.Ru, # отвечать на него не
87
- # нужно.
88
- #
89
- # К сожалению, Ваше письмо не может
90
- # быть# доставлено одному или нескольким
91
- # получателям:
92
- #
93
- # **********************
94
- #
95
- # This message was created automatically by mail delivery software.
96
- #
97
- # A message that you sent could not be delivered to one or more of its
98
- # recipients. This is a permanent error. The following address(es) failed:
99
- #
100
- # kijitora@example.jp
101
- # SMTP error from remote mail server after RCPT TO:<kijitora@example.jp>:
102
- # host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
103
- v = dscontents[-1]
104
-
105
- if e.start_with?(' ') && e.include?(' ') == false && e.index('@') > 1
106
- # kijitora@example.jp
107
- if v['recipient']
108
- # There are multiple recipient addresses in the message body.
109
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
110
- v = dscontents[-1]
111
- end
112
- v['recipient'] = e[2, e.size]
113
- recipients += 1
114
-
115
- elsif dscontents.size == recipients
116
- # Error message
117
- next if e.empty?
118
- v['diagnosis'] ||= ''
119
- v['diagnosis'] << e + ' '
120
- else
121
- # Error message when email address above does not include '@'
122
- # and domain part.
123
- next unless e.start_with?(' ')
124
- v['alterrors'] ||= ''
125
- v['alterrors'] << e + ' '
126
- end
127
- end
128
-
129
- unless recipients > 0
130
- # Fallback for getting recipient addresses
131
- if mhead['x-failed-recipients']
132
- # X-Failed-Recipients: kijitora@example.jp
133
- rcptinhead = mhead['x-failed-recipients'].split(',')
134
- rcptinhead.each { |a| a.delete(' ') }
135
- recipients = rcptinhead.size
136
-
137
- while e = rcptinhead.shift do
138
- # Insert each recipient address into dscontents
139
- dscontents[-1]['recipient'] = e
140
- next if dscontents.size == recipients
141
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
142
- end
143
- end
144
- end
145
- return nil unless recipients > 0
146
-
147
- # Get the name of the local MTA
148
- # Received: from marutamachi.example.org (c192128.example.net [192.0.2.128])
149
- receivedby = mhead['received'] || []
150
- recvdtoken = Sisimai::RFC5322.received(receivedby[-1])
151
-
152
- dscontents.each do |e|
153
- # Check the error message, the rhost, the lhost, and the smtp command.
154
- unless e['alterrors'].to_s.empty?
155
- # Copy alternative error message
156
- e['diagnosis'] ||= e['alterrors']
157
- if e['diagnosis'].start_with?('-') || e['diagnosis'].end_with?('__')
158
- # Override the value of diagnostic code message
159
- e['diagnosis'] = e['alterrors'] unless e['alterrors'].empty?
160
- end
161
- e.delete('alterrors')
162
- end
163
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
164
- p1 = e['diagnosis'].rindex('__') || -1
165
- e['diagnosis'] = e['diagnosis'][0, p1 - 1] if p1 > 2
166
-
167
- unless e['rhost']
168
- # Get the remote host name
169
- # host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
170
- p1 = e['diagnosis'].index('host ') || -1
171
- p2 = e['diagnosis'].index(' ', p1 + 5) || -1
172
- e['rhost'] = e['diagnosis'][p1 + 5, p2 - p1 - 5] if p1 > -1
173
- e['rhost'] ||= recvdtoken[1]
174
- end
175
- e['lhost'] ||= recvdtoken[0]
176
-
177
- unless e['command']
178
- # Get the SMTP command name for the session
179
- ReCommands.each do |r|
180
- # Verify each regular expression of SMTP commands
181
- if cv = e['diagnosis'].match(r)
182
- e['command'] = cv[1].upcase
183
- break
184
- end
185
- end
186
-
187
- # Detect the reason of bounce
188
- if %w[HELO EHLO].index(e['command'])
189
- # HELO | Connected to 192.0.2.135 but my name was rejected.
190
- e['reason'] = 'blocked'
191
-
192
- elsif e['command'] == 'MAIL'
193
- # MAIL | Connected to 192.0.2.135 but sender was rejected.
194
- e['reason'] = 'rejected'
195
- else
196
- # Verify each regular expression of session errors
197
- MessagesOf.each_key do |r|
198
- # Check each regular expression
199
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
200
- e['reason'] = r
201
- break
202
- end
203
- end
204
- end
205
- e['command'] ||= ''
206
- end
207
-
208
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
209
- end
210
- def description; return '@mail.ru: https://mail.ru'; end
211
- end
212
- end
213
- end
214
-