sisimai 5.1.0-java → 5.2.0-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake-test.yml +1 -1
  3. data/ChangeLog.md +102 -0
  4. data/Makefile +4 -2
  5. data/README-JA.md +23 -16
  6. data/README.md +22 -15
  7. data/lib/sisimai/arf.rb +121 -210
  8. data/lib/sisimai/fact.rb +208 -158
  9. data/lib/sisimai/lda.rb +98 -0
  10. data/lib/sisimai/lhost/activehunter.rb +1 -1
  11. data/lib/sisimai/lhost/amazonses.rb +185 -301
  12. data/lib/sisimai/lhost/apachejames.rb +48 -51
  13. data/lib/sisimai/lhost/biglobe.rb +1 -2
  14. data/lib/sisimai/lhost/courier.rb +10 -8
  15. data/lib/sisimai/lhost/domino.rb +25 -25
  16. data/lib/sisimai/lhost/dragonfly.rb +3 -4
  17. data/lib/sisimai/lhost/einsundeins.rb +3 -4
  18. data/lib/sisimai/lhost/exchange2003.rb +6 -8
  19. data/lib/sisimai/lhost/exchange2007.rb +111 -101
  20. data/lib/sisimai/lhost/exim.rb +232 -242
  21. data/lib/sisimai/lhost/ezweb.rb +43 -51
  22. data/lib/sisimai/lhost/fml.rb +2 -3
  23. data/lib/sisimai/lhost/gmail.rb +32 -28
  24. data/lib/sisimai/lhost/gmx.rb +4 -16
  25. data/lib/sisimai/lhost/googlegroups.rb +9 -8
  26. data/lib/sisimai/lhost/googleworkspace.rb +94 -0
  27. data/lib/sisimai/lhost/imailserver.rb +7 -16
  28. data/lib/sisimai/lhost/interscanmss.rb +1 -1
  29. data/lib/sisimai/lhost/kddi.rb +3 -4
  30. data/lib/sisimai/lhost/mailfoundry.rb +2 -5
  31. data/lib/sisimai/lhost/mailmarshalsmtp.rb +1 -2
  32. data/lib/sisimai/lhost/messagingserver.rb +14 -13
  33. data/lib/sisimai/lhost/mfilter.rb +4 -3
  34. data/lib/sisimai/lhost/notes.rb +2 -4
  35. data/lib/sisimai/lhost/opensmtpd.rb +2 -2
  36. data/lib/sisimai/lhost/postfix.rb +25 -27
  37. data/lib/sisimai/lhost/qmail.rb +130 -106
  38. data/lib/sisimai/lhost/sendmail.rb +19 -18
  39. data/lib/sisimai/lhost/v5sendmail.rb +88 -60
  40. data/lib/sisimai/lhost/verizon.rb +2 -2
  41. data/lib/sisimai/lhost/x1.rb +1 -1
  42. data/lib/sisimai/lhost/x2.rb +1 -2
  43. data/lib/sisimai/lhost/x3.rb +2 -2
  44. data/lib/sisimai/lhost/x6.rb +1 -1
  45. data/lib/sisimai/lhost/zoho.rb +2 -2
  46. data/lib/sisimai/lhost.rb +18 -21
  47. data/lib/sisimai/message.rb +93 -146
  48. data/lib/sisimai/order.rb +21 -77
  49. data/lib/sisimai/reason/authfailure.rb +1 -4
  50. data/lib/sisimai/reason/badreputation.rb +2 -2
  51. data/lib/sisimai/reason/blocked.rb +7 -10
  52. data/lib/sisimai/reason/contenterror.rb +7 -1
  53. data/lib/sisimai/reason/exceedlimit.rb +1 -4
  54. data/lib/sisimai/reason/failedstarttls.rb +42 -0
  55. data/lib/sisimai/reason/filtered.rb +5 -4
  56. data/lib/sisimai/reason/hasmoved.rb +1 -2
  57. data/lib/sisimai/reason/hostunknown.rb +3 -3
  58. data/lib/sisimai/reason/mailboxfull.rb +2 -4
  59. data/lib/sisimai/reason/mailererror.rb +1 -2
  60. data/lib/sisimai/reason/mesgtoobig.rb +2 -4
  61. data/lib/sisimai/reason/norelaying.rb +2 -3
  62. data/lib/sisimai/reason/notaccept.rb +2 -3
  63. data/lib/sisimai/reason/notcompliantrfc.rb +10 -4
  64. data/lib/sisimai/reason/rejected.rb +1 -1
  65. data/lib/sisimai/reason/requireptr.rb +2 -2
  66. data/lib/sisimai/reason/securityerror.rb +1 -3
  67. data/lib/sisimai/reason/spamdetected.rb +6 -8
  68. data/lib/sisimai/reason/speeding.rb +1 -2
  69. data/lib/sisimai/reason/suppressed.rb +36 -0
  70. data/lib/sisimai/reason/suspend.rb +1 -3
  71. data/lib/sisimai/reason/systemerror.rb +5 -0
  72. data/lib/sisimai/reason/toomanyconn.rb +1 -2
  73. data/lib/sisimai/reason/userunknown.rb +1 -1
  74. data/lib/sisimai/reason/virusdetected.rb +5 -6
  75. data/lib/sisimai/reason.rb +77 -73
  76. data/lib/sisimai/rfc1123.rb +152 -0
  77. data/lib/sisimai/rfc1894.rb +102 -62
  78. data/lib/sisimai/rfc2045.rb +2 -1
  79. data/lib/sisimai/rfc3464/thirdparty.rb +102 -0
  80. data/lib/sisimai/rfc3464.rb +222 -343
  81. data/lib/sisimai/rfc3834.rb +1 -1
  82. data/lib/sisimai/rfc5322.rb +7 -17
  83. data/lib/sisimai/rfc791.rb +69 -0
  84. data/lib/sisimai/rhost/aol.rb +36 -0
  85. data/lib/sisimai/rhost/apple.rb +5 -2
  86. data/lib/sisimai/rhost/cox.rb +3 -2
  87. data/lib/sisimai/rhost/facebook.rb +100 -0
  88. data/lib/sisimai/rhost/franceptt.rb +3 -2
  89. data/lib/sisimai/rhost/godaddy.rb +3 -2
  90. data/lib/sisimai/rhost/google.rb +19 -17
  91. data/lib/sisimai/rhost/gsuite.rb +42 -0
  92. data/lib/sisimai/rhost/iua.rb +3 -3
  93. data/lib/sisimai/rhost/kddi.rb +3 -2
  94. data/lib/sisimai/rhost/messagelabs.rb +37 -0
  95. data/lib/sisimai/rhost/microsoft.rb +56 -49
  96. data/lib/sisimai/rhost/mimecast.rb +29 -27
  97. data/lib/sisimai/rhost/nttdocomo.rb +4 -3
  98. data/lib/sisimai/rhost/outlook.rb +36 -0
  99. data/lib/sisimai/rhost/spectrum.rb +3 -2
  100. data/lib/sisimai/rhost/tencent.rb +3 -2
  101. data/lib/sisimai/rhost/yahooinc.rb +4 -3
  102. data/lib/sisimai/rhost.rb +69 -39
  103. data/lib/sisimai/smtp/command.rb +31 -21
  104. data/lib/sisimai/smtp/failure.rb +103 -0
  105. data/lib/sisimai/smtp/reply.rb +29 -25
  106. data/lib/sisimai/smtp/status.rb +36 -19
  107. data/lib/sisimai/smtp/transcript.rb +15 -15
  108. data/lib/sisimai/string.rb +0 -46
  109. data/lib/sisimai/version.rb +1 -1
  110. data/set-of-emails/maildir/bsd/lhost-postfix-30.eml +81 -81
  111. data/set-of-emails/maildir/bsd/{lhost-aol-03.eml → rhost-aol-03.eml} +1264 -1264
  112. data/set-of-emails/maildir/bsd/{lhost-aol-04.eml → rhost-aol-04.eml} +1260 -1260
  113. data/set-of-emails/maildir/bsd/{lhost-aol-05.eml → rhost-aol-05.eml} +105 -105
  114. data/set-of-emails/maildir/bsd/{lhost-aol-06.eml → rhost-aol-06.eml} +105 -105
  115. data/set-of-emails/maildir/bsd/rhost-gsuite-01.eml +189 -0
  116. data/set-of-emails/maildir/bsd/rhost-gsuite-02.eml +180 -0
  117. data/set-of-emails/maildir/bsd/rhost-gsuite-03.eml +251 -0
  118. data/set-of-emails/maildir/bsd/rhost-gsuite-04.eml +211 -0
  119. data/set-of-emails/maildir/bsd/rhost-gsuite-05.eml +226 -0
  120. data/set-of-emails/maildir/bsd/rhost-gsuite-06.eml +257 -0
  121. data/set-of-emails/maildir/bsd/rhost-gsuite-07.eml +289 -0
  122. data/set-of-emails/maildir/bsd/rhost-gsuite-08.eml +231 -0
  123. data/set-of-emails/maildir/bsd/rhost-gsuite-09.eml +231 -0
  124. data/set-of-emails/maildir/bsd/rhost-gsuite-10.eml +254 -0
  125. data/set-of-emails/maildir/bsd/rhost-gsuite-11.eml +228 -0
  126. data/set-of-emails/maildir/bsd/rhost-gsuite-12.eml +271 -0
  127. data/set-of-emails/maildir/bsd/rhost-gsuite-13.eml +261 -0
  128. data/set-of-emails/maildir/bsd/rhost-gsuite-14.eml +273 -0
  129. data/set-of-emails/maildir/bsd/rhost-gsuite-15.eml +229 -0
  130. data/set-of-emails/maildir/bsd/{lhost-messagelabs-01.eml → rhost-messagelabs-01.eml} +93 -93
  131. data/set-of-emails/maildir/bsd/rhost-outlook-01.eml +72 -0
  132. data/set-of-emails/maildir/bsd/rhost-outlook-02.eml +72 -0
  133. data/set-of-emails/maildir/bsd/rhost-outlook-03.eml +72 -0
  134. data/set-of-emails/maildir/bsd/rhost-outlook-04.eml +79 -0
  135. data/set-of-emails/maildir/bsd/rhost-outlook-06.eml +75 -0
  136. data/set-of-emails/maildir/bsd/rhost-outlook-07.eml +70 -0
  137. data/set-of-emails/maildir/bsd/rhost-outlook-08.eml +70 -0
  138. data/set-of-emails/maildir/bsd/rhost-outlook-09.eml +56 -0
  139. data/set-of-emails/maildir/tmp/arf-22.eml +49 -0
  140. data/set-of-emails/maildir/tmp/arf-23.eml +49 -0
  141. data/set-of-emails/maildir/tmp/arf-24.eml +50 -0
  142. data/set-of-emails/maildir/tmp/lhost-exim-07.eml +28 -0
  143. metadata +73 -56
  144. data/lib/sisimai/lhost/amavis.rb +0 -163
  145. data/lib/sisimai/lhost/amazonworkmail.rb +0 -127
  146. data/lib/sisimai/lhost/aol.rb +0 -125
  147. data/lib/sisimai/lhost/barracuda.rb +0 -92
  148. data/lib/sisimai/lhost/bigfoot.rb +0 -125
  149. data/lib/sisimai/lhost/facebook.rb +0 -188
  150. data/lib/sisimai/lhost/gsuite.rb +0 -194
  151. data/lib/sisimai/lhost/mailru.rb +0 -214
  152. data/lib/sisimai/lhost/mcafee.rb +0 -109
  153. data/lib/sisimai/lhost/messagelabs.rb +0 -120
  154. data/lib/sisimai/lhost/mxlogic.rb +0 -198
  155. data/lib/sisimai/lhost/office365.rb +0 -252
  156. data/lib/sisimai/lhost/outlook.rb +0 -129
  157. data/lib/sisimai/lhost/powermta.rb +0 -118
  158. data/lib/sisimai/lhost/receivingses.rb +0 -126
  159. data/lib/sisimai/lhost/sendgrid.rb +0 -150
  160. data/lib/sisimai/lhost/surfcontrol.rb +0 -105
  161. data/lib/sisimai/lhost/x4.rb +0 -269
  162. data/lib/sisimai/lhost/x5.rb +0 -112
  163. data/lib/sisimai/lhost/yahoo.rb +0 -102
  164. data/lib/sisimai/lhost/yandex.rb +0 -118
  165. data/lib/sisimai/mda.rb +0 -121
  166. data/lib/sisimai/smtp/error.rb +0 -119
  167. /data/set-of-emails/maildir/bsd/{lhost-googlegroups-15.eml → lhost-googleworkspace-01.eml} +0 -0
  168. /data/set-of-emails/maildir/bsd/{lhost-x4-08.eml → lhost-x2-06.eml} +0 -0
  169. /data/set-of-emails/maildir/bsd/{lhost-gsuite-01.eml → rfc3464-51.eml} +0 -0
  170. /data/set-of-emails/maildir/bsd/{lhost-gsuite-03.eml → rfc3464-52.eml} +0 -0
  171. /data/set-of-emails/maildir/bsd/{lhost-gsuite-04.eml → rfc3464-53.eml} +0 -0
  172. /data/set-of-emails/maildir/bsd/{lhost-gsuite-05.eml → rfc3464-54.eml} +0 -0
  173. /data/set-of-emails/maildir/bsd/{lhost-gsuite-06.eml → rfc3464-55.eml} +0 -0
  174. /data/set-of-emails/maildir/bsd/{lhost-gsuite-07.eml → rfc3464-56.eml} +0 -0
  175. /data/set-of-emails/maildir/bsd/{lhost-gsuite-08.eml → rfc3464-57.eml} +0 -0
  176. /data/set-of-emails/maildir/bsd/{lhost-gsuite-09.eml → rfc3464-58.eml} +0 -0
  177. /data/set-of-emails/maildir/bsd/{lhost-gsuite-10.eml → rfc3464-59.eml} +0 -0
  178. /data/set-of-emails/maildir/bsd/{lhost-gsuite-11.eml → rfc3464-60.eml} +0 -0
  179. /data/set-of-emails/maildir/bsd/{lhost-gsuite-12.eml → rfc3464-61.eml} +0 -0
  180. /data/set-of-emails/maildir/bsd/{lhost-gsuite-13.eml → rfc3464-62.eml} +0 -0
  181. /data/set-of-emails/maildir/bsd/{lhost-gsuite-14.eml → rfc3464-63.eml} +0 -0
  182. /data/set-of-emails/maildir/bsd/{lhost-gsuite-15.eml → rfc3464-64.eml} +0 -0
  183. /data/set-of-emails/maildir/bsd/{lhost-gsuite-02.eml → rfc3464-65.eml} +0 -0
  184. /data/set-of-emails/maildir/bsd/{lhost-aol-01.eml → rhost-aol-01.eml} +0 -0
  185. /data/set-of-emails/maildir/bsd/{lhost-aol-02.eml → rhost-aol-02.eml} +0 -0
  186. /data/set-of-emails/maildir/bsd/{lhost-facebook-03.eml → rhost-facebook-03.eml} +0 -0
  187. /data/set-of-emails/maildir/bsd/{lhost-facebook-04.eml → rhost-facebook-04.eml} +0 -0
  188. /data/set-of-emails/maildir/bsd/{lhost-messagelabs-02.eml → rhost-messagelabs-02.eml} +0 -0
  189. /data/set-of-emails/maildir/bsd/{lhost-messagelabs-03.eml → rhost-messagelabs-03.eml} +0 -0
  190. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-37.eml +0 -0
  191. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-38.eml +0 -0
  192. /data/set-of-emails/maildir/{bsd → tmp}/rfc3464-39.eml +0 -0
