sisimai 4.24.1 → 4.25.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of sisimai might be problematic. Click here for more details.

Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +3 -2
  3. data/ANALYTICAL-PRECISION +16 -25
  4. data/ChangeLog.md +41 -0
  5. data/Developers.mk +2 -2
  6. data/README-JA.md +13 -13
  7. data/README.md +13 -13
  8. data/lib/sisimai.rb +3 -7
  9. data/lib/sisimai/address.rb +25 -41
  10. data/lib/sisimai/arf.rb +58 -59
  11. data/lib/sisimai/bite.rb +0 -1
  12. data/lib/sisimai/bite/email.rb +7 -7
  13. data/lib/sisimai/bite/email/activehunter.rb +4 -3
  14. data/lib/sisimai/bite/email/amavis.rb +133 -0
  15. data/lib/sisimai/bite/email/amazonses.rb +53 -87
  16. data/lib/sisimai/bite/email/amazonworkmail.rb +51 -57
  17. data/lib/sisimai/bite/email/aol.rb +50 -76
  18. data/lib/sisimai/bite/email/apachejames.rb +2 -2
  19. data/lib/sisimai/bite/email/bigfoot.rb +47 -74
  20. data/lib/sisimai/bite/email/biglobe.rb +8 -9
  21. data/lib/sisimai/bite/email/courier.rb +56 -101
  22. data/lib/sisimai/bite/email/domino.rb +7 -8
  23. data/lib/sisimai/bite/email/einsundeins.rb +4 -5
  24. data/lib/sisimai/bite/email/exchange2003.rb +21 -22
  25. data/lib/sisimai/bite/email/exchange2007.rb +26 -28
  26. data/lib/sisimai/bite/email/exim.rb +48 -47
  27. data/lib/sisimai/bite/email/ezweb.rb +24 -36
  28. data/lib/sisimai/bite/email/facebook.rb +54 -79
  29. data/lib/sisimai/bite/email/fml.rb +10 -10
  30. data/lib/sisimai/bite/email/gmx.rb +6 -6
  31. data/lib/sisimai/bite/email/google.rb +12 -13
  32. data/lib/sisimai/bite/email/gsuite.rb +80 -108
  33. data/lib/sisimai/bite/email/imailserver.rb +16 -16
  34. data/lib/sisimai/bite/email/interscanmss.rb +4 -6
  35. data/lib/sisimai/bite/email/kddi.rb +9 -11
  36. data/lib/sisimai/bite/email/mailfoundry.rb +2 -2
  37. data/lib/sisimai/bite/email/mailmarshalsmtp.rb +2 -2
  38. data/lib/sisimai/bite/email/mailru.rb +12 -13
  39. data/lib/sisimai/bite/email/mcafee.rb +31 -25
  40. data/lib/sisimai/bite/email/messagelabs.rb +48 -87
  41. data/lib/sisimai/bite/email/messagingserver.rb +9 -10
  42. data/lib/sisimai/bite/email/mfilter.rb +16 -16
  43. data/lib/sisimai/bite/email/mxlogic.rb +11 -11
  44. data/lib/sisimai/bite/email/notes.rb +5 -6
  45. data/lib/sisimai/bite/email/office365.rb +25 -42
  46. data/lib/sisimai/bite/email/opensmtpd.rb +8 -8
  47. data/lib/sisimai/bite/email/outlook.rb +49 -67
  48. data/lib/sisimai/bite/email/postfix.rb +78 -112
  49. data/lib/sisimai/bite/email/qmail.rb +23 -23
  50. data/lib/sisimai/bite/email/receivingses.rb +53 -86
  51. data/lib/sisimai/bite/email/sendgrid.rb +65 -84
  52. data/lib/sisimai/bite/email/sendmail.rb +89 -117
  53. data/lib/sisimai/bite/email/surfcontrol.rb +15 -18
  54. data/lib/sisimai/bite/email/userdefined.rb +1 -1
  55. data/lib/sisimai/bite/email/v5sendmail.rb +3 -4
  56. data/lib/sisimai/bite/email/verizon.rb +7 -8
  57. data/lib/sisimai/bite/email/x1.rb +2 -2
  58. data/lib/sisimai/bite/email/x2.rb +2 -2
  59. data/lib/sisimai/bite/email/x3.rb +3 -3
  60. data/lib/sisimai/bite/email/x4.rb +22 -22
  61. data/lib/sisimai/bite/email/x5.rb +40 -49
  62. data/lib/sisimai/bite/email/yahoo.rb +3 -3
  63. data/lib/sisimai/bite/email/yandex.rb +54 -82
  64. data/lib/sisimai/bite/email/zoho.rb +6 -6
  65. data/lib/sisimai/bite/json/amazonses.rb +20 -20
  66. data/lib/sisimai/bite/json/sendgrid.rb +2 -2
  67. data/lib/sisimai/data.rb +27 -40
  68. data/lib/sisimai/datetime.rb +146 -162
  69. data/lib/sisimai/mda.rb +30 -31
  70. data/lib/sisimai/message/email.rb +83 -123
  71. data/lib/sisimai/message/json.rb +2 -4
  72. data/lib/sisimai/mime.rb +31 -34
  73. data/lib/sisimai/order/email.rb +23 -22
  74. data/lib/sisimai/reason.rb +61 -61
  75. data/lib/sisimai/reason/blocked.rb +139 -135
  76. data/lib/sisimai/reason/contenterror.rb +11 -10
  77. data/lib/sisimai/reason/exceedlimit.rb +4 -4
  78. data/lib/sisimai/reason/expired.rb +20 -20
  79. data/lib/sisimai/reason/filtered.rb +19 -18
  80. data/lib/sisimai/reason/hasmoved.rb +3 -3
  81. data/lib/sisimai/reason/hostunknown.rb +19 -19
  82. data/lib/sisimai/reason/mailboxfull.rb +49 -49
  83. data/lib/sisimai/reason/mailererror.rb +16 -16
  84. data/lib/sisimai/reason/mesgtoobig.rb +17 -17
  85. data/lib/sisimai/reason/networkerror.rb +19 -19
  86. data/lib/sisimai/reason/norelaying.rb +16 -16
  87. data/lib/sisimai/reason/notaccept.rb +9 -10
  88. data/lib/sisimai/reason/onhold.rb +1 -1
  89. data/lib/sisimai/reason/policyviolation.rb +21 -20
  90. data/lib/sisimai/reason/rejected.rb +53 -53
  91. data/lib/sisimai/reason/securityerror.rb +29 -29
  92. data/lib/sisimai/reason/spamdetected.rb +127 -127
  93. data/lib/sisimai/reason/suspend.rb +17 -17
  94. data/lib/sisimai/reason/systemerror.rb +22 -21
  95. data/lib/sisimai/reason/systemfull.rb +6 -6
  96. data/lib/sisimai/reason/toomanyconn.rb +19 -18
  97. data/lib/sisimai/reason/userunknown.rb +122 -121
  98. data/lib/sisimai/reason/vacation.rb +8 -8
  99. data/lib/sisimai/reason/virusdetected.rb +8 -8
  100. data/lib/sisimai/rfc1894.rb +142 -0
  101. data/lib/sisimai/rfc3464.rb +70 -70
  102. data/lib/sisimai/rfc3834.rb +15 -15
  103. data/lib/sisimai/rfc5322.rb +20 -36
  104. data/lib/sisimai/rhost.rb +1 -0
  105. data/lib/sisimai/rhost/exchangeonline.rb +31 -33
  106. data/lib/sisimai/rhost/franceptt.rb +23 -23
  107. data/lib/sisimai/rhost/godaddy.rb +28 -28
  108. data/lib/sisimai/rhost/googleapps.rb +39 -41
  109. data/lib/sisimai/rhost/kddi.rb +3 -3
  110. data/lib/sisimai/rhost/tencentqq.rb +51 -0
  111. data/lib/sisimai/smtp/error.rb +14 -21
  112. data/lib/sisimai/smtp/reply.rb +14 -13
  113. data/lib/sisimai/smtp/status.rb +178 -179
  114. data/lib/sisimai/string.rb +13 -12
  115. data/lib/sisimai/version.rb +1 -1
  116. data/set-of-emails/README.md +1 -5
  117. data/set-of-emails/maildir/bsd/arf-23.eml +49 -0
  118. data/set-of-emails/maildir/bsd/email-amavis-01.eml +78 -0
  119. data/set-of-emails/maildir/bsd/email-amavis-02.eml +78 -0
  120. data/set-of-emails/maildir/bsd/email-exchange2007-04.eml +146 -0
  121. data/set-of-emails/maildir/bsd/email-exim-60.eml +94 -0
  122. data/set-of-emails/maildir/bsd/email-ezweb-08.eml +49 -0
  123. data/set-of-emails/maildir/bsd/email-google-19.eml +67 -0
  124. data/set-of-emails/maildir/bsd/email-mcafee-05.eml +74 -0
  125. data/set-of-emails/maildir/bsd/email-messagingserver-12.eml +99 -0
  126. data/set-of-emails/maildir/bsd/email-postfix-46.eml +81 -0
  127. data/set-of-emails/maildir/bsd/email-postfix-47.eml +79 -0
  128. data/set-of-emails/maildir/bsd/email-postfix-48.eml +79 -0
  129. data/set-of-emails/maildir/bsd/email-postfix-49.eml +141 -0
  130. data/set-of-emails/maildir/bsd/email-postfix-50.eml +143 -0
  131. data/set-of-emails/maildir/bsd/email-postfix-51.eml +73 -0
  132. data/set-of-emails/maildir/bsd/email-postfix-52.eml +79 -0
  133. data/set-of-emails/maildir/bsd/email-postfix-53.eml +76 -0
  134. data/set-of-emails/maildir/bsd/email-postfix-54.eml +73 -0
  135. data/set-of-emails/maildir/bsd/email-postfix-55.eml +74 -0
  136. data/set-of-emails/maildir/bsd/email-postfix-56.eml +78 -0
  137. data/set-of-emails/maildir/bsd/email-qmail-10.eml +50 -0
  138. data/set-of-emails/maildir/bsd/email-x2-05.eml +38 -0
  139. data/set-of-emails/maildir/bsd/rhost-google-apps-02.eml +88 -0
  140. data/set-of-emails/maildir/bsd/rhost-tencentqq-01.eml +84 -0
  141. data/set-of-emails/maildir/bsd/rhost-tencentqq-02.eml +84 -0
  142. data/set-of-emails/maildir/bsd/rhost-tencentqq-03.eml +81 -0
  143. data/set-of-emails/maildir/dos/email-amavis-01.eml +78 -0
  144. data/set-of-emails/maildir/dos/email-apachejames-01.eml +1 -2
  145. data/set-of-emails/maildir/dos/email-messagelabs-01.eml +67 -50
  146. data/set-of-emails/maildir/dos/email-x4-01.eml +31 -76
  147. data/set-of-emails/maildir/dos/rhost-tencentqq-01.eml +84 -0
  148. data/set-of-emails/maildir/mac/email-amavis-01.eml +1 -4
  149. data/set-of-emails/maildir/mac/email-apachejames-01.eml +1 -9
  150. data/set-of-emails/maildir/mac/email-messagelabs-01.eml +1 -9
  151. data/set-of-emails/maildir/mac/email-x4-01.eml +1 -5
  152. data/set-of-emails/maildir/mac/rhost-tencentqq-01.eml +1 -4
  153. metadata +35 -4
  154. data/set-of-emails/logo/horizontalversions.png +0 -0
  155. data/set-of-emails/logo/icon.png +0 -0
