sisimai 4.25.16-java → 5.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (177) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +3 -3
  3. data/ANALYTICAL-PRECISION +2 -2
  4. data/Benchmarks.mk +3 -3
  5. data/CONTRIBUTING +1 -1
  6. data/ChangeLog.md +412 -393
  7. data/Developers.mk +5 -6
  8. data/Gemfile +1 -1
  9. data/Makefile +15 -15
  10. data/README-JA.md +140 -78
  11. data/README.md +290 -143
  12. data/Rakefile +9 -3
  13. data/Repository.mk +2 -3
  14. data/lib/sisimai/address.rb +118 -74
  15. data/lib/sisimai/arf.rb +84 -82
  16. data/lib/sisimai/datetime.rb +5 -52
  17. data/lib/sisimai/{data → fact}/json.rb +7 -9
  18. data/lib/sisimai/fact/yaml.rb +31 -0
  19. data/lib/sisimai/fact.rb +468 -0
  20. data/lib/sisimai/lhost/activehunter.rb +12 -14
  21. data/lib/sisimai/lhost/amavis.rb +11 -14
  22. data/lib/sisimai/lhost/amazonses.rb +37 -41
  23. data/lib/sisimai/lhost/amazonworkmail.rb +15 -18
  24. data/lib/sisimai/lhost/aol.rb +12 -14
  25. data/lib/sisimai/lhost/apachejames.rb +19 -21
  26. data/lib/sisimai/lhost/barracuda.rb +10 -12
  27. data/lib/sisimai/lhost/bigfoot.rb +21 -21
  28. data/lib/sisimai/lhost/biglobe.rb +15 -16
  29. data/lib/sisimai/lhost/courier.rb +20 -20
  30. data/lib/sisimai/lhost/domino.rb +23 -19
  31. data/lib/sisimai/lhost/einsundeins.rb +23 -18
  32. data/lib/sisimai/lhost/exchange2003.rb +30 -29
  33. data/lib/sisimai/lhost/exchange2007.rb +70 -58
  34. data/lib/sisimai/lhost/exim.rb +175 -161
  35. data/lib/sisimai/lhost/ezweb.rb +31 -56
  36. data/lib/sisimai/lhost/facebook.rb +21 -33
  37. data/lib/sisimai/lhost/fml.rb +43 -48
  38. data/lib/sisimai/lhost/gmail.rb +29 -29
  39. data/lib/sisimai/lhost/gmx.rb +18 -17
  40. data/lib/sisimai/lhost/googlegroups.rb +9 -10
  41. data/lib/sisimai/lhost/gsuite.rb +21 -27
  42. data/lib/sisimai/lhost/imailserver.rb +25 -39
  43. data/lib/sisimai/lhost/interscanmss.rb +28 -31
  44. data/lib/sisimai/lhost/kddi.rb +22 -28
  45. data/lib/sisimai/lhost/mailfoundry.rb +11 -12
  46. data/lib/sisimai/lhost/mailmarshalsmtp.rb +25 -29
  47. data/lib/sisimai/lhost/mailru.rb +33 -27
  48. data/lib/sisimai/lhost/mcafee.rb +21 -31
  49. data/lib/sisimai/lhost/messagelabs.rb +17 -20
  50. data/lib/sisimai/lhost/messagingserver.rb +40 -37
  51. data/lib/sisimai/lhost/mfilter.rb +15 -16
  52. data/lib/sisimai/lhost/mxlogic.rb +24 -23
  53. data/lib/sisimai/lhost/notes.rb +17 -17
  54. data/lib/sisimai/lhost/office365.rb +63 -27
  55. data/lib/sisimai/lhost/opensmtpd.rb +12 -13
  56. data/lib/sisimai/lhost/outlook.rb +12 -15
  57. data/lib/sisimai/lhost/postfix.rb +179 -129
  58. data/lib/sisimai/lhost/powermta.rb +12 -14
  59. data/lib/sisimai/lhost/qmail.rb +44 -47
  60. data/lib/sisimai/lhost/receivingses.rb +15 -20
  61. data/lib/sisimai/lhost/sendgrid.rb +34 -32
  62. data/lib/sisimai/lhost/sendmail.rb +66 -53
  63. data/lib/sisimai/lhost/surfcontrol.rb +19 -19
  64. data/lib/sisimai/lhost/v5sendmail.rb +45 -39
  65. data/lib/sisimai/lhost/verizon.rb +35 -39
  66. data/lib/sisimai/lhost/x1.rb +18 -17
  67. data/lib/sisimai/lhost/x2.rb +17 -14
  68. data/lib/sisimai/lhost/x3.rb +19 -19
  69. data/lib/sisimai/lhost/x4.rb +72 -57
  70. data/lib/sisimai/lhost/x5.rb +17 -19
  71. data/lib/sisimai/lhost/x6.rb +41 -17
  72. data/lib/sisimai/lhost/yahoo.rb +17 -16
  73. data/lib/sisimai/lhost/yandex.rb +16 -20
  74. data/lib/sisimai/lhost/zoho.rb +16 -15
  75. data/lib/sisimai/lhost.rb +8 -10
  76. data/lib/sisimai/mail/maildir.rb +1 -3
  77. data/lib/sisimai/mail/mbox.rb +3 -4
  78. data/lib/sisimai/mail/memory.rb +0 -1
  79. data/lib/sisimai/mail/stdin.rb +1 -3
  80. data/lib/sisimai/mail.rb +3 -7
  81. data/lib/sisimai/mda.rb +28 -42
  82. data/lib/sisimai/message.rb +435 -326
  83. data/lib/sisimai/order.rb +5 -5
  84. data/lib/sisimai/reason/authfailure.rb +64 -0
  85. data/lib/sisimai/reason/badreputation.rb +53 -0
  86. data/lib/sisimai/reason/blocked.rb +94 -160
  87. data/lib/sisimai/reason/contenterror.rb +8 -9
  88. data/lib/sisimai/reason/delivered.rb +4 -6
  89. data/lib/sisimai/reason/exceedlimit.rb +10 -12
  90. data/lib/sisimai/reason/expired.rb +6 -8
  91. data/lib/sisimai/reason/feedback.rb +2 -3
  92. data/lib/sisimai/reason/filtered.rb +17 -19
  93. data/lib/sisimai/reason/hasmoved.rb +9 -10
  94. data/lib/sisimai/reason/hostunknown.rb +15 -15
  95. data/lib/sisimai/reason/mailboxfull.rb +10 -12
  96. data/lib/sisimai/reason/mailererror.rb +18 -20
  97. data/lib/sisimai/reason/mesgtoobig.rb +9 -11
  98. data/lib/sisimai/reason/networkerror.rb +5 -8
  99. data/lib/sisimai/reason/norelaying.rb +8 -11
  100. data/lib/sisimai/reason/notaccept.rb +13 -14
  101. data/lib/sisimai/reason/notcompliantrfc.rb +43 -0
  102. data/lib/sisimai/reason/onhold.rb +6 -9
  103. data/lib/sisimai/reason/policyviolation.rb +14 -12
  104. data/lib/sisimai/reason/rejected.rb +26 -24
  105. data/lib/sisimai/reason/requireptr.rb +69 -0
  106. data/lib/sisimai/reason/securityerror.rb +33 -36
  107. data/lib/sisimai/reason/spamdetected.rb +114 -147
  108. data/lib/sisimai/reason/speeding.rb +49 -0
  109. data/lib/sisimai/reason/suspend.rb +11 -11
  110. data/lib/sisimai/reason/syntaxerror.rb +11 -10
  111. data/lib/sisimai/reason/systemerror.rb +7 -9
  112. data/lib/sisimai/reason/systemfull.rb +7 -8
  113. data/lib/sisimai/reason/toomanyconn.rb +9 -11
  114. data/lib/sisimai/reason/undefined.rb +2 -3
  115. data/lib/sisimai/reason/userunknown.rb +129 -146
  116. data/lib/sisimai/reason/vacation.rb +3 -4
  117. data/lib/sisimai/reason/virusdetected.rb +10 -11
  118. data/lib/sisimai/reason.rb +59 -64
  119. data/lib/sisimai/rfc1894.rb +55 -28
  120. data/lib/sisimai/rfc2045.rb +373 -0
  121. data/lib/sisimai/rfc3464.rb +250 -308
  122. data/lib/sisimai/rfc3834.rb +42 -45
  123. data/lib/sisimai/rfc5322.rb +75 -100
  124. data/lib/sisimai/rfc5965.rb +31 -0
  125. data/lib/sisimai/rhost/cox.rb +5 -6
  126. data/lib/sisimai/rhost/franceptt.rb +6 -8
  127. data/lib/sisimai/rhost/godaddy.rb +12 -12
  128. data/lib/sisimai/rhost/{googleapps.rb → google.rb} +80 -72
  129. data/lib/sisimai/rhost/iua.rb +9 -10
  130. data/lib/sisimai/rhost/kddi.rb +6 -8
  131. data/lib/sisimai/rhost/{exchangeonline.rb → microsoft.rb} +115 -114
  132. data/lib/sisimai/rhost/mimecast.rb +42 -40
  133. data/lib/sisimai/rhost/nttdocomo.rb +12 -12
  134. data/lib/sisimai/rhost/spectrum.rb +10 -12
  135. data/lib/sisimai/rhost/{tencentqq.rb → tencent.rb} +7 -8
  136. data/lib/sisimai/rhost.rb +23 -31
  137. data/lib/sisimai/smtp/command.rb +59 -0
  138. data/lib/sisimai/smtp/error.rb +4 -7
  139. data/lib/sisimai/smtp/reply.rb +161 -74
  140. data/lib/sisimai/smtp/status.rb +504 -393
  141. data/lib/sisimai/smtp/transcript.rb +124 -0
  142. data/lib/sisimai/smtp.rb +0 -1
  143. data/lib/sisimai/string.rb +74 -5
  144. data/lib/sisimai/time.rb +1 -2
  145. data/lib/sisimai/version.rb +1 -1
  146. data/lib/sisimai.rb +35 -21
  147. data/set-of-emails/maildir/bsd/lhost-domino-02.eml +6 -3
  148. data/set-of-emails/maildir/bsd/lhost-googlegroups-15.eml +174 -0
  149. data/set-of-emails/maildir/bsd/lhost-gsuite-15.eml +229 -0
  150. data/set-of-emails/maildir/bsd/lhost-postfix-75.eml +51 -0
  151. data/set-of-emails/maildir/bsd/lhost-postfix-76.eml +101 -0
  152. data/set-of-emails/maildir/bsd/lhost-postfix-77.eml +74 -0
  153. data/set-of-emails/maildir/bsd/lhost-postfix-78.eml +91 -0
  154. data/set-of-emails/maildir/bsd/lhost-receivingses-08.eml +88 -0
  155. data/set-of-emails/maildir/bsd/rfc3464-43.eml +88 -0
  156. data/set-of-emails/maildir/bsd/rhost-google-03.eml +101 -0
  157. data/set-of-emails/maildir/bsd/rhost-google-04.eml +102 -0
  158. data/set-of-emails/maildir/bsd/rhost-google-05.eml +82 -0
  159. data/set-of-emails/maildir/bsd/rhost-google-06.eml +102 -0
  160. data/set-of-emails/maildir/bsd/rhost-google-07.eml +69 -0
  161. data/set-of-emails/maildir/bsd/rhost-google-08.eml +99 -0
  162. data/sisimai-java.gemspec +1 -1
  163. data/sisimai.gemspec +1 -1
  164. metadata +42 -22
  165. data/.rspec +0 -2
  166. data/lib/sisimai/data/yaml.rb +0 -33
  167. data/lib/sisimai/data.rb +0 -411
  168. data/lib/sisimai/mime.rb +0 -456
  169. /data/set-of-emails/maildir/bsd/{rfc3464-41.eml → rfc3834-05.eml} +0 -0
  170. /data/set-of-emails/maildir/bsd/{rhost-googleapps-01.eml → rhost-google-01.eml} +0 -0
  171. /data/set-of-emails/maildir/bsd/{rhost-googleapps-02.eml → rhost-google-02.eml} +0 -0
  172. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-01.eml → rhost-microsoft-01.eml} +0 -0
  173. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-02.eml → rhost-microsoft-02.eml} +0 -0
  174. /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-03.eml → rhost-microsoft-03.eml} +0 -0
  175. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-01.eml → rhost-tencent-01.eml} +0 -0
  176. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-02.eml → rhost-tencent-02.eml} +0 -0
  177. /data/set-of-emails/maildir/bsd/{rhost-tencentqq-03.eml → rhost-tencent-03.eml} +0 -0
