sisimai 4.22.3 → 4.22.4

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 (130) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/Benchmarks.mk +54 -0
  4. data/ChangeLog.md +23 -2
  5. data/Developers.mk +42 -35
  6. data/Makefile +10 -0
  7. data/README-JA.md +13 -13
  8. data/README.md +14 -14
  9. data/lib/sisimai.rb +12 -18
  10. data/lib/sisimai/address.rb +64 -82
  11. data/lib/sisimai/arf.rb +27 -42
  12. data/lib/sisimai/bite/email.rb +2 -4
  13. data/lib/sisimai/bite/email/activehunter.rb +12 -17
  14. data/lib/sisimai/bite/email/amazonses.rb +30 -48
  15. data/lib/sisimai/bite/email/amazonworkmail.rb +20 -27
  16. data/lib/sisimai/bite/email/aol.rb +27 -35
  17. data/lib/sisimai/bite/email/apachejames.rb +17 -28
  18. data/lib/sisimai/bite/email/bigfoot.rb +20 -33
  19. data/lib/sisimai/bite/email/biglobe.rb +15 -24
  20. data/lib/sisimai/bite/email/courier.rb +37 -61
  21. data/lib/sisimai/bite/email/domino.rb +19 -28
  22. data/lib/sisimai/bite/email/einsundeins.rb +20 -34
  23. data/lib/sisimai/bite/email/exchange2003.rb +25 -43
  24. data/lib/sisimai/bite/email/exchange2007.rb +15 -23
  25. data/lib/sisimai/bite/email/exim.rb +101 -120
  26. data/lib/sisimai/bite/email/ezweb.rb +28 -44
  27. data/lib/sisimai/bite/email/facebook.rb +26 -37
  28. data/lib/sisimai/bite/email/fml.rb +11 -20
  29. data/lib/sisimai/bite/email/gmx.rb +17 -27
  30. data/lib/sisimai/bite/email/google.rb +19 -29
  31. data/lib/sisimai/bite/email/gsuite.rb +39 -48
  32. data/lib/sisimai/bite/email/imailserver.rb +25 -39
  33. data/lib/sisimai/bite/email/interscanmss.rb +19 -26
  34. data/lib/sisimai/bite/email/kddi.rb +20 -33
  35. data/lib/sisimai/bite/email/mailfoundry.rb +14 -24
  36. data/lib/sisimai/bite/email/mailmarshalsmtp.rb +15 -24
  37. data/lib/sisimai/bite/email/mailru.rb +40 -59
  38. data/lib/sisimai/bite/email/mcafee.rb +21 -35
  39. data/lib/sisimai/bite/email/messagelabs.rb +23 -38
  40. data/lib/sisimai/bite/email/messagingserver.rb +15 -27
  41. data/lib/sisimai/bite/email/mfilter.rb +19 -28
  42. data/lib/sisimai/bite/email/mxlogic.rb +31 -49
  43. data/lib/sisimai/bite/email/notes.rb +16 -24
  44. data/lib/sisimai/bite/email/office365.rb +29 -38
  45. data/lib/sisimai/bite/email/opensmtpd.rb +50 -67
  46. data/lib/sisimai/bite/email/outlook.rb +24 -36
  47. data/lib/sisimai/bite/email/postfix.rb +33 -42
  48. data/lib/sisimai/bite/email/qmail.rb +44 -59
  49. data/lib/sisimai/bite/email/receivingses.rb +28 -36
  50. data/lib/sisimai/bite/email/sendgrid.rb +28 -37
  51. data/lib/sisimai/bite/email/sendmail.rb +35 -51
  52. data/lib/sisimai/bite/email/surfcontrol.rb +17 -25
  53. data/lib/sisimai/bite/email/userdefined.rb +17 -28
  54. data/lib/sisimai/bite/email/v5sendmail.rb +32 -41
  55. data/lib/sisimai/bite/email/verizon.rb +31 -56
  56. data/lib/sisimai/bite/email/x1.rb +11 -18
  57. data/lib/sisimai/bite/email/x2.rb +11 -23
  58. data/lib/sisimai/bite/email/x3.rb +10 -19
  59. data/lib/sisimai/bite/email/x4.rb +46 -65
  60. data/lib/sisimai/bite/email/x5.rb +26 -37
  61. data/lib/sisimai/bite/email/yahoo.rb +11 -19
  62. data/lib/sisimai/bite/email/yandex.rb +19 -30
  63. data/lib/sisimai/bite/email/zoho.rb +21 -30
  64. data/lib/sisimai/bite/json.rb +1 -2
  65. data/lib/sisimai/bite/json/amazonses.rb +20 -25
  66. data/lib/sisimai/bite/json/sendgrid.rb +1 -1
  67. data/lib/sisimai/data.rb +36 -55
  68. data/lib/sisimai/data/json.rb +3 -3
  69. data/lib/sisimai/data/yaml.rb +1 -1
  70. data/lib/sisimai/datetime.rb +5 -21
  71. data/lib/sisimai/mail.rb +4 -6
  72. data/lib/sisimai/mail/maildir.rb +1 -1
  73. data/lib/sisimai/mda.rb +41 -44
  74. data/lib/sisimai/message.rb +2 -3
  75. data/lib/sisimai/message/email.rb +42 -52
  76. data/lib/sisimai/message/json.rb +7 -7
  77. data/lib/sisimai/mime.rb +25 -23
  78. data/lib/sisimai/order/email.rb +2 -2
  79. data/lib/sisimai/order/json.rb +2 -7
  80. data/lib/sisimai/reason.rb +41 -46
  81. data/lib/sisimai/reason/blocked.rb +60 -71
  82. data/lib/sisimai/reason/contenterror.rb +4 -8
  83. data/lib/sisimai/reason/delivered.rb +1 -3
  84. data/lib/sisimai/reason/exceedlimit.rb +10 -20
  85. data/lib/sisimai/reason/expired.rb +5 -9
  86. data/lib/sisimai/reason/feedback.rb +1 -3
  87. data/lib/sisimai/reason/filtered.rb +19 -38
  88. data/lib/sisimai/reason/hasmoved.rb +5 -8
  89. data/lib/sisimai/reason/hostunknown.rb +11 -18
  90. data/lib/sisimai/reason/mailboxfull.rb +14 -24
  91. data/lib/sisimai/reason/mailererror.rb +3 -5
  92. data/lib/sisimai/reason/mesgtoobig.rb +15 -25
  93. data/lib/sisimai/reason/networkerror.rb +8 -10
  94. data/lib/sisimai/reason/norelaying.rb +9 -14
  95. data/lib/sisimai/reason/notaccept.rb +9 -21
  96. data/lib/sisimai/reason/onhold.rb +3 -8
  97. data/lib/sisimai/reason/policyviolation.rb +8 -10
  98. data/lib/sisimai/reason/rejected.rb +36 -49
  99. data/lib/sisimai/reason/securityerror.rb +11 -13
  100. data/lib/sisimai/reason/spamdetected.rb +23 -37
  101. data/lib/sisimai/reason/suspend.rb +9 -10
  102. data/lib/sisimai/reason/syntaxerror.rb +3 -4
  103. data/lib/sisimai/reason/systemerror.rb +7 -9
  104. data/lib/sisimai/reason/systemfull.rb +2 -4
  105. data/lib/sisimai/reason/toomanyconn.rb +17 -30
  106. data/lib/sisimai/reason/undefined.rb +1 -3
  107. data/lib/sisimai/reason/userunknown.rb +28 -38
  108. data/lib/sisimai/reason/vacation.rb +4 -6
  109. data/lib/sisimai/reason/virusdetected.rb +4 -6
  110. data/lib/sisimai/rfc2606.rb +1 -2
  111. data/lib/sisimai/rfc3464.rb +87 -101
  112. data/lib/sisimai/rfc3834.rb +29 -39
  113. data/lib/sisimai/rfc5322.rb +17 -24
  114. data/lib/sisimai/rhost.rb +10 -7
  115. data/lib/sisimai/rhost/exchangeonline.rb +124 -255
  116. data/lib/sisimai/rhost/franceptt.rb +2 -2
  117. data/lib/sisimai/rhost/godaddy.rb +12 -25
  118. data/lib/sisimai/rhost/googleapps.rb +82 -183
  119. data/lib/sisimai/smtp.rb +4 -4
  120. data/lib/sisimai/smtp/error.rb +8 -8
  121. data/lib/sisimai/smtp/reply.rb +1 -1
  122. data/lib/sisimai/smtp/status.rb +1 -0
  123. data/lib/sisimai/string.rb +5 -7
  124. data/lib/sisimai/version.rb +1 -1
  125. data/set-of-emails/README.md +1 -1
  126. data/set-of-emails/maildir/bsd/README.md +50 -50
  127. data/sisimai-java.gemspec +1 -1
  128. data/sisimai.gemspec +1 -1
  129. metadata +5 -5
  130. data/lib/sisimai/skeleton.rb +0 -43