@@ -19,28 +19,28 @@ module Sisimai::Bite::Email
19
19
  }.freeze
20
20
  ReFailures = {
21
21
  # notaccept: [ %r/The following recipients did not receive this message:/ ],
22
- mailboxfull: [
22
+ 'mailboxfull' => [
23
23
  %r/The user[(]s[)] account is temporarily over quota/,
24
24
  ],
25
- suspend: [
25
+ 'suspend' => [
26
26
  # http://www.naruhodo-au.kddi.com/qa3429203.html
27
27
  # The recipient may be unpaid user...?
28
28
  %r/The user[(]s[)] account is disabled[.]/,
29
29
  %r/The user[(]s[)] account is temporarily limited[.]/,
30
30
  ],
31
- expired: [
31
+ 'expired' => [
32
32
  # Your message was not delivered within 0 days and 1 hours.
33
33
  # Remote host is not responding.
34
34
  %r/Your message was not delivered within /,
35
35
  ],
36
- onhold: [
36
+ 'onhold' => [
37
37
  %r/Each of the following recipients was rejected by a remote mail server/,
38
38
  ],
39
39
  }.freeze
40
40
 
41
41
  def description; return 'au EZweb: http://www.au.kddi.com/mobile/'; end
42
42
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
43
- def headerlist; return ['X-SPASIGN']; end
43
+ def headerlist; return %w[x-spasign]; end
44
44
 
45
45
  # Parse bounce messages from au EZweb
46
46
  # @param [Hash] mhead Message headers of a bounce email
@@ -65,6 +65,8 @@ module Sisimai::Bite::Email
65
65
  end
66
66
  return nil if match < 2
67
67
 
68
+ require 'sisimai/rfc1894'
69
+ fieldtable = Sisimai::RFC1894.FIELDTABLE
68
70
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
69
71
  hasdivided = mbody.split("\n")
70
72
  rfc822list = [] # (Array) Each line in message/rfc822 part string
@@ -98,7 +100,7 @@ module Sisimai::Bite::Email
98
100
  end
99
101
 
100
102
  if readcursor & Indicators[:'message-rfc822'] > 0
101
- # After "message/rfc822"
103
+ # Inside of the original message part
102
104
  if e.empty?
103
105
  blanklines += 1
104
106
  break if blanklines > 1
@@ -106,7 +108,7 @@ module Sisimai::Bite::Email
106
108
  end
107
109
  rfc822list << e
108
110
  else
109
- # Before "message/rfc822"
111
+ # Error message part
110
112
  next if (readcursor & Indicators[:deliverystatus]) == 0
111
113
  next if e.empty?
112
114
 
@@ -134,29 +136,18 @@ module Sisimai::Bite::Email
134
136
  end
135
137
 
136
138
  r = Sisimai::Address.s3s4(cv[1])
137
- if Sisimai::RFC5322.is_emailaddress(r)
138
- v['recipient'] = r
139
- recipients += 1
140
- end
141
-
142
- elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
143
- # Status: 5.1.1
144
- # Status:5.2.0
145
- # Status: 5.1.0 (permanent failure)
146
- v['status'] = cv[1]
139
+ next unless Sisimai::RFC5322.is_emailaddress(r)
140
+ v['recipient'] = r
141
+ recipients += 1
147
142
 
148
- elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
149
- # Action: failed
150
- v['action'] = cv[1].downcase
143
+ elsif f = Sisimai::RFC1894.match(e)
144
+ # "e" matched with any field defined in RFC3464
145
+ next unless o = Sisimai::RFC1894.field(e)
146
+ next unless fieldtable.key?(o[0])
147
+ v[fieldtable[o[0]]] = o[2]
151
148
 
152
- elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
153
- # Remote-MTA: DNS; mx.example.jp
154
- v['rhost'] = cv[1].downcase
155
-
156
- elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
157
- # Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
158
- v['date'] = cv[1]
159
149
  else
150
+ # The line does not begin with a DSN field defined in RFC3464
160
151
  next if Sisimai::String.is_8bit(e)
161
152
  if cv = e.match(/\A[ \t]+[>]{3}[ \t]+([A-Z]{4})/)
162
153
  # >>> RCPT TO:<******@ezweb.ne.jp>
@@ -179,6 +170,8 @@ module Sisimai::Bite::Email
179
170
  return nil unless recipients > 0
180
171
 
181
172
  dscontents.each do |e|
173
+ e['agent'] = self.smtpagent
174
+
182
175
  unless e['alterrors'].to_s.empty?
183
176
  # Copy alternative error message
184
177
  e['diagnosis'] ||= e['alterrors']
@@ -207,7 +200,7 @@ module Sisimai::Bite::Email
207
200
  ReFailures[r].each do |rr|
208
201
  # Check each regular expression
209
202
  next unless e['diagnosis'] =~ rr
210
- e['reason'] = r.to_s
203
+ e['reason'] = r
211
204
  throw :SESSION
212
205
  end
213
206
  end
@@ -215,14 +208,9 @@ module Sisimai::Bite::Email
215
208
 
216
209
  end
217
210
  end
218
-
219
- unless e['reason']
220
- # The value of "reason" is not set yet.
221
- # Deal as "userunknown" when the domain part of the recipient
222
- # is "ezweb.ne.jp".
223
- e['reason'] = 'userunknown' unless e['recipient'].end_with?('@ezweb.ne.jp', '@au.com')
224
- end
225
- e['agent'] = self.smtpagent
211
+ next if e['reason']
212
+ next if e['recipient'].end_with?('@ezweb.ne.jp', '@au.com')
213
+ e['reason'] = 'userunknown'
226
214
  end
227
215
 
228
216
  rfc822part = Sisimai::RFC5322.weedout(rfc822list)
@@ -14,56 +14,56 @@ module Sisimai::Bite::Email
14
14
  ReFailures = {
15
15
  # http://postmaster.facebook.com/response_codes
16
16
  # NOT TESTD EXCEPT RCP-P2
17
- userunknown: [
17
+ 'userunknown' => [
18
18
  'RCP-P1', # The attempted recipient address does not exist.
19
19
  'INT-P1', # The attempted recipient address does not exist.
20
20
  'INT-P3', # The attempted recpient group address does not exist.
21
21
  'INT-P4', # The attempted recipient address does not exist.
22
22
  ],
23
- filtered: [
23
+ 'filtered' => [
24
24
  'RCP-P2', # The attempted recipient's preferences prevent messages from being delivered.
25
25
  'RCP-P3', # The attempted recipient's privacy settings blocked the delivery.
26
26
  ],
27
- mesgtoobig: [
27
+ 'mesgtoobig' => [
28
28
  'MSG-P1', # The message exceeds Facebook's maximum allowed size.
29
29
  'INT-P2', # The message exceeds Facebook's maximum allowed size.
30
30
  ],
31
- contenterror: [
31
+ 'contenterror' => [
32
32
  'MSG-P2', # The message contains an attachment type that Facebook does not accept.
33
33
  '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
34
34
  'POL-P6', # The message contains a url that has been blocked by Facebook.
35
35
  'POL-P7', # The message does not comply with Facebook's abuse policies and will not be accepted.
36
36
  ],
37
- securityerror: [
37
+ 'securityerror' => [
38
38
  'POL-P1', # Your mail server's IP Address is listed on the Spamhaus PBL.
39
39
  'POL-P2', # Facebook will no longer accept mail from your mail server's IP Address.
40
40
  'POL-P5', # The message contains a virus.
41
41
  'POL-P7', # The message does not comply with Facebook's Domain Authentication requirements.
42
42
  ],
43
- notaccept: [
43
+ 'notaccept' => [
44
44
  'POL-P3', # Facebook is not accepting messages from your mail server. This will persist for 4 to 8 hours.
45
45
  'POL-P4', # Facebook is not accepting messages from your mail server. This will persist for 24 to 48 hours.
46
46
  '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.
47
47
  '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.
48
48
  '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.
49
49
  ],
50
- rejected: [
50
+ 'rejected' => [
51
51
  'DNS-P1', # Your SMTP MAIL FROM domain does not exist.
52
52
  'DNS-P2', # Your SMTP MAIL FROM domain does not have an MX record.
53
53
  'DNS-T1', # Your SMTP MAIL FROM domain exists but does not currently resolve.
54
54
  'DNS-P3', # Your mail server does not have a reverse DNS record.
55
55
  'DNS-T2', # You mail server's reverse DNS record does not currently resolve.
56
56
  ],
57
- systemerror: [
57
+ 'systemerror' => [
58
58
  'CON-T1', # Facebook's mail server currently has too many connections open to allow another one.
59
59
  ],
60
- toomanyconn: [
60
+ 'toomanyconn' => [
61
61
  'CON-T3', # Your mail server has opened too many new connections to Facebook's mail servers in a short period of time.
62
62
  ],
63
- suspend: [
63
+ 'suspend' => [
64
64
  'RCP-T4', # The attempted recipient address is currently deactivated. The user may or may not reactivate it.
65
65
  ],
66
- undefined: [
66
+ 'undefined' => [
67
67
  'RCP-T1', # The attempted recipient address is not currently available due to an internal system issue. This is a temporary condition.
68
68
  'MSG-T1', # The number of recipients on the message exceeds Facebook's allowed maximum.
69
69
  'CON-T2', # Your mail server currently has too many connections open to Facebook's mail servers.
@@ -90,6 +90,10 @@ module Sisimai::Bite::Email
90
90
  return nil unless mhead['from'] == 'Facebook <mailer-daemon@mx.facebook.com>'
91
91
  return nil unless mhead['subject'] == 'Sorry, your message could not be delivered'
92
92
 
93
+ require 'sisimai/rfc1894'
94
+ fieldtable = Sisimai::RFC1894.FIELDTABLE
95
+ permessage = {} # (Hash) Store values of each Per-Message field
96
+
93
97
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
94
98
  hasdivided = mbody.split("\n")
95
99
  havepassed = ['']
@@ -98,11 +102,6 @@ module Sisimai::Bite::Email
98
102
  readcursor = 0 # (Integer) Points the current cursor position
99
103
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
100
104
  fbresponse = '' # (String) Response code from Facebook
101
- connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
102
- connheader = {
103
- 'date' => '', # The value of Arrival-Date header
104
- 'lhost' => '', # The value of Reporting-MTA header
105
- }
106
105
  v = nil
107
106
 
108
107
  while e = hasdivided.shift do
@@ -111,7 +110,7 @@ module Sisimai::Bite::Email
111
110
  p = havepassed[-2]
112
111
 
113
112
  if readcursor == 0
114
- # Beginning of the bounce message or delivery status part
113
+ # Beginning of the bounce message or message/delivery-status part
115
114
  if e == StartingOf[:message][0]
116
115
  readcursor |= Indicators[:deliverystatus]
117
116
  next
@@ -119,7 +118,7 @@ module Sisimai::Bite::Email
119
118
  end
120
119
 
121
120
  if (readcursor & Indicators[:'message-rfc822']) == 0
122
- # Beginning of the original message part
121
+ # Beginning of the original message part(message/rfc822)
123
122
  if e == StartingOf[:rfc822][0]
124
123
  readcursor |= Indicators[:'message-rfc822']
125
124
  next
@@ -127,7 +126,7 @@ module Sisimai::Bite::Email
127
126
  end
128
127
 
129
128
  if readcursor & Indicators[:'message-rfc822'] > 0
130
- # After "message/rfc822"
129
+ # message/rfc822 OR text/rfc822-headers part
131
130
  if e.empty?
132
131
  blanklines += 1
133
132
  break if blanklines > 1
@@ -135,80 +134,56 @@ module Sisimai::Bite::Email
135
134
  end
136
135
  rfc822list << e
137
136
  else
138
- # Before "message/rfc822"
137
+ # message/delivery-status part
139
138
  next if (readcursor & Indicators[:deliverystatus]) == 0
140
139
  next if e.empty?
141
140
 
142
- if connvalues == connheader.keys.size
143
- # Reporting-MTA: dns; 10.138.205.200
144
- # Arrival-Date: Thu, 23 Jun 2011 02:29:43 -0700
141
+ if f = Sisimai::RFC1894.match(e)
142
+ # "e" matched with any field defined in RFC3464
143
+ o = Sisimai::RFC1894.field(e) || next
145
144
  v = dscontents[-1]
146
145
 
147
- if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
148
- # Final-Recipient: RFC822; userunknown@example.jp
149
- if v['recipient']
150
- # There are multiple recipient addresses in the message body.
151
- dscontents << Sisimai::Bite.DELIVERYSTATUS
152
- v = dscontents[-1]
146
+ if o[-1] == 'addr'
147
+ # Final-Recipient: rfc822; kijitora@example.jp
148
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
149
+ if o[0] == 'final-recipient'
150
+ # Final-Recipient: rfc822; kijitora@example.jp
151
+ if v['recipient']
152
+ # There are multiple recipient addresses in the message body.
153
+ dscontents << Sisimai::Bite.DELIVERYSTATUS
154
+ v = dscontents[-1]
155
+ end
156
+ v['recipient'] = o[2]
157
+ recipients += 1
158
+ else
159
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
160
+ v['alias'] = o[2]
153
161
  end
154
- v['recipient'] = cv[1]
155
- recipients += 1
156
-
157
- elsif cv = e.match(/\AX-Actual-Recipient:[ ]*(?:RFC|rfc)822;[ ]*(.+)\z/)
158
- # X-Actual-Recipient: RFC822; kijitora@example.co.jp
159
- v['alias'] = cv[1]
160
-
161
- elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
162
- # Action: failed
163
- v['action'] = cv[1].downcase
164
-
165
- elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
166
- # Status: 5.1.1
167
- # Status:5.2.0
168
- # Status: 5.1.0 (permanent failure)
169
- v['status'] = cv[1]
170
-
171
- elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
172
- # Remote-MTA: DNS; mx.example.jp
173
- v['rhost'] = cv[1].downcase
174
-
175
- elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
176
- # Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
177
- v['date'] = cv[1]
162
+ elsif o[-1] == 'code'
163
+ # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
164
+ v['spec'] = o[1]
165
+ v['diagnosis'] = o[2]
178
166
  else
179
- if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
180
- # Diagnostic-Code: smtp; 550 5.1.1 RCP-P2
181
- # http://postmaster.facebook.com/response_codes?ip=192.0.2.135#rcp Refused due to recipient preferences
182
- v['spec'] = cv[1].upcase
183
- v['diagnosis'] = cv[2]
167
+ # Other DSN fields defined in RFC3464
168
+ next unless fieldtable.key?(o[0])
169
+ v[fieldtable[o[0]]] = o[2]
184
170
 
185
- elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
186
- # Continued line of the value of Diagnostic-Code header
187
- v['diagnosis'] << ' ' << cv[1]
188
- havepassed[-1] = 'Diagnostic-Code: ' << e
189
- end
171
+ next unless f == 1
172
+ permessage[fieldtable[o[0]]] = o[2]
190
173
  end
191
174
  else
192
- if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
193
- # Reporting-MTA: dns; mx.example.jp
194
- next unless connheader['lhost'].empty?
195
- connheader['lhost'] = cv[1].downcase
196
- connvalues += 1
197
-
198
- elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
199
- # Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
200
- next unless connheader['date'].empty?
201
- connheader['date'] = cv[1]
202
- connvalues += 1
203
- end
204
-
175
+ # Continued line of the value of Diagnostic-Code field
176
+ next unless p.start_with?('Diagnostic-Code:')
177
+ next unless cv = e.match(/\A[ \t]+(.+)\z/)
178
+ v['diagnosis'] << ' ' << cv[1]
179
+ havepassed[-1] = 'Diagnostic-Code: ' << e
205
180
  end
206
- end
181
+ end # End of message/delivery-status
207
182
  end
208
183
  return nil unless recipients > 0
209
184
 
210
185
  dscontents.each do |e|
211
- e['lhost'] ||= connheader['lhost']
186
+ e['lhost'] ||= permessage['lhost']
212
187
  e['agent'] = self.smtpagent
213
188
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
214
189
 
@@ -227,7 +202,7 @@ module Sisimai::Bite::Email
227
202
  ReFailures[r].each do |rr|
228
203
  # Check each regular expression
229
204
  next unless fbresponse == rr
230
- e['reason'] = r.to_s
205
+ e['reason'] = r
231
206
  throw :SESSION
232
207
  end
233
208
  end
@@ -9,24 +9,24 @@ module Sisimai::Bite::Email
9
9
  Indicators = Sisimai::Bite::Email.INDICATORS
10
10
  StartingOf = { rfc822: ['Original mail as follows:'] }.freeze
11
11
  ErrorTitle = {
12
- :rejected => %r{(?>
12
+ 'rejected' => %r{(?>
13
13
  (?:Ignored[ ])*NOT[ ]MEMBER[ ]article[ ]from[ ]
14
14
  |reject[ ]mail[ ](?:.+:|from)[ ],
15
15
  |Spam[ ]mail[ ]from[ ]a[ ]spammer[ ]is[ ]rejected
16
16
  |You[ ].+[ ]are[ ]not[ ]member
17
17
  )
18
18
  }x,
19
- :systemerror => %r{(?:
19
+ 'systemerror' => %r{(?:
20
20
  fml[ ]system[ ]error[ ]message
21
21
  |Loop[ ]Alert:[ ]
22
22
  |Loop[ ]Back[ ]Warning:[ ]
23
23
  |WARNING:[ ]UNIX[ ]FROM[ ]Loop
24
24
  )
25
25
  }x,
26
- :securityerror => %r/Security Alert/,
26
+ 'securityerror' => %r/Security Alert/,
27
27
  }.freeze
28
28
  ErrorTable = {
29
- :rejected => %r{(?>
29
+ 'rejected' => %r{(?>
30
30
  (?:Ignored[ ])*NOT[ ]MEMBER[ ]article[ ]from[ ]
31
31
  |reject[ ](?:
32
32
  mail[ ]from[ ].+[@].+
@@ -36,18 +36,18 @@ module Sisimai::Bite::Email
36
36
  |You[ ]are[ ]not[ ]a[ ]member[ ]of[ ]this[ ]mailing[ ]list
37
37
  )
38
38
  }x,
39
- :systemerror => %r{(?:
39
+ 'systemerror' => %r{(?:
40
40
  Duplicated[ ]Message-ID
41
41
  |fml[ ].+[ ]has[ ]detected[ ]a[ ]loop[ ]condition[ ]so[ ]that
42
42
  |Loop[ ]Back[ ]Warning:
43
43
  )
44
44
  }x,
45
- :securityerror => %r/Security alert:/,
45
+ 'securityerror' => %r/Security alert:/,
46
46
  }.freeze
47
47
 
48
48
  def description; return 'fml mailing list server/manager'; end
49
49
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
50
- def headerlist; return ['X-MLServer']; end
50
+ def headerlist; return %w[x-mlserver]; end
51
51
 
52
52
  # Parse bounce messages from fml mailling list server/manager
53
53
  # @param [Hash] mhead Message headers of a bounce email
@@ -97,7 +97,7 @@ module Sisimai::Bite::Email
97
97
  end
98
98
  rfc822list << e.lstrip
99
99
  else
100
- # Before "message/rfc822"
100
+ # Error message part
101
101
  next if (readcursor & Indicators[:deliverystatus]) == 0
102
102
  next if e.empty?
103
103
 
@@ -133,7 +133,7 @@ module Sisimai::Bite::Email
133
133
  ErrorTable.each_key do |f|
134
134
  # Try to match with error messages defined in ErrorTable
135
135
  next unless e['diagnosis'] =~ ErrorTable[f]
136
- e['reason'] = f.to_s
136
+ e['reason'] = f
137
137
  break
138
138
  end
139
139
 
@@ -142,7 +142,7 @@ module Sisimai::Bite::Email
142
142
  ErrorTitle.each_key do |f|
143
143
  # Try to match with the Subject string
144
144
  next unless mhead['subject'] =~ ErrorTitle[f]
145
- e['reason'] = f.to_s
145
+ e['reason'] = f
146
146
  break
147
147
  end
148
148
  end
@@ -11,7 +11,7 @@ module Sisimai::Bite::Email
11
11
  message: ['This message was created automatically by mail delivery software'],
12
12
  rfc822: ['--- The header of the original message is following'],
13
13
  }.freeze
14
- MessagesOf = { expired: ['delivery retry timeout exceeded'] }.freeze
14
+ MessagesOf = { 'expired' => ['delivery retry timeout exceeded'] }.freeze
15
15
 
16
16
  def description; return 'GMX: http://www.gmx.net'; end
17
17
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
@@ -20,7 +20,7 @@ module Sisimai::Bite::Email
20
20
  # X-GMX-Antispam: 0 (Mail was not recognized as spam); Detail=V3;
21
21
  # X-GMX-Antivirus: 0 (no virus found)
22
22
  # X-UI-Out-Filterresults: unknown:0;
23
- def headerlist; return ['X-GMX-Antispam']; end
23
+ def headerlist; return %w[x-gmx-antispam]; end
24
24
 
25
25
  # Parse bounce messages from GMX
26
26
  # @param [Hash] mhead Message headers of a bounce email
@@ -64,7 +64,7 @@ module Sisimai::Bite::Email
64
64
  end
65
65
 
66
66
  if readcursor & Indicators[:'message-rfc822'] > 0
67
- # After "message/rfc822"
67
+ # Inside of the original message part
68
68
  if e.empty?
69
69
  blanklines += 1
70
70
  break if blanklines > 1
@@ -72,7 +72,7 @@ module Sisimai::Bite::Email
72
72
  end
73
73
  rfc822list << e
74
74
  else
75
- # Before "message/rfc822"
75
+ # Error message part
76
76
  next if (readcursor & Indicators[:deliverystatus]) == 0
77
77
  next if e.empty?
78
78
 
@@ -132,12 +132,12 @@ module Sisimai::Bite::Email
132
132
 
133
133
  dscontents.each do |e|
134
134
  e['agent'] = self.smtpagent
135
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].gsub(/\\n/, ' '))
135
+ e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
136
136
 
137
137
  MessagesOf.each_key do |r|
138
138
  # Verify each regular expression of session errors
139
139
  next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
140
- e['reason'] = r.to_s
140
+ e['reason'] = r
141
141
  break
142
142
  end
143
143
  end