@@ -1,14 +1,12 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::Exchange2003 parses a bounce email which created by
3
- # Microsoft Exchange Server 2003.
2
+ # Sisimai::Lhost::Exchange2003 parses a bounce email which created by Microsoft Exchange Server 2003.
4
3
  # Methods in the module are called from only Sisimai::Message.
5
4
  module Exchange2003
6
5
  class << self
7
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/Exchange2003.pm
8
6
  require 'sisimai/lhost'
9
7
 
10
8
  Indicators = Sisimai::Lhost.INDICATORS
11
- ReBackbone = %r|^Content-Type:[ ]message/rfc822|.freeze
9
+ Boundaries = ['Content-Type: message/rfc822'].freeze
12
10
  StartingOf = {
13
11
  message: ['Your message'],
14
12
  error: ['did not reach the following recipient(s):'],
@@ -46,7 +44,7 @@ module Sisimai::Lhost
46
44
  # @param [String] mbody Message body of a bounce email
47
45
  # @return [Hash] Bounce data list and message/rfc822 part
48
46
  # @return [Nil] it failed to parse or the arguments are missing
49
- def make(mhead, mbody)
47
+ def inquire(mhead, mbody)
50
48
  match = 0
51
49
  tryto = []
52
50
 
@@ -85,8 +83,8 @@ module Sisimai::Lhost
85
83
  return nil unless match > 0
86
84
 
87
85
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
88
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
89
- bodyslices = emailsteak[0].split("\n")
86
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
87
+ bodyslices = emailparts[0].split("\n")
90
88
  readcursor = 0 # (Integer) Points the current cursor position
91
89
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
92
90
  statuspart = false # (Boolean) Flag, true = have got delivery status part.
@@ -99,8 +97,8 @@ module Sisimai::Lhost
99
97
  v = nil
100
98
 
101
99
  while e = bodyslices.shift do
102
- # Read error messages and delivery status lines from the head of the email
103
- # to the previous line of the beginning of the original message.
100
+ # Read error messages and delivery status lines from the head of the email to the previous
101
+ # line of the beginning of the original message.
104
102
  if readcursor == 0
105
103
  # Beginning of the bounce message or delivery status part
106
104
  readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
@@ -124,8 +122,7 @@ module Sisimai::Lhost
124
122
  # MSEXCH:IMS:KIJITORA CAT:EXAMPLE:EXCHANGE 0 (000C05A6) Unknown Recipient
125
123
  v = dscontents[-1]
126
124
 
127
- if cv = e.match(/\A[ \t]*([^ ]+[@][^ ]+) on[ \t]*.*\z/) ||
128
- e.match(/\A[ \t]*.+(?:SMTP|smtp)=([^ ]+[@][^ ]+) on[ \t]*.*\z/)
125
+ if Sisimai::String.aligned(e, ['@', ' on '])
129
126
  # kijitora@example.co.jp on Thu, 29 Apr 2007 16:51:51 -0500
130
127
  # kijitora@example.com on 4/29/99 9:19:59 AM
131
128
  if v['recipient']
@@ -133,14 +130,16 @@ module Sisimai::Lhost
133
130
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
134
131
  v = dscontents[-1]
135
132
  end
136
- v['recipient'] = cv[1]
133
+ p1 = e.downcase.index('smtp='); p1 = p1.nil? ? 0 : p1 + 5
134
+ p2 = e.index(' on ') + 1
135
+ v['recipient'] = Sisimai::Address.s3s4(e[p1, p2])
137
136
  v['msexch'] = false
138
137
  recipients += 1
139
138
 
140
- elsif cv = e.match(/\A[ \t]+(MSEXCH:.+)\z/)
139
+ elsif e.start_with?(' ') && e.include?('MSEXCH:')
141
140
  # MSEXCH:IMS:KIJITORA CAT:EXAMPLE:EXCHANGE 0 (000C05A6) Unknown Recipient
142
141
  v['diagnosis'] ||= ''
143
- v['diagnosis'] << cv[1]
142
+ v['diagnosis'] << e[e.index('MSEXCH:'), e.size]
144
143
  else
145
144
  next if v['msexch']
146
145
  if v['diagnosis'].to_s.start_with?('MSEXCH:')
@@ -161,24 +160,23 @@ module Sisimai::Lhost
161
160
  # Subject: ...
162
161
  # Sent: Thu, 29 Apr 2010 18:14:35 +0000
163
162
  #
164
- if cv = e.match(/\A[ \t]+To:[ \t]+(.+)\z/)
163
+ if e.start_with?(' To: ') || e.start_with?(' To: ')
165
164
  # To: shironeko@example.jp
166
165
  next unless connheader['to'].empty?
167
- connheader['to'] = cv[1]
166
+ connheader['to'] = e[e.rindex(' ') + 1, e.size]
168
167
  connvalues += 1
169
168
 
170
- elsif cv = e.match(/\A[ \t]+Subject:[ \t]+(.+)\z/)
169
+ elsif e.start_with?(' Subject: ') || e.start_with?(' Subject: ')
171
170
  # Subject: ...
172
171
  next unless connheader['subject'].empty?
173
- connheader['subject'] = cv[1]
172
+ connheader['subject'] = e[e.rindex(' ') + 1, e.size]
174
173
  connvalues += 1
175
174
 
176
- elsif cv = e.match(%r|\A[ \t]+Sent:[ \t]+([A-Z][a-z]{2},.+[-+]\d{4})\z|) ||
177
- e.match(%r|\A[ \t]+Sent:[ \t]+(\d+[/]\d+[/]\d+[ \t]+\d+:\d+:\d+[ \t].+)|)
175
+ elsif e.start_with?(' Sent: ') || e.start_with?(' Sent: ')
178
176
  # Sent: Thu, 29 Apr 2010 18:14:35 +0000
179
177
  # Sent: 4/29/99 9:19:59 AM
180
178
  next unless connheader['date'].empty?
181
- connheader['date'] = cv[1]
179
+ connheader['date'] = e[e.index(':') + 2, e.size]
182
180
  connvalues += 1
183
181
  end
184
182
  end
@@ -187,10 +185,13 @@ module Sisimai::Lhost
187
185
 
188
186
  dscontents.each do |e|
189
187
  e.delete('msexch')
190
- if cv = e['diagnosis'].match(/\AMSEXCH:.+[ \t]*[(]([0-9A-F]{8})[)][ \t]*(.*)\z/)
188
+ e['diagnosis'] ||= ''
189
+ if e['diagnosis'].start_with?('MSEXCH:')
191
190
  # MSEXCH:IMS:KIJITORA CAT:EXAMPLE:EXCHANGE 0 (000C05A6) Unknown Recipient
192
- capturedcode = cv[1]
193
- errormessage = cv[2]
191
+ p1 = e['diagnosis'].index('(') || -1
192
+ p2 = e['diagnosis'].index(')') || -1
193
+ capturedcode = e['diagnosis'][p1 + 1, 8]
194
+ errormessage = e['diagnosis'][p2 + 1, e['diagnosis'].size]
194
195
 
195
196
  ErrorCodes.each_key do |r|
196
197
  # Find captured code from the error code table
@@ -214,14 +215,14 @@ module Sisimai::Lhost
214
215
  end
215
216
  end
216
217
 
217
- if emailsteak[1].empty?
218
+ if emailparts[1].empty?
218
219
  # When original message does not included in the bounce message
219
- emailsteak[1] << ('From: ' << connheader['to'] << "\n")
220
- emailsteak[1] << ('Date: ' << connheader['date'] << "\n")
221
- emailsteak[1] << ('Subject: ' << connheader['subject'] << "\n")
220
+ emailparts[1] << ('From: ' << connheader['to'] << "\n")
221
+ emailparts[1] << ('Date: ' << connheader['date'] << "\n")
222
+ emailparts[1] << ('Subject: ' << connheader['subject'] << "\n")
222
223
  end
223
224
 
224
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
225
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
225
226
  end
226
227
  def description; return 'Microsoft Exchange Server 2003'; end
227
228
  end
@@ -1,34 +1,28 @@
1
1
  module Sisimai::Lhost
2
- # Sisimai::Lhost::Exchange2007 parses a bounce email which created by
3
- # Microsoft Exchange Server 2007.
2
+ # Sisimai::Lhost::Exchange2007 parses a bounce email which created by Microsoft Exchange Server 2007.
4
3
  # Methods in the module are called from only Sisimai::Message.
5
4
  module Exchange2007
6
5
  class << self
7
- # Imported from p5-Sisimail/lib/Sisimai/Lhost/Exchange2007.pm
8
6
  require 'sisimai/lhost'
9
7
 
10
8
  Indicators = Sisimai::Lhost.INDICATORS
11
- ReBackbone = %r{^(?:
12
- Original[ ]message[ ]headers: # en-US
13
- |En-t.tes[ ]de[ ]message[ ]d'origine[ ]: # fr-FR/En-têtes de message d'origine
14
- |Intestazioni[ ]originali[ ]del[ ]messaggio: # it-CH
15
- )
16
- }x.freeze
9
+ Boundaries = [
10
+ 'Original message headers:', # en-US
11
+ "tes de message d'origine :", # fr-FR/En-têtes de message d'origine
12
+ 'Intestazioni originali del messaggio:', # it-CH
13
+ ].freeze
17
14
  MarkingsOf = {
18
- message: %r{\A(?:
19
- Diagnostic[ ]information[ ]for[ ]administrators: # en-US
20
- |Informations[ ]de[ ]diagnostic[ ]pour[ ]les[ ]administrateurs # fr-FR
21
- |Informazioni[ ]di[ ]diagnostica[ ]per[ ]gli[ ]amministratori # it-CH
22
- )
23
- }x,
24
- error: %r/ ((?:RESOLVER|QUEUE)[.][A-Za-z]+(?:[.]\w+)?);/,
25
- rhost: %r{\A(?:
26
- Generating[ ]server # en-US
27
- |Serveur[ ]de[ ]g[^ ]+ration[ ] # fr-FR/Serveur de génération
28
- |Server[ ]di[ ]generazione # it-CH
29
- ):[ ]?(.*)
30
- }x,
31
- subject: %r/\A(?:Undeliverable|Non_remis_|Non[ ]recapitabile):/,
15
+ message: [
16
+ 'Diagnostic information for administrators:', # en-US
17
+ 'Informations de diagnostic pour les administrateurs', # fr-FR
18
+ 'Informazioni di diagnostica per gli amministratori', # it-CH
19
+ ],
20
+ error: [' RESOLVER.', ' QUEUE.'],
21
+ rhost: [
22
+ 'Generating server', # en-US
23
+ 'Serveur de g', # fr-FR/Serveur de g�Hn�Hration
24
+ 'Server di generazione', # it-CH
25
+ ]
32
26
  }.freeze
33
27
  NDRSubject = {
34
28
  'SMTPSEND.DNS.NonExistentDomain' => 'hostunknown', # 554 5.4.4 SMTPSEND.DNS.NonExistentDomain
@@ -50,19 +44,26 @@ module Sisimai::Lhost
50
44
  # @param [String] mbody Message body of a bounce email
51
45
  # @return [Hash] Bounce data list and message/rfc822 part
52
46
  # @return [Nil] it failed to parse or the arguments are missing
53
- def make(mhead, mbody)
47
+ def inquire(mhead, mbody)
54
48
  # Content-Language: en-US, fr-FR
55
- return nil unless mhead['subject'] =~ MarkingsOf[:subject]
49
+ match = nil
50
+ match ||= 1 if mhead['subject'].start_with?('Undeliverable')
51
+ match ||= 1 if mhead['subject'].start_with?('Non_remis_')
52
+ match ||= 1 if mhead['subject'].start_with?('Non recapitabile')
53
+ return nil unless match
56
54
  return nil unless mhead['content-language']
57
- return nil unless mhead['content-language'] =~ /\A[a-z]{2}(?:[-][A-Z]{2})?\z/
55
+
56
+ match += 1 if mhead['content-language'].size == 2 # JP
57
+ match += 1 if mhead['content-language'].size == 5 # ja-JP
58
+ return nil unless match > 1
58
59
 
59
60
  # These headers exist only a bounce mail from Office365
60
61
  return nil if mhead['x-ms-exchange-crosstenant-originalarrivaltime']
61
62
  return nil if mhead['x-ms-exchange-crosstenant-fromentityheader']
62
63
 
63
64
  dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
64
- emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
65
- bodyslices = emailsteak[0].split("\n")
65
+ emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
66
+ bodyslices = emailparts[0].split("\n")
66
67
  readcursor = 0 # (Integer) Points the current cursor position
67
68
  recipients = 0 # (Integer) The number of 'Final-Recipient' header
68
69
  connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
@@ -72,11 +73,11 @@ module Sisimai::Lhost
72
73
  v = nil
73
74
 
74
75
  while e = bodyslices.shift do
75
- # Read error messages and delivery status lines from the head of the email
76
- # to the previous line of the beginning of the original message.
76
+ # Read error messages and delivery status lines from the head of the email to the previous
77
+ # line of the beginning of the original message.
77
78
  if readcursor == 0
78
79
  # Beginning of the bounce message or delivery status part
79
- readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
80
+ readcursor |= Indicators[:deliverystatus] if MarkingsOf[:message].any? { |a| e.start_with?(a) }
80
81
  next
81
82
  end
82
83
  next if (readcursor & Indicators[:deliverystatus]) == 0
@@ -92,59 +93,70 @@ module Sisimai::Lhost
92
93
  # Original message headers:
93
94
  v = dscontents[-1]
94
95
 
95
- if cv = e.match(/\A([^ @]+[@][^ @]+)\z/)
96
+ if e.include?('@') && e.include?(' ') == false
96
97
  # kijitora@example.jp
97
98
  if v['recipient']
98
99
  # There are multiple recipient addresses in the message body.
99
100
  dscontents << Sisimai::Lhost.DELIVERYSTATUS
100
101
  v = dscontents[-1]
101
102
  end
102
- v['recipient'] = cv[1]
103
+ v['recipient'] = Sisimai::Address.s3s4(e)
103
104
  v['diagnosis'] = ''
104
105
  recipients += 1
105
106
 
106
- elsif cv = e.match(/([45]\d{2})[ ]([45][.]\d[.]\d+)[ ].+\z/)
107
- # #550 5.1.1 RESOLVER.ADR.RecipNotFound; not found ##
108
- # #550 5.2.3 RESOLVER.RST.RecipSizeLimit; message too large for this recipient ##
109
- # Remote Server returned '550 5.1.1 RESOLVER.ADR.RecipNotFound; not found'
110
- # 3/09/2016 8:05:56 PM - Remote Server at mydomain.com (10.1.1.3) returned '550 4.4.7 QUEUE.Expired; message expired'
111
- v['replycode'] = cv[1]
112
- v['status'] = cv[2]
113
- v['diagnosis'] = e
114
107
  else
115
108
  # Continued line of error messages
116
- next if v['diagnosis'].to_s.empty?
117
- next unless v['diagnosis'].end_with?('=')
118
- v['diagnosis'] = v['diagnosis'].chomp('=')
119
- v['diagnosis'] << e
109
+ cr = Sisimai::SMTP::Reply.find(e)
110
+ cs = Sisimai::SMTP::Status.find(e)
111
+ if cr || cs
112
+ # #550 5.1.1 RESOLVER.ADR.RecipNotFound; not found ##
113
+ # #550 5.2.3 RESOLVER.RST.RecipSizeLimit; message too large for this recipient ##
114
+ # Remote Server returned '550 5.1.1 RESOLVER.ADR.RecipNotFound; not found'
115
+ # 3/09/2016 8:05:56 PM - Remote Server at mydomain.com (10.1.1.3) returned '550 4.4.7 QUEUE.Expired; message expired'
116
+ v['replycode'] = cr || ''
117
+ v['status'] = cs || ''
118
+ v['diagnosis'] = e
119
+ else
120
+ # Continued line of error messages
121
+ next if v['diagnosis'].to_s.empty?
122
+ next unless v['diagnosis'].end_with?('=')
123
+ v['diagnosis'] = v['diagnosis'].chomp('=')
124
+ v['diagnosis'] << e
125
+ end
120
126
  end
121
127
  else
122
128
  # Diagnostic information for administrators:
123
129
  #
124
130
  # Generating server: mta22.neko.example.org
125
- next unless cv = e.match(MarkingsOf[:rhost])
131
+ next unless MarkingsOf[:rhost].any? { |a| e.start_with?(a) }
126
132
  next unless connheader['rhost'].empty?
127
- connheader['rhost'] = cv[1]
133
+ connheader['rhost'] = e[e.index(':') + 1, e.size]
128
134
  connvalues += 1
129
135
  end
130
136
  end
131
137
  return nil unless recipients > 0
132
138
 
133
139
  dscontents.each do |e|
134
- if cv = e['diagnosis'].match(MarkingsOf[:error])
135
- # #550 5.1.1 RESOLVER.ADR.RecipNotFound; not found ##
136
- f = cv[1]
137
- NDRSubject.each_key do |r|
138
- # Try to match with error subject strings
139
- next unless f == r
140
- e['reason'] = NDRSubject[r]
141
- break
142
- end
143
- end
140
+ p = -1
144
141
  e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
142
+ MarkingsOf[:error].each do |q|
143
+ # Find an error message, get an error code.
144
+ p = e['diagnosis'].index(q) || -1
145
+ break if p > -1
146
+ end
147
+ next unless p > 0
148
+
149
+ # #550 5.1.1 RESOLVER.ADR.RecipNotFound; not found ##
150
+ f = e['diagnosis'][p + 1, e['diagnosis'].index(';') - p -1]
151
+ NDRSubject.each_key do |r|
152
+ # Try to match with error subject strings
153
+ next unless f == r
154
+ e['reason'] = NDRSubject[r]
155
+ break
156
+ end
145
157
  end
146
158
 
147
- return { 'ds' => dscontents, 'rfc822' => emailsteak[1] }
159
+ return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
148
160
  end
149
161
  def description; return 'Microsoft Exchange Server 2007'; end
150
162
  end