@@ -6,25 +6,18 @@ module Sisimai::Bite::Email
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/EZweb.pm
7
7
  require 'sisimai/bite/email'
8
8
 
9
- Re0 = {
10
- :'from' => %r/[<]?(?>postmaster[@]ezweb[.]ne[.]jp)[>]?/i,
11
- :'subject' => %r/\AMail System Error - Returned Mail\z/,
12
- :'received' => %r/\Afrom[ ](?:.+[.])?ezweb[.]ne[.]jp[ ]/,
13
- :'message-id' => %r/[@].+[.]ezweb[.]ne[.]jp[>]\z/,
14
- }.freeze
15
- Re1 = {
16
- :begin => %r{\A(?:
9
+ Indicators = Sisimai::Bite::Email.INDICATORS
10
+ MarkingsOf = {
11
+ message: %r{\A(?:
17
12
  The[ ]user[(]s[)][ ]
18
13
  |Your[ ]message[ ]
19
14
  |Each[ ]of[ ]the[ ]following
20
15
  |[<][^ ]+[@][^ ]+[>]\z
21
16
  )
22
17
  }x,
23
- :rfc822 => %r#\A(?:[-]{50}|Content-Type:[ ]*message/rfc822)#,
24
- :boundary => %r/\A__SISIMAI_PSEUDO_BOUNDARY__\z/,
25
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
18
+ rfc822: %r#\A(?:[-]{50}|Content-Type:[ ]*message/rfc822)#,
26
19
  }.freeze
27
- ReFailure = {
20
+ ReFailures = {
28
21
  # notaccept: [ %r/The following recipients did not receive this message:/ ],
29
22
  mailboxfull: [
30
23
  %r/The user[(]s[)] account is temporarily over quota/,
@@ -44,12 +37,10 @@ module Sisimai::Bite::Email
44
37
  %r/Each of the following recipients was rejected by a remote mail server/,
45
38
  ],
46
39
  }.freeze
47
- Indicators = Sisimai::Bite::Email.INDICATORS
48
40
 
49
41
  def description; return 'au EZweb: http://www.au.kddi.com/mobile/'; end
50
42
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
51
43
  def headerlist; return ['X-SPASIGN']; end
52
- def pattern; return Re0; end
53
44
 
54
45
  # Parse bounce messages from au EZweb
55
46
  # @param [Hash] mhead Message headers of a bounce email
@@ -67,11 +58,11 @@ module Sisimai::Bite::Email
67
58
  return nil unless mbody
68
59
 
69
60
  match = 0
70
- match += 1 if mhead['from'] =~ Re0[:from]
71
- match += 1 if mhead['subject'] =~ Re0[:subject]
72
- match += 1 if mhead['received'].find { |a| a =~ Re0[:received] }
61
+ match += 1 if mhead['from'].include?('Postmaster@ezweb.ne.jp')
62
+ match += 1 if mhead['subject'] == 'Mail System Error - Returned Mail'
63
+ match += 1 if mhead['received'].find { |a| a.include?('ezweb.ne.jp (EZweb Mail) with') }
73
64
  if mhead['message-id']
74
- match += 1 if mhead['message-id'] =~ Re0[:'message-id']
65
+ match += 1 if mhead['message-id'].end_with?('.ezweb.ne.jp>')
75
66
  end
76
67
  return nil if match < 2
77
68
 
@@ -93,21 +84,21 @@ module Sisimai::Bite::Email
93
84
  b0 = Sisimai::MIME.boundary(mhead['content-type'], 1)
94
85
  if b0.size > 0
95
86
  # Convert to regular expression
96
- rxboundary = Regexp.new('\A' + Regexp.escape(b0) + '\z')
87
+ rxboundary = Regexp.new('\A' << Regexp.escape(b0) << '\z')
97
88
  end
98
89
  end
99
90
  rxmessages = []
100
- ReFailure.each_key { |a| rxmessages.concat(ReFailure[a]) }
91
+ ReFailures.each_key { |a| rxmessages.concat(ReFailures[a]) }
101
92
 
102
- hasdivided.each do |e|
93
+ while e = hasdivided.shift do
103
94
  if readcursor.zero?
104
95
  # Beginning of the bounce message or delivery status part
105
- readcursor |= Indicators[:deliverystatus] if e =~ Re1[:begin]
96
+ readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
106
97
  end
107
98
 
108
99
  if (readcursor & Indicators[:'message-rfc822']).zero?
109
100
  # Beginning of the original message part
110
- if e =~ Re1[:rfc822] || e =~ rxboundary
101
+ if e =~ MarkingsOf[:rfc822] || e =~ rxboundary
111
102
  readcursor |= Indicators[:'message-rfc822']
112
103
  next
113
104
  end
@@ -121,7 +112,6 @@ module Sisimai::Bite::Email
121
112
  next
122
113
  end
123
114
  rfc822list << e
124
-
125
115
  else
126
116
  # Before "message/rfc822"
127
117
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -156,41 +146,38 @@ module Sisimai::Bite::Email
156
146
  recipients += 1
157
147
  end
158
148
 
159
- elsif cv = e.match(/\A[Ss]tatus:[ ]*(\d[.]\d+[.]\d+)/)
149
+ elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
160
150
  # Status: 5.1.1
161
151
  # Status:5.2.0
162
152
  # Status: 5.1.0 (permanent failure)
163
153
  v['status'] = cv[1]
164
154
 
165
- elsif cv = e.match(/\A[Aa]ction:[ ]*(.+)\z/)
155
+ elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
166
156
  # Action: failed
167
157
  v['action'] = cv[1].downcase
168
158
 
169
- elsif cv = e.match(/\A[Rr]emote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
159
+ elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
170
160
  # Remote-MTA: DNS; mx.example.jp
171
161
  v['rhost'] = cv[1].downcase
172
162
 
173
- elsif cv = e.match(/\A[Ll]ast-[Aa]ttempt-[Dd]ate:[ ]*(.+)\z/)
163
+ elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
174
164
  # Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
175
165
  v['date'] = cv[1]
176
-
177
166
  else
178
167
  next if Sisimai::String.is_8bit(e)
179
168
  if cv = e.match(/\A[ \t]+[>]{3}[ \t]+([A-Z]{4})/)
180
169
  # >>> RCPT TO:<******@ezweb.ne.jp>
181
170
  v['command'] = cv[1]
182
-
183
171
  else
184
172
  # Check error message
185
173
  if rxmessages.find { |a| e =~ a }
186
174
  # Check with regular expressions of each error
187
175
  v['diagnosis'] ||= ''
188
- v['diagnosis'] += ' ' + e
189
-
176
+ v['diagnosis'] << ' ' << e
190
177
  else
191
178
  # >>> 550
192
179
  v['alterrors'] ||= ''
193
- v['alterrors'] += ' ' + e
180
+ v['alterrors'] << ' ' << e
194
181
  end
195
182
  end
196
183
  end
@@ -199,10 +186,10 @@ module Sisimai::Bite::Email
199
186
  return nil if recipients.zero?
200
187
 
201
188
  dscontents.map do |e|
202
- if e['alterrors'] && e['alterrors'].size > 0
189
+ if e['alterrors'].to_s.size > 0
203
190
  # Copy alternative error message
204
191
  e['diagnosis'] ||= e['alterrors']
205
- if e['diagnosis'] =~ /\A[-]+/ || e['diagnosis'].end_with?('__')
192
+ if e['diagnosis'].start_with?('-') || e['diagnosis'].end_with?('__')
206
193
  # Override the value of diagnostic code message
207
194
  e['diagnosis'] = e['alterrors'] if e['alterrors'].size > 0
208
195
  end
@@ -210,11 +197,10 @@ module Sisimai::Bite::Email
210
197
  end
211
198
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
212
199
 
213
- if mhead['x-spasign'] && mhead['x-spasign'] == 'NG'
200
+ if mhead['x-spasign'].to_s == 'NG'
214
201
  # Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by EZweb)
215
202
  # Filtered recipient returns message that include 'X-SPASIGN' header
216
203
  e['reason'] = 'filtered'
217
-
218
204
  else
219
205
  if e['command'] == 'RCPT'
220
206
  # set "userunknown" when the remote server rejected after RCPT
@@ -223,9 +209,9 @@ module Sisimai::Bite::Email
223
209
  else
224
210
  # SMTP command is not RCPT
225
211
  catch :SESSION do
226
- ReFailure.each_key do |r|
212
+ ReFailures.each_key do |r|
227
213
  # Verify each regular expression of session errors
228
- ReFailure[r].each do |rr|
214
+ ReFailures[r].each do |rr|
229
215
  # Check each regular expression
230
216
  next unless e['diagnosis'] =~ rr
231
217
  e['reason'] = r.to_s
@@ -239,11 +225,9 @@ module Sisimai::Bite::Email
239
225
 
240
226
  unless e['reason']
241
227
  # The value of "reason" is not set yet.
242
- unless e['recipient'] =~ /[@]ezweb[.]ne[.]jp\z/
243
- # Deal as "userunknown" when the domain part of the recipient
244
- # is "ezweb.ne.jp".
245
- e['reason'] = 'userunknown'
246
- end
228
+ # Deal as "userunknown" when the domain part of the recipient
229
+ # is "ezweb.ne.jp".
230
+ e['reason'] = 'userunknown' unless e['recipient'].end_with?('@ezweb.ne.jp')
247
231
  end
248
232
  e['agent'] = self.smtpagent
249
233
  end
@@ -6,19 +6,14 @@ module Sisimai::Bite::Email
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/Facebook.pm
7
7
  require 'sisimai/bite/email'
8
8
 
9
- Re0 = {
10
- :from => %r/\AFacebook [<]mailer-daemon[@]mx[.]facebook[.]com[>]\z/,
11
- :subject => %r/\ASorry, your message could not be delivered\z/,
12
- }.freeze
13
- Re1 = {
14
- :begin => %r/\AThis message was created automatically by Facebook[.]\z/,
15
- :rfc822 => %r/\AContent-Disposition: inline\z/,
16
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
9
+ Indicators = Sisimai::Bite::Email.INDICATORS
10
+ StartingOf = {
11
+ message: ['This message was created automatically by Facebook.'],
12
+ rfc822: ['Content-Disposition: inline'],
17
13
  }.freeze
18
-
19
- # http://postmaster.facebook.com/response_codes
20
- # NOT TESTD EXCEPT RCP-P2
21
- ReFailure = {
14
+ ReFailures = {
15
+ # http://postmaster.facebook.com/response_codes
16
+ # NOT TESTD EXCEPT RCP-P2
22
17
  userunknown: [
23
18
  'RCP-P1', # The attempted recipient address does not exist.
24
19
  'INT-P1', # The attempted recipient address does not exist.
@@ -75,12 +70,10 @@ module Sisimai::Bite::Email
75
70
  'CON-T4', # Your mail server has exceeded the maximum number of recipients for its current connection.
76
71
  ],
77
72
  }.freeze
78
- Indicators = Sisimai::Bite::Email.INDICATORS
79
73
 
80
74
  def description; return 'Facebook: https://www.facebook.com'; end
81
75
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
82
76
  def headerlist; return []; end
83
- def pattern; return Re0; end
84
77
 
85
78
  # Parse bounce messages from Facebook
86
79
  # @param [Hash] mhead Message headers of a bounce email
@@ -96,8 +89,8 @@ module Sisimai::Bite::Email
96
89
  def scan(mhead, mbody)
97
90
  return nil unless mhead
98
91
  return nil unless mbody
99
- return nil unless mhead['from'] =~ Re0[:from]
100
- return nil unless mhead['subject'] =~ Re0[:subject]
92
+ return nil unless mhead['from'] == 'Facebook <mailer-daemon@mx.facebook.com>'
93
+ return nil unless mhead['subject'] == 'Sorry, your message could not be delivered'
101
94
 
102
95
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
103
96
  hasdivided = mbody.split("\n")
@@ -114,14 +107,14 @@ module Sisimai::Bite::Email
114
107
  }
115
108
  v = nil
116
109
 
117
- hasdivided.each do |e|
110
+ while e = hasdivided.shift do
118
111
  # Save the current line for the next loop
119
112
  havepassed << e
120
113
  p = havepassed[-2]
121
114
 
122
115
  if readcursor.zero?
123
116
  # Beginning of the bounce message or delivery status part
124
- if e =~ Re1[:begin]
117
+ if e == StartingOf[:message][0]
125
118
  readcursor |= Indicators[:deliverystatus]
126
119
  next
127
120
  end
@@ -129,7 +122,7 @@ module Sisimai::Bite::Email
129
122
 
130
123
  if (readcursor & Indicators[:'message-rfc822']).zero?
131
124
  # Beginning of the original message part
132
- if e =~ Re1[:rfc822]
125
+ if e == StartingOf[:rfc822][0]
133
126
  readcursor |= Indicators[:'message-rfc822']
134
127
  next
135
128
  end
@@ -143,7 +136,6 @@ module Sisimai::Bite::Email
143
136
  next
144
137
  end
145
138
  rfc822list << e
146
-
147
139
  else
148
140
  # Before "message/rfc822"
149
141
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -154,7 +146,7 @@ module Sisimai::Bite::Email
154
146
  # Arrival-Date: Thu, 23 Jun 2011 02:29:43 -0700
155
147
  v = dscontents[-1]
156
148
 
157
- if cv = e.match(/\A[Ff]inal-[Rr]ecipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
149
+ if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
158
150
  # Final-Recipient: RFC822; userunknown@example.jp
159
151
  if v['recipient']
160
152
  # There are multiple recipient addresses in the message body.
@@ -164,51 +156,48 @@ module Sisimai::Bite::Email
164
156
  v['recipient'] = cv[1]
165
157
  recipients += 1
166
158
 
167
- elsif cv = e.match(/\A[Xx]-[Aa]ctual-[Rr]ecipient:[ ]*(?:RFC|rfc)822;[ ]*(.+)\z/)
159
+ elsif cv = e.match(/\AX-Actual-Recipient:[ ]*(?:RFC|rfc)822;[ ]*(.+)\z/)
168
160
  # X-Actual-Recipient: RFC822; kijitora@example.co.jp
169
161
  v['alias'] = cv[1]
170
162
 
171
- elsif cv = e.match(/\A[Aa]ction:[ ]*(.+)\z/)
163
+ elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
172
164
  # Action: failed
173
165
  v['action'] = cv[1].downcase
174
166
 
175
- elsif cv = e.match(/\A[Ss]tatus:[ ]*(\d[.]\d+[.]\d+)/)
167
+ elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
176
168
  # Status: 5.1.1
177
169
  # Status:5.2.0
178
170
  # Status: 5.1.0 (permanent failure)
179
171
  v['status'] = cv[1]
180
172
 
181
- elsif cv = e.match(/\A[Rr]emote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
173
+ elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
182
174
  # Remote-MTA: DNS; mx.example.jp
183
175
  v['rhost'] = cv[1].downcase
184
176
 
185
- elsif cv = e.match(/\A[Ll]ast-[Aa]ttempt-[Dd]ate:[ ]*(.+)\z/)
177
+ elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
186
178
  # Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
187
179
  v['date'] = cv[1]
188
-
189
180
  else
190
- if cv = e.match(/\A[Dd]iagnostic-[Cc]ode:[ ]*(.+?);[ ]*(.+)\z/)
181
+ if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
191
182
  # Diagnostic-Code: smtp; 550 5.1.1 RCP-P2
192
183
  # http://postmaster.facebook.com/response_codes?ip=192.0.2.135#rcp Refused due to recipient preferences
193
184
  v['spec'] = cv[1].upcase
194
185
  v['diagnosis'] = cv[2]
195
186
 
196
- elsif p =~ /\A[Dd]iagnostic-[Cc]ode:[ ]*/ && cv = e.match(/\A[ \t]+(.+)\z/)
187
+ elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
197
188
  # Continued line of the value of Diagnostic-Code header
198
- v['diagnosis'] ||= ''
199
- v['diagnosis'] += ' ' + cv[1]
200
- havepassed[-1] = 'Diagnostic-Code: ' + e
189
+ v['diagnosis'] << ' ' << cv[1]
190
+ havepassed[-1] = 'Diagnostic-Code: ' << e
201
191
  end
202
192
  end
203
-
204
193
  else
205
- if cv = e.match(/\A[Rr]eporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
194
+ if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
206
195
  # Reporting-MTA: dns; mx.example.jp
207
196
  next if connheader['lhost'].size > 0
208
197
  connheader['lhost'] = cv[1].downcase
209
198
  connvalues += 1
210
199
 
211
- elsif cv = e.match(/\A[Aa]rrival-[Dd]ate:[ ]*(.+)\z/)
200
+ elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
212
201
  # Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
213
202
  next if connheader['date'].size > 0
214
203
  connheader['date'] = cv[1]
@@ -236,9 +225,9 @@ module Sisimai::Bite::Email
236
225
  end
237
226
 
238
227
  catch :SESSION do
239
- ReFailure.each_key do |r|
228
+ ReFailures.each_key do |r|
240
229
  # Verify each regular expression of session errors
241
- ReFailure[r].each do |rr|
230
+ ReFailures[r].each do |rr|
242
231
  # Check each regular expression
243
232
  next unless fbresponse == rr
244
233
  e['reason'] = r.to_s
@@ -6,14 +6,8 @@ module Sisimai::Bite::Email
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/FML.pm
7
7
  require 'sisimai/bite/email'
8
8
 
9
- Re0 = {
10
- :'from' => %r/.+[-]admin[@].+/,
11
- :'message-id' => %r/\A[<]\d+[.]FML.+[@].+[>]\z/,
12
- }.freeze
13
- Re1 = {
14
- :rfc822 => %r/\AOriginal[ ]mail[ ]as[ ]follows:\z/,
15
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
16
- }.freeze
9
+ Indicators = Sisimai::Bite::Email.INDICATORS
10
+ StartingOf = { rfc822: ['Original mail as follows:'] }.freeze
17
11
  ErrorTitle = {
18
12
  :rejected => %r{(?>
19
13
  (?:Ignored[ ])*NOT[ ]MEMBER[ ]article[ ]from[ ]
@@ -29,7 +23,7 @@ module Sisimai::Bite::Email
29
23
  |WARNING:[ ]UNIX[ ]FROM[ ]Loop
30
24
  )
31
25
  }x,
32
- :securityerror => %r/Security[ ]Alert/,
26
+ :securityerror => %r/Security Alert/,
33
27
  }.freeze
34
28
  ErrorTable = {
35
29
  :rejected => %r{(?>
@@ -48,14 +42,12 @@ module Sisimai::Bite::Email
48
42
  |Loop[ ]Back[ ]Warning:
49
43
  )
50
44
  }x,
51
- :securityerror => %r/Security[ ]alert:/,
45
+ :securityerror => %r/Security alert:/,
52
46
  }.freeze
53
- Indicators = Sisimai::Bite::Email.INDICATORS
54
47
 
55
48
  def description; return 'fml mailing list server/manager'; end
56
49
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
57
50
  def headerlist; return ['X-MLServer']; end
58
- def pattern; return Re0; end
59
51
 
60
52
  # Parse bounce messages from fml mailling list server/manager
61
53
  # @param [Hash] mhead Message headers of a bounce email
@@ -72,8 +64,8 @@ module Sisimai::Bite::Email
72
64
  return nil unless mhead
73
65
  return nil unless mbody
74
66
  return nil unless mhead['x-mlserver']
75
- return nil unless mhead['from'] =~ Re0[:from]
76
- return nil unless mhead['message-id'] =~ Re0[:'message-id']
67
+ return nil unless mhead['from'] =~ /.+[-]admin[@].+/
68
+ return nil unless mhead['message-id'] =~ /\A[<]\d+[.]FML.+[@].+[>]\z/
77
69
 
78
70
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
79
71
  hasdivided = mbody.split("\n")
@@ -84,10 +76,10 @@ module Sisimai::Bite::Email
84
76
  v = nil
85
77
 
86
78
  readcursor |= Indicators[:deliverystatus]
87
- hasdivided.each do |e|
79
+ while e = hasdivided.shift do
88
80
  if (readcursor & Indicators[:'message-rfc822']).zero?
89
81
  # Beginning of the original message part
90
- if e =~ Re1[:rfc822]
82
+ if e == StartingOf[:rfc822][0]
91
83
  readcursor |= Indicators[:'message-rfc822']
92
84
  next
93
85
  end
@@ -105,8 +97,7 @@ module Sisimai::Bite::Email
105
97
  break if blanklines > 1
106
98
  next
107
99
  end
108
- e = e.sub(/\A[ ]{3}/, '')
109
- rfc822list << e
100
+ rfc822list << e.lstrip
110
101
  else
111
102
  # Before "message/rfc822"
112
103
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -130,13 +121,13 @@ module Sisimai::Bite::Email
130
121
  # If you know the general guide of this list, please send mail with
131
122
  # the mail body
132
123
  v['diagnosis'] ||= ''
133
- v['diagnosis'] += e
124
+ v['diagnosis'] << e
134
125
  end
135
126
  end
136
127
  end
137
128
  return nil if recipients.zero?
138
- require 'sisimai/string'
139
129
 
130
+ require 'sisimai/string'
140
131
  dscontents.map do |e|
141
132
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
142
133
  e['agent'] = self.smtpagent
@@ -6,19 +6,12 @@ module Sisimai::Bite::Email
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/GMX.pm
7
7
  require 'sisimai/bite/email'
8
8
 
9
- Re0 = {
10
- :from => %r/\AMAILER-DAEMON[@]/,
11
- :subject => %r/\AMail delivery failed: returning message to sender\z/,
12
- }.freeze
13
- Re1 = {
14
- :begin => %r/\AThis message was created automatically by mail delivery software/,
15
- :rfc822 => %r/\A--- The header of the original message is following/,
16
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
17
- }.freeze
18
- ReFailure = {
19
- expired: %r/delivery[ ]retry[ ]timeout[ ]exceeded/x,
20
- }.freeze
21
9
  Indicators = Sisimai::Bite::Email.INDICATORS
10
+ StartingOf = {
11
+ message: ['This message was created automatically by mail delivery software'],
12
+ rfc822: ['--- The header of the original message is following'],
13
+ }.freeze
14
+ ReFailures = { expired: %r/delivery retry timeout exceeded/ }.freeze
22
15
 
23
16
  def description; return 'GMX: http://www.gmx.net'; end
24
17
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
@@ -28,7 +21,6 @@ module Sisimai::Bite::Email
28
21
  # X-GMX-Antivirus: 0 (no virus found)
29
22
  # X-UI-Out-Filterresults: unknown:0;
30
23
  def headerlist; return ['X-GMX-Antispam']; end
31
- def pattern; return Re0; end
32
24
 
33
25
  # Parse bounce messages from GMX
34
26
  # @param [Hash] mhead Message headers of a bounce email
@@ -44,6 +36,9 @@ module Sisimai::Bite::Email
44
36
  def scan(mhead, mbody)
45
37
  return nil unless mhead
46
38
  return nil unless mbody
39
+
40
+ # :from => %r/\AMAILER-DAEMON[@]/,
41
+ # :subject => %r/\AMail delivery failed: returning message to sender\z/,
47
42
  return nil unless mhead['x-gmx-antispam']
48
43
 
49
44
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
@@ -54,10 +49,10 @@ module Sisimai::Bite::Email
54
49
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
55
50
  v = nil
56
51
 
57
- hasdivided.each do |e|
52
+ while e = hasdivided.shift do
58
53
  if readcursor.zero?
59
54
  # Beginning of the bounce message or delivery status part
60
- if e =~ Re1[:begin]
55
+ if e.start_with?(StartingOf[:message][0])
61
56
  readcursor |= Indicators[:deliverystatus]
62
57
  next
63
58
  end
@@ -65,7 +60,7 @@ module Sisimai::Bite::Email
65
60
 
66
61
  if (readcursor & Indicators[:'message-rfc822']).zero?
67
62
  # Beginning of the original message part
68
- if e =~ Re1[:rfc822]
63
+ if e.start_with?(StartingOf[:rfc822][0])
69
64
  readcursor |= Indicators[:'message-rfc822']
70
65
  next
71
66
  end
@@ -79,7 +74,6 @@ module Sisimai::Bite::Email
79
74
  next
80
75
  end
81
76
  rfc822list << e
82
-
83
77
  else
84
78
  # Before "message/rfc822"
85
79
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -119,39 +113,35 @@ module Sisimai::Bite::Email
119
113
  elsif cv = e.match(/\Ahost:[ \t]*(.+)\z/)
120
114
  # host: mx.example.jp
121
115
  v['rhost'] = cv[1]
122
-
123
116
  else
124
117
  # Get error message
125
118
  if e =~ /\b[45][.]\d[.]\d\b/ || e =~ /[<][^ ]+[@][^ ]+[>]/ || e =~ /\b[45]\d{2}\b/
126
119
  v['diagnosis'] ||= e
127
-
128
120
  else
129
- next if e =~ /\A\z/
130
- if e =~ /\AReason:\z/
121
+ next if e.empty?
122
+ if e.start_with?('Reason:')
131
123
  # Reason:
132
124
  # delivery retry timeout exceeded
133
125
  v['diagnosis'] = e
134
126
 
135
- elsif v['diagnosis'] =~ /\AReason:\z/
127
+ elsif v['diagnosis'] == 'Reason:'
136
128
  v['diagnosis'] = e
137
129
  end
138
130
  end
139
131
  end
140
132
  end
141
133
  end
142
-
143
134
  return nil if recipients.zero?
144
- require 'sisimai/string'
145
- require 'sisimai/smtp/status'
146
135
 
136
+ require 'sisimai/string'
147
137
  dscontents.map do |e|
148
138
  e['agent'] = self.smtpagent
149
139
  e['diagnosis'] = e['diagnosis'].gsub(/\\n/, ' ')
150
140
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
151
141
 
152
- ReFailure.each_key do |r|
142
+ ReFailures.each_key do |r|
153
143
  # Verify each regular expression of session errors
154
- next unless e['diagnosis'] =~ ReFailure[r]
144
+ next unless e['diagnosis'] =~ ReFailures[r]
155
145
  e['reason'] = r.to_s
156
146
  break
157
147
  end