sisimai 4.22.3-java → 4.22.4-java

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 +4 -4
  130. data/lib/sisimai/skeleton.rb +0 -43
@@ -6,15 +6,12 @@ module Sisimai::Bite::Email
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/Domino.pm
7
7
  require 'sisimai/bite/email'
8
8
 
9
- Re0 = {
10
- :subject => %r/\ADELIVERY FAILURE:/,
11
- }.freeze
12
- Re1 = {
13
- :begin => %r/\AYour message/,
14
- :rfc822 => %r|\AContent-Type: message/delivery-status\z|,
15
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
9
+ Indicators = Sisimai::Bite::Email.INDICATORS
10
+ StartingOf = {
11
+ message: ['Your message'],
12
+ rfc822: ['Content-Type: message/delivery-status'],
16
13
  }.freeze
17
- ReFailure = {
14
+ ReFailures = {
18
15
  userunknown: %r{(?>
19
16
  not[ ]listed[ ]in[ ](?:
20
17
  Domino[ ]Directory
@@ -23,15 +20,13 @@ module Sisimai::Bite::Email
23
20
  |Domino[ ]ディレクトリには見つかりません
24
21
  )
25
22
  }x,
26
- filtered: %r/Cannot[ ]route[ ]mail[ ]to[ ]user/x,
27
- systemerror: %r/Several[ ]matches[ ]found[ ]in[ ]Domino[ ]Directory/x,
23
+ filtered: %r/Cannot route mail to user/,
24
+ systemerror: %r/Several matches found in Domino Directory/,
28
25
  }.freeze
29
- Indicators = Sisimai::Bite::Email.INDICATORS
30
26
 
31
27
  def description; return 'IBM Domino Server'; end
32
28
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
33
29
  def headerlist; return []; end
34
- def pattern; return Re0; end
35
30
 
36
31
  # Parse bounce messages from IBM Domino Server
37
32
  # @param [Hash] mhead Message headers of a bounce email
@@ -47,7 +42,7 @@ module Sisimai::Bite::Email
47
42
  def scan(mhead, mbody)
48
43
  return nil unless mhead
49
44
  return nil unless mbody
50
- return nil unless mhead['subject'] =~ Re0[:subject]
45
+ return nil unless mhead['subject'].start_with?('DELIVERY FAILURE:')
51
46
 
52
47
  require 'sisimai/address'
53
48
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
@@ -59,12 +54,12 @@ module Sisimai::Bite::Email
59
54
  subjecttxt = '' # (String) The value of Subject:
60
55
  v = nil
61
56
 
62
- hasdivided.each do |e|
57
+ while e = hasdivided.shift do
63
58
  next if e.empty?
64
59
 
65
60
  if readcursor.zero?
66
61
  # Beginning of the bounce message or delivery status part
67
- if e =~ Re1[:begin]
62
+ if e.start_with?(StartingOf[:message][0])
68
63
  readcursor |= Indicators[:deliverystatus]
69
64
  next
70
65
  end
@@ -72,7 +67,7 @@ module Sisimai::Bite::Email
72
67
 
73
68
  if (readcursor & Indicators[:'message-rfc822']).zero?
74
69
  # Beginning of the original message part
75
- if e =~ Re1[:rfc822]
70
+ if e == StartingOf[:rfc822][0]
76
71
  readcursor |= Indicators[:'message-rfc822']
77
72
  next
78
73
  end
@@ -86,7 +81,6 @@ module Sisimai::Bite::Email
86
81
  next
87
82
  end
88
83
  rfc822list << e
89
-
90
84
  else
91
85
  # Before "message/rfc822"
92
86
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -105,7 +99,7 @@ module Sisimai::Bite::Email
105
99
  #
106
100
  v = dscontents[-1]
107
101
 
108
- if e =~ /\Awas not delivered to:\z/
102
+ if e.start_with?('was not delivered to:')
109
103
  # was not delivered to:
110
104
  if v['recipient']
111
105
  # There are multiple recipient addresses in the message body.
@@ -120,13 +114,11 @@ module Sisimai::Bite::Email
120
114
  # kijitora@example.net
121
115
  v['recipient'] = Sisimai::Address.s3s4(cv[1])
122
116
 
123
- elsif e =~ /\Abecause:\z/
117
+ elsif e.start_with?('because:')
124
118
  # because:
125
119
  v['diagnosis'] = e
126
-
127
120
  else
128
-
129
- if v['diagnosis'] && v['diagnosis'] == 'because:'
121
+ if v['diagnosis'].to_s == 'because:'
130
122
  # Error message, continued from the line "because:"
131
123
  v['diagnosis'] = e
132
124
 
@@ -137,19 +129,18 @@ module Sisimai::Bite::Email
137
129
  end
138
130
  end
139
131
  end
140
-
141
132
  return nil if recipients.zero?
133
+
142
134
  require 'sisimai/string'
143
135
  require 'sisimai/smtp/status'
144
-
145
136
  dscontents.map do |e|
146
137
  e['agent'] = self.smtpagent
147
138
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
148
139
  e['recipient'] = Sisimai::Address.s3s4(e['recipient'])
149
140
 
150
- ReFailure.each_key do |r|
141
+ ReFailures.each_key do |r|
151
142
  # Check each regular expression of Domino error messages
152
- next unless e['diagnosis'] =~ ReFailure[r]
143
+ next unless e['diagnosis'] =~ ReFailures[r]
153
144
  e['reason'] = r.to_s
154
145
  pseudostatus = Sisimai::SMTP::Status.code(r.to_s, false)
155
146
  e['status'] = pseudostatus if pseudostatus.size > 0
@@ -158,10 +149,10 @@ module Sisimai::Bite::Email
158
149
  e.each_key { |a| e[a] ||= '' }
159
150
  end
160
151
 
161
- unless rfc822list.find { |a| a =~ /^Subject:/ }
152
+ unless rfc822list.find { |a| a.start_with?('Subject:') }
162
153
  # Set the value of subjecttxt as a Subject if there is no original
163
154
  # message in the bounce mail.
164
- rfc822list << sprintf('Subject: %s', subjecttxt)
155
+ rfc822list << ('Subject: ' << subjecttxt)
165
156
  end
166
157
 
167
158
  rfc822part = Sisimai::RFC5322.weedout(rfc822list)
@@ -6,26 +6,18 @@ module Sisimai::Bite::Email
6
6
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/EinsUndEins.pm
7
7
  require 'sisimai/bite/email'
8
8
 
9
- Re0 = {
10
- :from => %r/\A["]Mail Delivery System["]/,
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
- :error => %r/\AFor the following reason:/,
16
- :rfc822 => %r/\A--- The header of the original message is following/,
17
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
18
- }.freeze
19
- ReFailure = {
20
- mesgtoobig: %r/Mail[ ]size[ ]limit[ ]exceeded/x,
21
- }.freeze
22
9
  Indicators = Sisimai::Bite::Email.INDICATORS
10
+ StartingOf = {
11
+ message: ['This message was created automatically by mail delivery software'],
12
+ error: ['For the following reason:'],
13
+ rfc822: ['--- The header of the original message is following'],
14
+ }.freeze
15
+ ReFailures = { mesgtoobig: %r/Mail size limit exceeded/ }.freeze
23
16
 
24
17
  def description; return '1&1: http://www.1and1.de'; end
25
18
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
26
19
  # X-UI-Out-Filterresults: unknown:0;
27
20
  def headerlist; return []; end
28
- def pattern; return Re0; end
29
21
 
30
22
  # Parse bounce messages from 1&1
31
23
  # @param [Hash] mhead Message headers of a bounce email
@@ -41,8 +33,8 @@ module Sisimai::Bite::Email
41
33
  def scan(mhead, mbody)
42
34
  return nil unless mhead
43
35
  return nil unless mbody
44
- return nil unless mhead['from'] =~ Re0[:from]
45
- return nil unless mhead['subject'] =~ Re0[:subject]
36
+ return nil unless mhead['from'].start_with?('"Mail Delivery System"')
37
+ return nil unless mhead['subject'] == 'Mail delivery failed: returning message to sender'
46
38
 
47
39
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
48
40
  hasdivided = mbody.split("\n")
@@ -52,10 +44,10 @@ module Sisimai::Bite::Email
52
44
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
53
45
  v = nil
54
46
 
55
- hasdivided.each do |e|
47
+ while e = hasdivided.shift do
56
48
  if readcursor.zero?
57
49
  # Beginning of the bounce message or delivery status part
58
- if e =~ Re1[:begin]
50
+ if e.start_with?(StartingOf[:message][0])
59
51
  readcursor |= Indicators[:deliverystatus]
60
52
  next
61
53
  end
@@ -63,7 +55,7 @@ module Sisimai::Bite::Email
63
55
 
64
56
  if (readcursor & Indicators[:'message-rfc822']).zero?
65
57
  # Beginning of the original message part
66
- if e =~ Re1[:rfc822]
58
+ if e.start_with?(StartingOf[:rfc822][0])
67
59
  readcursor |= Indicators[:'message-rfc822']
68
60
  next
69
61
  end
@@ -77,7 +69,6 @@ module Sisimai::Bite::Email
77
69
  next
78
70
  end
79
71
  rfc822list << e
80
-
81
72
  else
82
73
  # Before "message/rfc822"
83
74
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -103,31 +94,26 @@ module Sisimai::Bite::Email
103
94
  v['recipient'] = cv[1]
104
95
  recipients += 1
105
96
 
106
- elsif e =~ Re1[:error]
97
+ elsif e.start_with?(StartingOf[:error][0])
107
98
  # For the following reason:
108
99
  v['diagnosis'] = e
109
-
110
100
  else
111
- # Get error message
112
- if v['diagnosis']
113
- # Append error message strings
114
- v['diagnosis'] += ' ' + e
115
- end
101
+ # Get error message and append error message strings
102
+ v['diagnosis'] << ' ' << e if v['diagnosis']
116
103
  end
117
104
  end
118
105
  end
119
106
  return nil if recipients.zero?
120
- require 'sisimai/string'
121
107
 
108
+ require 'sisimai/string'
122
109
  dscontents.map do |e|
123
- e['agent'] = self.smtpagent
124
- e['diagnosis'] ||= ''
125
- e['diagnosis'] = e['diagnosis'].gsub(/\A#{Re1[:error]}/, '')
126
- e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
110
+ e['agent'] = self.smtpagent
111
+ e['diagnosis'] = e['diagnosis'].to_s.gsub(/\A#{StartingOf[:error][0]}/, '')
112
+ e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
127
113
 
128
- ReFailure.each_key do |r|
114
+ ReFailures.each_key do |r|
129
115
  # Verify each regular expression of session errors
130
- next unless e['diagnosis'] =~ ReFailure[r]
116
+ next unless e['diagnosis'] =~ ReFailures[r]
131
117
  e['reason'] = r.to_s
132
118
  break
133
119
  end
@@ -7,25 +7,13 @@ module Sisimai::Bite::Email
7
7
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/Exchange2003.pm
8
8
  require 'sisimai/bite/email'
9
9
 
10
- Re0 = {
11
- # X-Mailer: Internet Mail Service (5.0.1461.28)
12
- # X-Mailer: Microsoft Exchange Server Internet Mail Connector Version ...
13
- :'x-mailer' => %r{\A(?:
14
- Internet[ ]Mail[ ]Service[ ][(][\d.]+[)]\z
15
- |Microsoft[ ]Exchange[ ]Server[ ]Internet[ ]Mail[ ]Connector
16
- )
17
- }x,
18
- :'x-mimeole' => %r/\AProduced By Microsoft Exchange/,
19
- # Received: by ***.**.** with Internet Mail Service (5.5.2657.72)
20
- :'received' => %r/\Aby .+ with Internet Mail Service [(][\d.]+[)]/,
21
- }.freeze
22
- Re1 = {
23
- :begin => %r/\AYour message/,
24
- :error => %r/\Adid not reach the following recipient[(]s[)]:/,
25
- :rfc822 => %r|\AContent-Type: message/rfc822|,
26
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
10
+ Indicators = Sisimai::Bite::Email.INDICATORS
11
+ StartingOf = {
12
+ message: ['Your message'],
13
+ error: ['did not reach the following recipient(s):'],
14
+ rfc822: ['Content-Type: message/rfc822'],
27
15
  }.freeze
28
- CodeTable = {
16
+ ErrorCodes = {
29
17
  onhold: [
30
18
  '000B099C', # Host Unknown, Message exceeds size limit, ...
31
19
  '000B09AA', # Unable to relay for, Message exceeds size limit,...
@@ -52,12 +40,10 @@ module Sisimai::Bite::Email
52
40
  '000C0595', # Ambiguous Recipient
53
41
  ],
54
42
  }.freeze
55
- Indicators = Sisimai::Bite::Email.INDICATORS
56
43
 
57
44
  def description; return 'Microsoft Exchange Server 2003'; end
58
45
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
59
46
  def headerlist; return ['X-MS-Embedded-Report', 'X-MimeOLE']; end
60
- def pattern; return Re0; end
61
47
 
62
48
  # Parse bounce messages from Microsoft Exchange Server 2003
63
49
  # @param [Hash] mhead Message headers of a bounce email
@@ -74,29 +60,31 @@ module Sisimai::Bite::Email
74
60
  return nil unless mhead
75
61
  return nil unless mbody
76
62
  match = 0
63
+ tryto = []
77
64
 
78
65
  match += 1 if mhead['x-ms-embedded-report']
79
66
  catch :EXCHANGE_OR_NOT do
80
- loop do
67
+ while true
81
68
  throw :EXCHANGE_OR_NOT if match > 0
82
69
 
83
70
  if mhead['x-mailer']
84
71
  # X-Mailer: Microsoft Exchange Server Internet Mail Connector Version 4.0.994.63
85
72
  # X-Mailer: Internet Mail Service (5.5.2232.9)
86
- match += 1 if mhead['x-mailer'] =~ Re0[:'x-mailer']
73
+ tryto = ['Internet Mail Service (', 'Microsoft Exchange Server Internet Mail Connector']
74
+ match += 1 if mhead['x-mailer'].start_with?(tryto[0], tryto[1])
87
75
  throw :EXCHANGE_OR_NOT if match > 0
88
76
  end
89
77
 
90
78
  if mhead['x-mimeole']
91
79
  # X-MimeOLE: Produced By Microsoft Exchange V6.5
92
- match += 1 if mhead['x-mimeole'] =~ Re0[:'x-mimeole']
80
+ match += 1 if mhead['x-mimeole'].start_with?('Produced By Microsoft Exchange')
93
81
  throw :EXCHANGE_OR_NOT if match > 0
94
82
  end
95
83
 
96
84
  throw :EXCHANGE_OR_NOT if mhead['received'].size.zero?
97
85
  mhead['received'].each do |e|
98
86
  # Received: by ***.**.** with Internet Mail Service (5.5.2657.72)
99
- next unless e =~ Re0[:'received']
87
+ next unless e.include?(' with Internet Mail Service (')
100
88
  match += 1
101
89
  throw :EXCHANGE_OR_NOT
102
90
  end
@@ -120,10 +108,10 @@ module Sisimai::Bite::Email
120
108
  }
121
109
  v = nil
122
110
 
123
- hasdivided.each do |e|
111
+ while e = hasdivided.shift do
124
112
  if readcursor.zero?
125
113
  # Beginning of the bounce message or delivery status part
126
- if e =~ Re1[:begin]
114
+ if e.start_with?(StartingOf[:message][0])
127
115
  readcursor |= Indicators[:deliverystatus]
128
116
  next
129
117
  end
@@ -131,7 +119,7 @@ module Sisimai::Bite::Email
131
119
 
132
120
  if (readcursor & Indicators[:'message-rfc822']).zero?
133
121
  # Beginning of the original message part
134
- if e =~ Re1[:rfc822]
122
+ if e.start_with?(StartingOf[:rfc822][0])
135
123
  readcursor |= Indicators[:'message-rfc822']
136
124
  next
137
125
  end
@@ -145,7 +133,6 @@ module Sisimai::Bite::Email
145
133
  next
146
134
  end
147
135
  rfc822list << e
148
-
149
136
  else
150
137
  # Before "message/rfc822"
151
138
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -182,24 +169,20 @@ module Sisimai::Bite::Email
182
169
  elsif cv = e.match(/\A[ \t]+(MSEXCH:.+)\z/)
183
170
  # MSEXCH:IMS:KIJITORA CAT:EXAMPLE:EXCHANGE 0 (000C05A6) Unknown Recipient
184
171
  v['diagnosis'] ||= ''
185
- v['diagnosis'] += cv[1]
186
-
172
+ v['diagnosis'] << cv[1]
187
173
  else
188
174
  next if v['msexch']
189
- if v['diagnosis'] =~ /\AMSEXCH:.+/
175
+ if v['diagnosis'].to_s.start_with?('MSEXCH:')
190
176
  # Continued from MEEXCH in the previous line
191
177
  v['msexch'] = true
192
- v['diagnosis'] ||= ''
193
- v['diagnosis'] += ' ' + e
178
+ v['diagnosis'] << ' ' << e
194
179
  statuspart = true
195
-
196
180
  else
197
181
  # Error message in the body part
198
182
  v['alterrors'] ||= ''
199
- v['alterrors'] += ' ' + e
183
+ v['alterrors'] << ' ' << e
200
184
  end
201
185
  end
202
-
203
186
  else
204
187
  # Your message
205
188
  #
@@ -230,11 +213,10 @@ module Sisimai::Bite::Email
230
213
  end
231
214
  end
232
215
  end
233
-
234
216
  return nil if recipients.zero?
217
+
235
218
  require 'sisimai/string'
236
219
  require 'sisimai/smtp/status'
237
-
238
220
  dscontents.map do |e|
239
221
  if cv = e['diagnosis'].match(/\AMSEXCH:.+[ \t]*[(]([0-9A-F]{8})[)][ \t]*(.*)\z/)
240
222
  # MSEXCH:IMS:KIJITORA CAT:EXAMPLE:EXCHANGE 0 (000C05A6) Unknown Recipient
@@ -242,9 +224,9 @@ module Sisimai::Bite::Email
242
224
  errormessage = cv[2]
243
225
  pseudostatus = ''
244
226
 
245
- CodeTable.each_key do |r|
227
+ ErrorCodes.each_key do |r|
246
228
  # Find captured code from the error code table
247
- next unless CodeTable[r].index(capturedcode)
229
+ next unless ErrorCodes[r].index(capturedcode)
248
230
  e['reason'] = r.to_s
249
231
  pseudostatus = Sisimai::SMTP::Status.code(r.to_s)
250
232
  e['status'] = pseudostatus if pseudostatus.size > 0
@@ -269,9 +251,9 @@ module Sisimai::Bite::Email
269
251
 
270
252
  if rfc822list.empty?
271
253
  # When original message does not included in the bounce message
272
- rfc822list << sprintf('From: %s', connheader['to'])
273
- rfc822list << sprintf('Date: %s', connheader['date'])
274
- rfc822list << sprintf('Subject: %s', connheader['subject'])
254
+ rfc822list << ('From: ' << connheader['to'])
255
+ rfc822list << ('Date: ' << connheader['date'])
256
+ rfc822list << ('Subject: ' << connheader['subject'])
275
257
  end
276
258
 
277
259
  rfc822part = Sisimai::RFC5322.weedout(rfc822list)
@@ -7,16 +7,12 @@ module Sisimai::Bite::Email
7
7
  # Imported from p5-Sisimail/lib/Sisimai/Bite/Email/Exchange2007.pm
8
8
  require 'sisimai/bite/email'
9
9
 
10
- Re0 = {
11
- :'subject' => %r/\AUndeliverable:/,
12
- :'content-language' => %r/\A[a-z]{2}(?:[-][A-Z]{2})?\z/,
13
- }.freeze
14
- Re1 = {
15
- :begin => %r/[ ]Microsoft[ ]Exchange[ ]Server[ ]20\d{2}/,
16
- :error => %r/[ ]((?:RESOLVER|QUEUE)[.][A-Za-z]+(?:[.]\w+)?);/,
17
- :rhost => %r/\AGenerating[ ]server:[ ]?(.*)/,
18
- :rfc822 => %r/\AOriginal message headers:/,
19
- :endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
10
+ Indicators = Sisimai::Bite::Email.INDICATORS
11
+ StartingOf = { rfc822: ['Original message headers:'] }.freeze
12
+ MarkingsOf = {
13
+ message: %r/ Microsoft Exchange Server 20\d{2}/,
14
+ error: %r/ ((?:RESOLVER|QUEUE)[.][A-Za-z]+(?:[.]\w+)?);/,
15
+ rhost: %r/\AGenerating server:[ ]?(.*)/,
20
16
  }.freeze
21
17
  NDRSubject = {
22
18
  :'SMTPSEND.DNS.NonExistentDomain'=> 'hostunknown', # 554 5.4.4 SMTPSEND.DNS.NonExistentDomain
@@ -32,12 +28,10 @@ module Sisimai::Bite::Email
32
28
  :'RESOLVER.RST.RecipSizeLimit' => 'mesgtoobig', # 550 5.2.3 RESOLVER.RST.RecipSizeLimit
33
29
  :'QUEUE.Expired' => 'expired', # 550 4.4.7 QUEUE.Expired
34
30
  }.freeze
35
- Indicators = Sisimai::Bite::Email.INDICATORS
36
31
 
37
32
  def description; return 'Microsoft Exchange Server 2007'; end
38
33
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
39
34
  def headerlist; return ['Content-Language']; end
40
- def pattern; return Re0; end
41
35
 
42
36
  # Parse bounce messages from Microsoft Exchange Server 2007
43
37
  # @param [Hash] mhead Message headers of a bounce email
@@ -54,9 +48,9 @@ module Sisimai::Bite::Email
54
48
  return nil unless mhead
55
49
  return nil unless mbody
56
50
 
57
- return nil unless mhead['subject'] =~ Re0[:'subject']
51
+ return nil unless mhead['subject'].start_with?('Undeliverable:')
58
52
  return nil unless mhead['content-language']
59
- return nil unless mhead['content-language'] =~ Re0[:'content-language']
53
+ return nil unless mhead['content-language'] =~ /\A[a-z]{2}(?:[-][A-Z]{2})?\z/
60
54
 
61
55
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
62
56
  hasdivided = mbody.split("\n")
@@ -70,10 +64,10 @@ module Sisimai::Bite::Email
70
64
  }
71
65
  v = nil
72
66
 
73
- hasdivided.each do |e|
67
+ while e = hasdivided.shift do
74
68
  if readcursor.zero?
75
69
  # Beginning of the bounce message or delivery status part
76
- if e =~ Re1[:begin]
70
+ if e =~ MarkingsOf[:message]
77
71
  readcursor |= Indicators[:deliverystatus]
78
72
  next
79
73
  end
@@ -81,7 +75,7 @@ module Sisimai::Bite::Email
81
75
 
82
76
  if (readcursor & Indicators[:'message-rfc822']).zero?
83
77
  # Beginning of the original message part
84
- if e =~ Re1[:rfc822]
78
+ if e.start_with?(StartingOf[:rfc822][0])
85
79
  readcursor |= Indicators[:'message-rfc822']
86
80
  next
87
81
  end
@@ -95,7 +89,6 @@ module Sisimai::Bite::Email
95
89
  next
96
90
  end
97
91
  rfc822list << e
98
-
99
92
  else
100
93
  # Before "message/rfc822"
101
94
  next if (readcursor & Indicators[:deliverystatus]).zero?
@@ -129,19 +122,18 @@ module Sisimai::Bite::Email
129
122
  v['replycode'] = cv[1]
130
123
  v['status'] = cv[2]
131
124
  v['diagnosis'] = e
132
-
133
125
  else
134
126
  if v['diagnosis'].to_s.size > 0 && v['diagnosis'].end_with?('=')
135
127
  # Continued line of error messages
136
- v['diagnosis'] = v['diagnosis'].sub(/=\z/, '')
137
- v['diagnosis'] += e
128
+ v['diagnosis'] = v['diagnosis'].chomp('=')
129
+ v['diagnosis'] << e
138
130
  end
139
131
  end
140
132
  else
141
133
  # Diagnostic information for administrators:
142
134
  #
143
135
  # Generating server: mta22.neko.example.org
144
- if cv = e.match(Re1[:rhost])
136
+ if cv = e.match(MarkingsOf[:rhost])
145
137
  # Generating server: mta22.neko.example.org
146
138
  next if connheader['rhost'].size > 0
147
139
  connheader['rhost'] = cv[1]
@@ -154,7 +146,7 @@ module Sisimai::Bite::Email
154
146
 
155
147
  require 'sisimai/string'
156
148
  dscontents.map do |e|
157
- if cv = e['diagnosis'].match(Re1[:error])
149
+ if cv = e['diagnosis'].match(MarkingsOf[:error])
158
150
  # #550 5.1.1 RESOLVER.ADR.RecipNotFound; not found ##
159
151
  f = cv[1]
160
152
  NDRSubject.each_key do |r|