@@ -1,118 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::PowerMTA decodes a bounce email which created by PowerMTA https://bird.com/email/power-mta.
3
- # Methods in the module are called from only Sisimai::Message.
4
- module PowerMTA
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Content-Type: text/rfc822-headers'].freeze
10
- StartingOf = { message: ['Hello, this is the mail server on '] }.freeze
11
- Categories = {
12
- 'bad-domain' => 'hostunknown',
13
- 'bad-mailbox' => 'userunknown',
14
- 'inactive-mailbox' => 'disabled',
15
- 'message-expired' => 'expired',
16
- 'no-answer-from-host' => 'networkerror',
17
- 'policy-related' => 'policyviolation',
18
- 'quota-issues' => 'mailboxfull',
19
- 'routing-errors' => 'systemerror',
20
- 'spam-related' => 'spamdetected',
21
- }.freeze
22
-
23
- # @abstract Decodes the bounce message from PowerMTA
24
- # @param [Hash] mhead Message headers of a bounce email
25
- # @param [String] mbody Message body of a bounce email
26
- # @return [Hash] Bounce data list and message/rfc822 part
27
- # @return [Nil] it failed to decode or the arguments are missing
28
- # @since v4.25.6
29
- def inquire(mhead, mbody)
30
- return nil unless mhead['subject'].to_s.start_with?('Delivery report')
31
-
32
- fieldtable = Sisimai::RFC1894.FIELDTABLE
33
- permessage = {} # (Hash) Store values of each Per-Message field
34
-
35
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
36
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
37
- bodyslices = emailparts[0].split("\n")
38
- readcursor = 0 # (Integer) Points the current cursor position
39
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
40
- v = nil
41
-
42
- while e = bodyslices.shift do
43
- # Read error messages and delivery status lines from the head of the email to the previous
44
- # line of the beginning of the original message.
45
- if readcursor == 0
46
- # Beginning of the bounce message or message/delivery-status part
47
- readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
48
- next
49
- end
50
- next if (readcursor & Indicators[:deliverystatus]) == 0
51
- next if e.empty?
52
-
53
- if f = Sisimai::RFC1894.match(e)
54
- # "e" matched with any field defined in RFC3464
55
- next unless o = Sisimai::RFC1894.field(e)
56
- v = dscontents[-1]
57
-
58
- if o[-1] == 'addr'
59
- # Final-Recipient: rfc822; kijitora@example.jp
60
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
61
- if o[0] == 'final-recipient'
62
- # Final-Recipient: rfc822; kijitora@example.jp
63
- if v['recipient']
64
- # There are multiple recipient addresses in the message body.
65
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
66
- v = dscontents[-1]
67
- end
68
- v['recipient'] = o[2]
69
- recipients += 1
70
- else
71
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
72
- v['alias'] = o[2]
73
- end
74
- elsif o[-1] == 'code'
75
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
76
- v['spec'] = o[1]
77
- v['diagnosis'] = o[2]
78
- else
79
- # Other DSN fields defined in RFC3464
80
- next unless fieldtable[o[0]]
81
- v[fieldtable[o[0]]] = o[2]
82
-
83
- next unless f
84
- permessage[fieldtable[o[0]]] = o[2]
85
- end
86
- else
87
- # Hello, this is the mail server on neko2.example.org.
88
- #
89
- # I am sending you this message to inform you on the delivery status of a
90
- # message you previously sent. Immediately below you will find a list of
91
- # the affected recipients; also attached is a Delivery Status Notification
92
- # (DSN) report in standard format, as well as the headers of the original
93
- # message.
94
- #
95
- # <kijitora@example.jp> delivery failed; will not continue trying
96
- #
97
- if e.start_with?('X-PowerMTA-BounceCategory: ')
98
- # X-PowerMTA-BounceCategory: bad-mailbox
99
- v['category'] = e[e.index(':') + 2, e.size]
100
- end
101
- end
102
- end
103
- return nil unless recipients > 0
104
-
105
- dscontents.each do |e|
106
- # Set default values if each value is empty.
107
- permessage.each_key { |a| e[a] ||= permessage[a] || '' }
108
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].to_s.tr("\n", ' '))
109
- e['reason'] = Categories[e['category']] || ''
110
- end
111
-
112
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
113
- end
114
- def description; return 'PowerMTA: https://www.sparkpost.com/powermta/'; end
115
- end
116
- end
117
- end
118
-
@@ -1,126 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::ReceivingSES decodes a bounce email which created by Amazon Simple Email Service
3
- # https://aws.amazon.com/ses. Methods in the module are called from only Sisimai::Message.
4
- module ReceivingSES
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- # https://aws.amazon.com/ses/
9
- Indicators = Sisimai::Lhost.INDICATORS
10
- Boundaries = ['Content-Type: text/rfc822-headers'].freeze
11
- StartingOf = { message: ['This message could not be delivered.'] }.freeze
12
- MessagesOf = {
13
- # The followings are error messages in Rule sets/*/Actions/Template
14
- 'filtered' => ['Mailbox does not exist'],
15
- 'mesgtoobig' => ['Message too large'],
16
- 'mailboxfull' => ['Mailbox full'],
17
- 'contenterror' => ['Message content rejected'],
18
- }.freeze
19
-
20
- # @abstract Decodes the bounce message from Amazon SES/Receiving
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 decode or the arguments are missing
25
- def inquire(mhead, mbody)
26
- # X-SES-Outgoing: 2015.10.01-54.240.27.7
27
- # Feedback-ID: 1.us-west-2.HX6/J9OVlHTadQhEu1+wdF9DBj6n6Pa9sW5Y/0pSOi8=:AmazonSES
28
- return nil unless mhead['x-ses-outgoing']
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
- readslices = ['']
37
- readcursor = 0 # (Integer) Points the current cursor position
38
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
39
- v = nil
40
-
41
- while e = bodyslices.shift do
42
- # Read error messages and delivery status lines from the head of the email to the previous
43
- # line of the beginning of the original message.
44
- readslices << e # Save the current line for the next loop
45
-
46
- if readcursor == 0
47
- # Beginning of the bounce message or message/delivery-status part
48
- readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
49
- next
50
- end
51
- next if (readcursor & Indicators[:deliverystatus]) == 0
52
- next if e.empty?
53
-
54
- if f = Sisimai::RFC1894.match(e)
55
- # "e" matched with any field defined in RFC3464
56
- next unless o = Sisimai::RFC1894.field(e)
57
- v = dscontents[-1]
58
-
59
- if o[-1] == 'addr'
60
- # Final-Recipient: rfc822; kijitora@example.jp
61
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
62
- if o[0] == 'final-recipient'
63
- # Final-Recipient: rfc822; kijitora@example.jp
64
- if v['recipient']
65
- # There are multiple recipient addresses in the message body.
66
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
67
- v = dscontents[-1]
68
- end
69
- v['recipient'] = o[2]
70
- recipients += 1
71
- else
72
- # X-Actual-Recipient: rfc822; kijitora@example.co.jp
73
- v['alias'] = o[2]
74
- end
75
- elsif o[-1] == 'code'
76
- # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
77
- v['spec'] = o[1]
78
- v['diagnosis'] = o[2]
79
- else
80
- # Other DSN fields defined in RFC3464
81
- next unless fieldtable[o[0]]
82
- v[fieldtable[o[0]]] = o[2]
83
-
84
- next unless f
85
- permessage[fieldtable[o[0]]] = o[2]
86
- end
87
- else
88
- # Continued line of the value of Diagnostic-Code field
89
- next unless readslices[-2].start_with?('Diagnostic-Code:')
90
- next unless e.start_with?(' ')
91
- v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
92
- readslices[-1] = 'Diagnostic-Code: ' << e
93
- end
94
- end
95
- return nil unless recipients > 0
96
-
97
- dscontents.each do |e|
98
- # Set default values if each value is empty.
99
- permessage.each_key { |a| e[a] ||= permessage[a] || '' }
100
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
101
-
102
- if e['status'].to_s.start_with?('5.0.0', '5.1.0', '4.0.0', '4.1.0')
103
- # Get other D.S.N. value from the error message
104
- errormessage = e['diagnosis']
105
- p1 = e['diagnosis'].index("-'"); p1 = e['diagnosis'].index('-"') unless p1
106
- p2 = e['diagnosis'].rindex("' "); p2 = e['diagnosis'].rindex('" ') unless p2
107
- errormessage = e['diagnosis'][p1 + 2, p2 - p1 - 2] if p1 && p2
108
- e['status'] = Sisimai::SMTP::Status.find(errormessage) || e['status']
109
- end
110
-
111
- MessagesOf.each_key do |r|
112
- # Verify each regular expression of session errors
113
- next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
114
- e['reason'] = r
115
- break
116
- end
117
- e['reason'] ||= Sisimai::SMTP::Status.name(e['status']) || ''
118
- end
119
-
120
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
121
- end
122
- def description; return 'Amazon SES(Receiving): https://aws.amazon.com/ses/'; end
123
- end
124
- end
125
- end
126
-
@@ -1,150 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::SendGrid decodes a bounce email which created by Twilio SendGrid https://sendgrid.com/.
3
- # Methods in the module are called from only Sisimai::Message.
4
- module SendGrid
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Content-Type: message/rfc822'].freeze
10
- StartingOf = { message: ['This is an automatically generated message from SendGrid.'] }.freeze
11
-
12
- # @abstract Decodes the bounce message from Twilio SendGrid
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
- # Return-Path: <apps@sendgrid.net>
19
- # X-Mailer: MIME-tools 5.502 (Entity 5.502)
20
- return nil unless mhead['return-path']
21
- return nil unless mhead['return-path'] == '<apps@sendgrid.net>'
22
- return nil unless mhead['subject'] == 'Undelivered Mail Returned to Sender'
23
-
24
- require 'sisimai/smtp/command'
25
- fieldtable = Sisimai::RFC1894.FIELDTABLE
26
- permessage = {} # (Hash) Store values of each Per-Message field
27
-
28
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
29
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
30
- bodyslices = emailparts[0].split("\n")
31
- readslices = ['']
32
- readcursor = 0 # (Integer) Points the current cursor position
33
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
34
- thecommand = '' # (String) SMTP Command name begin with the string '>>>'
35
- v = nil
36
-
37
- while e = bodyslices.shift do
38
- # Read error messages and delivery status lines from the head of the email to the previous
39
- # line of the beginning of the original message.
40
- readslices << e # Save the current line for the next loop
41
-
42
- if readcursor == 0
43
- # Beginning of the bounce message or message/delivery-status part
44
- readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
45
- next
46
- end
47
- next if (readcursor & Indicators[:deliverystatus]) == 0
48
- next if e.empty?
49
-
50
- if f = Sisimai::RFC1894.match(e)
51
- # "e" matched with any field defined in RFC3464
52
- o = Sisimai::RFC1894.field(e)
53
- v = dscontents[-1]
54
-
55
- unless o
56
- # Fallback code for empty value or invalid formatted value
57
- # - Status: (empty)
58
- # - Diagnostic-Code: 550 5.1.1 ... (No "diagnostic-type" sub field)
59
- v['diagnosis'] = e[e.index(':') + 2, e.size] if e.start_with?('Diagnostic-Code: ')
60
- next
61
- end
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
- elsif o[-1] == 'date'
84
- # Arrival-Date: 2012-12-31 23-59-59
85
- next unless e.start_with?('Arrival-Date: ')
86
- cf = e[e.index(': ') + 2, e.size].split(' '); next unless cf.size == 2
87
- cw = cf[0].split('-'); next unless cw.size == 3
88
- ce = cf[1].split('-'); next unless ce.size == 3
89
-
90
- o[1] << 'Thu, ' << cw[2] + ' '
91
- o[1] << Sisimai::DateTime.monthname(false)[cw[1].to_i - 1]
92
- o[1] << ' ' << cw[0] + ' ' << ce.join(':')
93
- o[1] << ' ' << Sisimai::DateTime.abbr2tz('CDT')
94
- else
95
- # Other DSN fields defined in RFC3464
96
- next unless fieldtable[o[0]]
97
- v[fieldtable[o[0]]] = o[2]
98
-
99
- next unless f
100
- permessage[fieldtable[o[0]]] = o[2]
101
- end
102
- else
103
- # The line does not begin with a DSN field defined in RFC3464
104
- if cv = Sisimai::SMTP::Command.find(e)
105
- # in RCPT TO, in MAIL FROM, end of DATA
106
- thecommand = cv
107
- elsif e.start_with?('Diagnostic-Code: ')
108
- # Diagnostic-Code: 550 5.1.1 <kijitora@example.jp>... User Unknown
109
- v['diagnosis'] = e[e.index(':') + 2, e.size]
110
- else
111
- # Continued line of the value of Diagnostic-Code field
112
- next unless readslices[-2].start_with?('Diagnostic-Code:')
113
- next unless e.start_with?(' ')
114
- v['diagnosis'] ||= ''
115
- v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
116
- readslices[-1] = 'Diagnostic-Code: ' << e
117
- end
118
- end
119
- end
120
- return nil unless recipients > 0
121
-
122
- dscontents.each do |e|
123
- # Get the value of SMTP status code as a pseudo D.S.N.
124
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
125
- e['replycode'] = Sisimai::SMTP::Reply.find(e['diagnosis']) || ''
126
- e['status'] = e['replycode'][0, 1] + '.0.0' if e['replycode'].size == 3
127
- e['command'] = thecommand
128
-
129
- if e['status'] == '5.0.0' || e['status'] == '4.0.0'
130
- # Get the value of D.S.N. from the error message or the value of Diagnostic-Code header.
131
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || e['status']
132
- end
133
-
134
- if e['action'] == 'expired'
135
- # Action: expired
136
- e['reason'] = 'expired'
137
- if !e['status'] || e['status'].end_with?('.0.0')
138
- # Set pseudo Status code value if the value of Status is not defined or 4.0.0 or 5.0.0.
139
- e['status'] = Sisimai::SMTP::Status.code('expired') || e['status']
140
- end
141
- end
142
- end
143
-
144
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
145
- end
146
- def description; return 'SendGrid: https://sendgrid.com/'; end
147
- end
148
- end
149
- end
150
-
@@ -1,105 +0,0 @@
1
- module Sisimai::Lhost
2
- # Sisimai::Lhost::SurfControl decodes a bounce email which created by WebSense SurfControl.
3
- # Methods in the module are called from only Sisimai::Message.
4
- module SurfControl
5
- class << self
6
- require 'sisimai/lhost'
7
-
8
- Indicators = Sisimai::Lhost.INDICATORS
9
- Boundaries = ['Content-Type: message/rfc822'].freeze
10
- StartingOf = { message: ['Your message could not be sent.'] }.freeze
11
-
12
- # @abstract Decodes the bounce message from SurfControl
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
- # X-SEF-ZeroHour-RefID: fgs=000000000
19
- # X-SEF-Processed: 0_0_0_000__2010_04_29_23_34_45
20
- # X-Mailer: SurfControl E-mail Filter
21
- return nil unless mhead['x-sef-processed']
22
- return nil unless mhead['x-mailer']
23
- return nil unless mhead['x-mailer'] == 'SurfControl E-mail Filter'
24
-
25
- fieldtable = Sisimai::RFC1894.FIELDTABLE
26
- dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
27
- emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
28
- bodyslices = emailparts[0].split("\n")
29
- readslices = ['']
30
- readcursor = 0 # (Integer) Points the current cursor position
31
- recipients = 0 # (Integer) The number of 'Final-Recipient' header
32
- v = nil
33
-
34
- while e = bodyslices.shift do
35
- # Read error messages and delivery status lines from the head of the email to the previous
36
- # line of the beginning of the original message.
37
- readslices << e # Save the current line for the next loop
38
-
39
- if readcursor == 0
40
- # Beginning of the bounce message or delivery status part
41
- readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
42
- next
43
- end
44
- next if (readcursor & Indicators[:deliverystatus]) == 0
45
- next if e.empty?
46
-
47
- # Your message could not be sent.
48
- # A transcript of the attempts to send the message follows.
49
- # The number of attempts made: 1
50
- # Addressed To: kijitora@example.com
51
- #
52
- # Thu 29 Apr 2010 23:34:45 +0900
53
- # Failed to send to identified host,
54
- # kijitora@example.com: [192.0.2.5], 550 kijitora@example.com... No such user
55
- # --- Message non-deliverable.
56
- v = dscontents[-1]
57
-
58
- if e.start_with?('Addressed To:') && e.index('@') > 1
59
- # Addressed To: kijitora@example.com
60
- if v['recipient']
61
- # There are multiple recipient addresses in the message body.
62
- dscontents << Sisimai::Lhost.DELIVERYSTATUS
63
- v = dscontents[-1]
64
- end
65
- v['recipient'] = Sisimai::Address.s3s4(e[e.index(':') + 2, e.size])
66
- recipients += 1
67
-
68
- elsif %w[Sun Mon Tue Wed Thu Fri Sat].any? { |a| e.start_with?(a) }
69
- # Thu 29 Apr 2010 23:34:45 +0900
70
- v['date'] = e
71
-
72
- elsif Sisimai::String.aligned(e, ['@', ':', ' ', '[', '],', '...'])
73
- # kijitora@example.com: [192.0.2.5], 550 kijitora@example.com... No such user
74
- p1 = e.index('[')
75
- p2 = e.index('],', p1 + 1)
76
- v['rhost'] = e[p1 + 1, p2 - p1 - 1]
77
- v['diagnosis'] = Sisimai::String.sweep(e[p2 + 2, e.size])
78
-
79
- else
80
- # Fallback, Decode RFC3464 headers.
81
- if f = Sisimai::RFC1894.match(e)
82
- # "e" matched with any field defined in RFC3464
83
- next unless o = Sisimai::RFC1894.field(e)
84
- next if o[1] == 'final-recipient'
85
- next unless fieldtable[o[0]]
86
- v[fieldtable[o[0]]] = o[2]
87
- else
88
- # Continued line of the value of Diagnostic-Code field
89
- next unless readslices[-2].start_with?('Diagnostic-Code:')
90
- next unless e.start_with?(' ')
91
- v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
92
- readslices[-1] = 'Diagnostic-Code: ' << e
93
- end
94
- end
95
- end
96
- return nil unless recipients > 0
97
-
98
- dscontents.each { |e| e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) }
99
- return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
100
- end
101
- def description; return 'WebSense SurfControl'; end
102
- end
103
- end
104
- end
105
-