sisimai 5.1.0 → 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 (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,125 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::Aol decodes a bounce email which created by Aol Mail https://mail.aol.com/.
3
- # Methods in the module are called from only Sisimai::Message.
4
- module Aol
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Content-Type: message/rfc822'].freeze
10
- StartingOf = { message: ['Content-Type: message/delivery-status'] }.freeze
11
- MessagesOf = {
12
- 'hostunknown' => ['Host or domain name not found'],
13
- 'notaccept' => ['type=MX: Malformed or unexpected name server reply'],
14
- }.freeze
15
-
16
- # @abstract Decodes the bounce message from Aol Mail
17
- # @param [Hash] mhead Message headers of a bounce email
18
- # @param [String] mbody Message body of a bounce email
19
- # @return [Hash] Bounce data list and message/rfc822 part
20
- # @return [Nil] it failed to decode or the arguments are missing
21
- def inquire(mhead, mbody)
22
- # X-AOL-IP: 192.0.2.135
23
- # X-AOL-VSS-INFO: 5600.1067/98281
24
- # X-AOL-VSS-CODE: clean
25
- # x-aol-sid: 3039ac1afc14546fb98a0945
26
- # X-AOL-SCOLL-EIL: 1
27
- # x-aol-global-disposition: G
28
- # x-aol-sid: 3039ac1afd4d546fb97d75c6
29
- # X-BounceIO-Id: 9D38DE46-21BC-4309-83E1-5F0D788EFF1F.1_0
30
- # X-Outbound-Mail-Relay-Queue-ID: 07391702BF4DC
31
- # X-Outbound-Mail-Relay-Sender: rfc822; shironeko@aol.example.jp
32
- return nil unless mhead['x-aol-ip']
33
-
34
- fieldtable = Sisimai::RFC1894.FIELDTABLE
35
- permessage = {} # (Hash) Store values of each Per-Message field
36
-
37
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
38
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
39
- bodyslices = emailparts[0].split("\n")
40
- readslices = ['']
41
- readcursor = 0 # (Integer) Points the current cursor position
42
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
43
- v = nil
44
-
45
- while e = bodyslices.shift do
46
- # Read error messages and delivery status lines from the head of the email to the previous
47
- # line of the beginning of the original message.
48
- readslices << e # Save the current line for the next loop
49
-
50
- if readcursor == 0
51
- # Beginning of the bounce message or message/delivery-status part
52
- readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
53
- next
54
- end
55
- next if (readcursor & Indicators[:deliverystatus]) == 0
56
- next if e.empty?
57
-
58
- if f = Sisimai::RFC1894.match(e)
59
- # "e" matched with any field defined in RFC3464
60
- next unless o = Sisimai::RFC1894.field(e)
61
- v = dscontents[-1]
62
-
63
- if o[-1] == 'addr'
64
- # Final-Recipient: rfc822; kijitora@example.jp
65
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
66
- if o[0] == 'final-recipient'
67
- # Final-Recipient: rfc822; kijitora@example.jp
68
- if v['recipient']
69
- # There are multiple recipient addresses in the message body.
70
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
71
- v = dscontents[-1]
72
- end
73
- v['recipient'] = o[2]
74
- recipients += 1
75
- else
76
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
77
- v['alias'] = o[2]
78
- end
79
- elsif o[-1] == 'code'
80
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
81
- v['spec'] = o[1]
82
- v['diagnosis'] = o[2]
83
- else
84
- # Other DSN fields defined in RFC3464
85
- next unless fieldtable[o[0]]
86
- v[fieldtable[o[0]]] = o[2]
87
-
88
- next unless f
89
- permessage[fieldtable[o[0]]] = o[2]
90
- end
91
- else
92
- # Continued line of the value of Diagnostic-Code field
93
- next unless readslices[-2].start_with?('Diagnostic-Code:')
94
- next unless e.start_with?(' ')
95
- v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
96
- readslices[-1] = 'Diagnostic-Code: ' << e
97
- end
98
- end
99
- return nil unless recipients > 0
100
-
101
- dscontents.each do |e|
102
- # Set default values if each value is empty.
103
- permessage.each_key { |a| e[a] ||= permessage[a] || '' }
104
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
105
-
106
- MessagesOf.each_key do |r|
107
- # Verify each regular expression of session errors
108
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
109
- e['reason'] = r
110
- break
111
- end
112
-
113
- if e['status'].empty? || e['status'].end_with?('.0.0')
114
- # There is no value of Status header or the value is 5.0.0, 4.0.0
115
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
116
- end
117
- end
118
-
119
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
120
- end
121
- def description; return 'Aol Mail: https://www.aol.com'; end
122
- end
123
- end
124
- end
125
-
@@ -1,92 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::Barracuda decodes a bounce email which created by Barracuda https://www.barracuda.com/.
3
- # Methods in the module are called from only Sisimai::Message.
4
- module Barracuda
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Content-Type: text/rfc822-headers'].freeze
10
- StartingOf = { message: ['Your message to:'] }.freeze
11
-
12
- # @abstract Decodes the bounce message from Barracuda
13
- # @param [Hash] mhead Message headers of a bounce email
14
- # @param [String] mbody Message body of a bounce email
15
- # @return [Hash] Bounce data list and message/rfc822 part
16
- # @return [Nil] it failed to decode or the arguments are missing
17
- # @since v4.25.6
18
- def inquire(mhead, mbody)
19
- # Subject: **Message you sent blocked by our bulk email filter**
20
- return nil unless mhead['subject'].to_s.end_with?('our bulk email filter**')
21
-
22
- fieldtable = Sisimai::RFC1894.FIELDTABLE
23
- permessage = {} # (Hash) Store values of each Per-Message field
24
-
25
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
26
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
27
- bodyslices = emailparts[0].split("\n")
28
- readcursor = 0 # (Integer) Points the current cursor position
29
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
30
- v = nil
31
-
32
- while e = bodyslices.shift do
33
- # Read error messages and delivery status lines from the head of the email to the previous
34
- # line of the beginning of the original message.
35
- if readcursor == 0
36
- # Beginning of the bounce message or message/delivery-status part
37
- readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
38
- next
39
- end
40
- next if (readcursor & Indicators[:deliverystatus]) == 0
41
- next if e.empty?
42
-
43
- if f = Sisimai::RFC1894.match(e)
44
- # "e" matched with any field defined in RFC3464
45
- next unless o = Sisimai::RFC1894.field(e)
46
- v = dscontents[-1]
47
-
48
- if o[-1] == 'addr'
49
- # Final-Recipient: rfc822; kijitora@example.jp
50
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
51
- if o[0] == 'final-recipient'
52
- # Final-Recipient: rfc822; kijitora@example.jp
53
- if v['recipient']
54
- # There are multiple recipient addresses in the message body.
55
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
56
- v = dscontents[-1]
57
- end
58
- v['recipient'] = o[2]
59
- recipients += 1
60
- else
61
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
62
- v['alias'] = o[2]
63
- end
64
- elsif o[-1] == 'code'
65
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
66
- v['spec'] = o[1]
67
- v['diagnosis'] = o[2]
68
- else
69
- # Other DSN fields defined in RFC3464
70
- next unless fieldtable[o[0]]
71
- v[fieldtable[o[0]]] = o[2]
72
-
73
- next unless f
74
- permessage[fieldtable[o[0]]] = o[2]
75
- end
76
- end
77
- end
78
- return nil unless recipients > 0
79
-
80
- dscontents.each do |e|
81
- # Set default values if each value is empty.
82
- permessage.each_key { |a| e[a] ||= permessage[a] || '' }
83
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].to_s.tr("\n", ' '))
84
- end
85
-
86
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
87
- end
88
- def description; return 'Barracuda: https://www.barracuda.com'; end
89
- end
90
- end
91
- end
92
-
@@ -1,125 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::Bigfoot decodes a bounce email which created by Bigfoot https://www.bigfoot.com/.
3
- # Methods in the module are called from only Sisimai::Message.
4
- module Bigfoot
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Content-Type: message/partial'].freeze
10
- MarkingsOf = { message: ' ----- Transcript of session follows -----' }.freeze
11
-
12
- # @abstract Decodes the bounce message from Bigfoot
13
- # @param [Hash] mhead Message headers of a bounce email
14
- # @param [String] mbody Message body of a bounce email
15
- # @return [Hash] Bounce data list and message/rfc822 part
16
- # @return [Nil] it failed to decode or the arguments are missing
17
- def inquire(mhead, mbody)
18
- # :subject => %r/\AReturned mail: /,
19
- match = 0
20
- match += 1 if mhead['from'].include?('@bigfoot.com>')
21
- match += 1 if mhead['received'].any? { |a| a.include?('.bigfoot.com') }
22
- return nil unless match > 0
23
-
24
- require 'sisimai/smtp/command'
25
- require 'sisimai/rfc1894'
26
- fieldtable = Sisimai::RFC1894.FIELDTABLE
27
- permessage = {} # (Hash) Store values of each Per-Message field
28
-
29
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
30
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
31
- bodyslices = emailparts[0].split("\n")
32
- readslices = ['']
33
- readcursor = 0 # (Integer) Points the current cursor position
34
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
35
- thecommand = '' # (String) SMTP Command name begin with the string '>>>'
36
- esmtpreply = '' # (String) Reply from remote server on SMTP session
37
- v = nil
38
-
39
- while e = bodyslices.shift do
40
- # Read error messages and delivery status lines from the head of the email to the previous
41
- # line of the beginning of the original message.
42
- readslices << e # Save the current line for the next loop
43
-
44
- if readcursor == 0
45
- # Beginning of the bounce message or message/delivery-status part
46
- readcursor |= Indicators[:deliverystatus] if e.start_with?(MarkingsOf[:message])
47
- next
48
- end
49
- next if (readcursor & Indicators[:deliverystatus]) == 0
50
- next if e.empty?
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
- next unless f
83
- permessage[fieldtable[o[0]]] = o[2]
84
- end
85
- else
86
- # The line does not begin with a DSN field defined in RFC3464
87
- unless e.start_with?(' ')
88
- # ----- Transcript of session follows -----
89
- # >>> RCPT TO:<destinaion@example.net>
90
- # <<< 553 Invalid recipient destinaion@example.net (Mode: normal)
91
- if e.start_with?('>>> ')
92
- # >>> DATA
93
- thecommand = Sisimai::SMTP::Command.find(e)
94
- elsif e.start_with?('<<< ')
95
- # <<< Response
96
- esmtpreply = e[4, e.size - 4]
97
- end
98
- else
99
- # Continued line of the value of Diagnostic-Code field
100
- next unless readslices[-2].start_with?('Diagnostic-Code:')
101
- next unless e.start_with?(' ')
102
- v['diagnosis'] << ' ' << Sisimai::String.sweep(e[1, e.size])
103
- readslices[-1] = 'Diagnostic-Code: ' << e
104
- end
105
- end
106
- end
107
- return nil unless recipients > 0
108
-
109
- dscontents.each do |e|
110
- # Set default values if each value is empty.
111
- permessage.each_key { |a| e[a] ||= permessage[a] || '' }
112
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
113
- e['command'] = thecommand || ''
114
- if e['command'].empty?
115
- e['command'] = 'EHLO' unless esmtpreply.empty?
116
- end
117
- end
118
-
119
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
120
- end
121
- def description; return 'Bigfoot: http://www.bigfoot.com'; end
122
- end
123
- end
124
- end
125
-
@@ -1,188 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::Facebook decodes a bounce email which created by Facebook https://www.facebook.com.
3
- # Methods in the module 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
- # @abstract Decodes the bounce message 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 decode 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
-