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
@@ -21,12 +21,12 @@ module Sisimai::Bite::Email
21
21
  }.freeze
22
22
 
23
23
  MessagesOf = {
24
- expired: [
24
+ 'expired' => [
25
25
  'DNS Error: Could not contact DNS servers',
26
26
  'Delivery to the following recipient has been delayed',
27
27
  'The recipient server did not accept our requests to connect',
28
28
  ],
29
- hostunknown: [
29
+ 'hostunknown' => [
30
30
  'DNS Error: Domain name not found',
31
31
  'DNS Error: DNS server returned answer with no data',
32
32
  ],
@@ -107,7 +107,7 @@ module Sisimai::Bite::Email
107
107
 
108
108
  def description; return 'Google Gmail: https://mail.google.com'; end
109
109
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
110
- def headerlist; return ['X-Failed-Recipients']; end
110
+ def headerlist; return %w[x-failed-recipients]; end
111
111
 
112
112
  # Parse bounce messages from Google Gmail
113
113
  # @param [Hash] mhead Message headers of a bounce email
@@ -195,7 +195,7 @@ module Sisimai::Bite::Email
195
195
  end
196
196
 
197
197
  if readcursor & Indicators[:'message-rfc822'] > 0
198
- # After "message/rfc822"
198
+ # Inside of the original message part
199
199
  if e.empty?
200
200
  blanklines += 1
201
201
  break if blanklines > 1
@@ -203,7 +203,7 @@ module Sisimai::Bite::Email
203
203
  end
204
204
  rfc822list << e
205
205
  else
206
- # Before "message/rfc822"
206
+ # Error message part
207
207
  next if (readcursor & Indicators[:deliverystatus]) == 0
208
208
  next if e.empty?
209
209
 
@@ -232,11 +232,10 @@ module Sisimai::Bite::Email
232
232
  v = dscontents[-1]
233
233
  end
234
234
 
235
- addr0 = Sisimai::Address.s3s4(cv[1])
236
- if Sisimai::RFC5322.is_emailaddress(addr0)
237
- v['recipient'] = addr0
238
- recipients += 1
239
- end
235
+ r = Sisimai::Address.s3s4(cv[1])
236
+ next unless Sisimai::RFC5322.is_emailaddress(r)
237
+ v['recipient'] = r
238
+ recipients += 1
240
239
  else
241
240
  v['diagnosis'] ||= ''
242
241
  v['diagnosis'] << e + ' '
@@ -276,15 +275,15 @@ module Sisimai::Bite::Email
276
275
  MessagesOf.each_key do |r|
277
276
  # Verify each regular expression of session errors
278
277
  next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
279
- e['reason'] = r.to_s
278
+ e['reason'] = r
280
279
  break
281
280
  end
282
281
  end
283
282
  next unless e['reason']
284
283
 
285
284
  # Set pseudo status code
286
- e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
287
- e['reason'] = Sisimai::SMTP::Status.name(e['status']) if e['status'] =~ /\A[45][.][1-7][.][1-9]\z/
285
+ e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
286
+ e['reason'] = Sisimai::SMTP::Status.name(e['status']).to_s if e['status'] =~ /\A[45][.][1-7][.][1-9]\z/
288
287
  end
289
288
 
290
289
  rfc822part = Sisimai::RFC5322.weedout(rfc822list)
@@ -14,14 +14,14 @@ module Sisimai::Bite::Email
14
14
  html: %r{\AContent-Type:[ ]*text/html;[ ]*charset=['"]?(?:UTF|utf)[-]8['"]?\z},
15
15
  }.freeze
16
16
  MessagesOf = {
17
- userunknown: ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
18
- notaccept: ['Null MX'],
19
- networkerror: [' responded with code NXDOMAIN'],
17
+ 'userunknown' => ["because the address couldn't be found. Check for typos or unnecessary spaces and try again."],
18
+ 'notaccept' => ['Null MX'],
19
+ 'networkerror' => [' responded with code NXDOMAIN'],
20
20
  }.freeze
21
21
 
22
22
  def description; return 'G Suite: https://gsuite.google.com'; end
23
23
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
24
- def headerlist; return ['X-Gm-Message-State']; end
24
+ def headerlist; return %w[x-gm-message-state]; end
25
25
 
26
26
  # Parse bounce messages from G Suite (Transfer from G Suite to a destinaion host)
27
27
  # @param [Hash] mhead Message headers of a bounce email
@@ -39,6 +39,10 @@ module Sisimai::Bite::Email
39
39
  return nil unless mhead['subject'].start_with?('Delivery Status Notification')
40
40
  return nil unless mhead['x-gm-message-state']
41
41
 
42
+ require 'sisimai/rfc1894'
43
+ fieldtable = Sisimai::RFC1894.FIELDTABLE
44
+ permessage = {} # (Hash) Store values of each Per-Message field
45
+
42
46
  dscontents = [Sisimai::Bite.DELIVERYSTATUS]
43
47
  hasdivided = mbody.split("\n")
44
48
  rfc822list = [] # (Array) Each line in message/rfc822 part string
@@ -48,21 +52,16 @@ module Sisimai::Bite::Email
48
52
  endoferror = false # (Integer) Flag for a blank line after error messages
49
53
  anotherset = {} # (Hash) Another error information
50
54
  emptylines = 0 # (Integer) The number of empty lines
51
- connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
52
- connheader = {
53
- 'date' => '', # The value of Arrival-Date header
54
- 'lhost' => '', # The value of Reporting-MTA header
55
- }
56
55
  v = nil
57
56
 
58
57
  while e = hasdivided.shift do
59
58
  if readcursor == 0
60
- # Beginning of the bounce message or delivery status part
59
+ # Beginning of the bounce message or message/delivery-status part
61
60
  readcursor |= Indicators[:deliverystatus] if e =~ MarkingsOf[:message]
62
61
  end
63
62
 
64
63
  if (readcursor & Indicators[:'message-rfc822']) == 0
65
- # Beginning of the original message part
64
+ # Beginning of the original message part(message/rfc822)
66
65
  if e =~ MarkingsOf[:rfc822]
67
66
  readcursor |= Indicators[:'message-rfc822']
68
67
  next
@@ -70,7 +69,7 @@ module Sisimai::Bite::Email
70
69
  end
71
70
 
72
71
  if readcursor & Indicators[:'message-rfc822'] > 0
73
- # After "message/rfc822"
72
+ # message/rfc822 OR text/rfc822-headers part
74
73
  if e.empty?
75
74
  blanklines += 1
76
75
  break if blanklines > 1
@@ -78,123 +77,96 @@ module Sisimai::Bite::Email
78
77
  end
79
78
  rfc822list << e
80
79
  else
81
- # Before "message/rfc822"
80
+ # message/delivery-status part
82
81
  next if (readcursor & Indicators[:deliverystatus]) == 0
83
82
 
84
- if connvalues == connheader.keys.size
85
- # Final-Recipient: rfc822; kijitora@example.de
86
- # Action: failed
87
- # Status: 5.0.0
88
- # Remote-MTA: dns; 192.0.2.222 (192.0.2.222, the server for the domain.)
89
- # Diagnostic-Code: smtp; 550 #5.1.0 Address rejected.
90
- # Last-Attempt-Date: Fri, 24 Mar 2017 23:34:10 -0700 (PDT)
83
+ if f = Sisimai::RFC1894.match(e)
84
+ # "e" matched with any field defined in RFC3464
85
+ next unless o = Sisimai::RFC1894.field(e)
91
86
  v = dscontents[-1]
92
87
 
93
- if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*(.+)\z/)
94
- # Final-Recipient: rfc822; kijitora@example.de
95
- if v['recipient']
96
- # There are multiple recipient addresses in the message body.
97
- dscontents << Sisimai::Bite.DELIVERYSTATUS
98
- v = dscontents[-1]
88
+ if o[-1] == 'addr'
89
+ # Final-Recipient: rfc822; kijitora@example.jp
90
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
91
+ if o[0] == 'final-recipient'
92
+ # Final-Recipient: rfc822; kijitora@example.jp
93
+ if v['recipient']
94
+ # There are multiple recipient addresses in the message body.
95
+ dscontents << Sisimai::Bite.DELIVERYSTATUS
96
+ v = dscontents[-1]
97
+ end
98
+ v['recipient'] = o[2]
99
+ recipients += 1
100
+ else
101
+ # X-Actual-Recipient: rfc822; kijitora@example.co.jp
102
+ v['alias'] = o[2]
99
103
  end
100
- v['recipient'] = cv[1]
101
- recipients += 1
102
-
103
- elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
104
- # Action: failed
105
- v['action'] = cv[1].downcase
106
-
107
- elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
108
- # Status: 5.0.0
109
- v['status'] = cv[1]
110
-
111
- elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
112
- # Remote-MTA: dns; 192.0.2.222 (192.0.2.222, the server for the domain.)
113
- v['rhost'] = cv[1].downcase
114
- v['rhost'] = '' if v['rhost'] =~ /\A\s+\z/ # Remote-MTA: DNS;
115
-
116
- elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
117
- # Last-Attempt-Date: Fri, 24 Mar 2017 23:34:10 -0700 (PDT)
118
- v['date'] = cv[1]
104
+ elsif o[-1] == 'code'
105
+ # Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
106
+ v['spec'] = o[1]
107
+ v['diagnosis'] = o[2]
119
108
  else
120
- if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
121
- # Diagnostic-Code: smtp; 550 #5.1.0 Address rejected.
122
- v['spec'] = cv[1].upcase
123
- v['diagnosis'] = cv[2]
124
- else
125
- # Append error messages continued from the previous line
126
- if endoferror == false && !v['diagnosis'].to_s.empty?
127
- endoferror ||= true if e.empty?
128
- endoferror ||= true if e.start_with?('--')
109
+ # Other DSN fields defined in RFC3464
110
+ next unless fieldtable.key?(o[0])
111
+ v[fieldtable[o[0]]] = o[2]
129
112
 
130
- next if endoferror
131
- next unless e.start_with?(' ')
132
- v['diagnosis'] << e
133
- end
134
- end
113
+ next unless f == 1
114
+ permessage[fieldtable[o[0]]] = o[2]
135
115
  end
136
116
  else
137
- # Reporting-MTA: dns; googlemail.com
138
- # Received-From-MTA: dns; sironeko@example.jp
139
- # Arrival-Date: Fri, 24 Mar 2017 23:34:07 -0700 (PDT)
140
- # X-Original-Message-ID: <06C1ED5C-7E02-4036-AEE1-AA448067FB2C@example.jp>
141
- if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
142
- # Reporting-MTA: dns; mx.example.jp
143
- next unless connheader['lhost'].empty?
144
- connheader['lhost'] = cv[1].downcase
145
- connvalues += 1
117
+ # The line does not begin with a DSN field defined in RFC3464
118
+ # Append error messages continued from the previous line
119
+ if endoferror == false && v && ! v['diagnosis'].to_s.empty?
120
+ endoferror ||= true if e.empty?
146
121
 
147
- elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
148
- # Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
149
- next unless connheader['date'].empty?
150
- connheader['date'] = cv[1]
151
- connvalues += 1
152
- else
122
+ next if endoferror
123
+ next unless e.start_with?(' ')
124
+ v['diagnosis'] << e
125
+
126
+ elsif e =~ MarkingsOf[:error]
153
127
  # Detect SMTP session error or connection error
154
- if e =~ MarkingsOf[:error]
155
- # The response from the remote server was:
156
- anotherset['diagnosis'] << e
128
+ # The response from the remote server was:
129
+ anotherset['diagnosis'] << e
130
+ else
131
+ # ** Address not found **
132
+ #
133
+ # Your message wasn't delivered to * because the address couldn't be found.
134
+ # Check for typos or unnecessary spaces and try again.
135
+ #
136
+ # The response from the remote server was:
137
+ # 550 #5.1.0 Address rejected.
138
+ next if e =~ MarkingsOf[:html]
139
+
140
+ if anotherset['diagnosis']
141
+ # Continued error messages from the previous line like
142
+ # "550 #5.1.0 Address rejected."
143
+ next if e =~ /\AContent-Type:/
144
+ next if emptylines > 5
145
+ if e.empty?
146
+ # Count and next()
147
+ emptylines += 1
148
+ next
149
+ end
150
+ anotherset['diagnosis'] << ' ' << e
157
151
  else
158
152
  # ** Address not found **
159
153
  #
160
154
  # Your message wasn't delivered to * because the address couldn't be found.
161
155
  # Check for typos or unnecessary spaces and try again.
162
- #
163
- # The response from the remote server was:
164
- # 550 #5.1.0 Address rejected.
165
- next if e =~ MarkingsOf[:html]
166
-
167
- if anotherset['diagnosis']
168
- # Continued error messages from the previous line like
169
- # "550 #5.1.0 Address rejected."
170
- next if e =~ /\AContent-Type:/
171
- next if emptylines > 5
172
- if e.empty?
173
- # Count and next()
174
- emptylines += 1
175
- next
176
- end
177
- anotherset['diagnosis'] << ' ' << e
178
- else
179
- # ** Address not found **
180
- #
181
- # Your message wasn't delivered to * because the address couldn't be found.
182
- # Check for typos or unnecessary spaces and try again.
183
- next if e.empty?
184
- next unless e =~ MarkingsOf[:message]
185
- anotherset['diagnosis'] = e
186
- end
156
+ next if e.empty?
157
+ next unless e =~ MarkingsOf[:message]
158
+ anotherset['diagnosis'] = e
187
159
  end
188
-
189
160
  end
190
161
  end
191
- end
162
+ end # End of message/delivery-status
192
163
  end
193
164
  return nil unless recipients > 0
194
165
 
195
166
  dscontents.each do |e|
196
167
  # Set default values if each value is empty.
197
- connheader.each_key { |a| e[a] ||= connheader[a] || '' }
168
+ e['lhost'] ||= permessage['rhost']
169
+ permessage.each_key { |a| e[a] ||= permessage[a] || '' }
198
170
 
199
171
  if anotherset['diagnosis']
200
172
  # Copy alternative error message
@@ -213,7 +185,7 @@ module Sisimai::Bite::Email
213
185
  if e['status'] == '' || e['status'].start_with?('4.0.0', '5.0.0')
214
186
  # Check the value of D.S.N. in anotherset
215
187
  as = Sisimai::SMTP::Status.find(anotherset['diagnosis'])
216
- if !as.empty? && as[-3, 3] != '0.0'
188
+ if as && as[-3, 3] != '0.0'
217
189
  # The D.S.N. is neither an empty nor *.0.0
218
190
  e['status'] = as
219
191
  end
@@ -222,7 +194,7 @@ module Sisimai::Bite::Email
222
194
  if e['replycode'].empty? || e['replycode'].start_with?('400', '500')
223
195
  # Check the value of SMTP reply code in anotherset
224
196
  ar = Sisimai::SMTP::Reply.find(anotherset['diagnosis'])
225
- if !ar.empty? && ar[-2, 2].to_i != 0
197
+ if ar && ar[-2, 2].to_i != 0
226
198
  # The SMTP reply code is neither an empty nor *00
227
199
  e['replycode'] = ar
228
200
  end
@@ -241,7 +213,7 @@ module Sisimai::Bite::Email
241
213
  MessagesOf.each_key do |r|
242
214
  # Guess an reason of the bounce
243
215
  next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
244
- e['reason'] = r.to_s
216
+ e['reason'] = r
245
217
  break
246
218
  end
247
219
  end
@@ -15,24 +15,24 @@ module Sisimai::Bite::Email
15
15
  }.freeze
16
16
 
17
17
  ReSMTP = {
18
- conn: %r/(?:SMTP connection failed,|Unexpected connection response from server:)/,
19
- ehlo: %r|Unexpected response to EHLO/HELO:|,
20
- mail: %r|Server response to MAIL FROM:|,
21
- rcpt: %r|Additional RCPT TO generated following response:|,
22
- data: %r|DATA command generated response:|,
18
+ 'conn' => %r/(?:SMTP connection failed,|Unexpected connection response from server:)/,
19
+ 'ehlo' => %r|Unexpected response to EHLO/HELO:|,
20
+ 'mail' => %r|Server response to MAIL FROM:|,
21
+ 'rcpt' => %r|Additional RCPT TO generated following response:|,
22
+ 'data' => %r|DATA command generated response:|,
23
23
  }.freeze
24
24
  ReFailures = {
25
- hostunknown: %r/Unknown host/,
26
- userunknown: %r/\A(?:Unknown user|Invalid final delivery userid)/,
27
- mailboxfull: %r/\AUser mailbox exceeds allowed size/,
28
- securityerr: %r/\ARequested action not taken: virus detected/,
29
- undefined: %r/\Aundeliverable to /,
30
- expired: %r/\ADelivery failed \d+ attempts/,
25
+ 'hostunknown' => %r/Unknown host/,
26
+ 'userunknown' => %r/\A(?:Unknown user|Invalid final delivery userid)/,
27
+ 'mailboxfull' => %r/\AUser mailbox exceeds allowed size/,
28
+ 'securityerr' => %r/\ARequested action not taken: virus detected/,
29
+ 'undefined' => %r/\Aundeliverable to /,
30
+ 'expired' => %r/\ADelivery failed \d+ attempts/,
31
31
  }.freeze
32
32
 
33
33
  def description; return 'IPSWITCH IMail Server'; end
34
34
  def smtpagent; return Sisimai::Bite.smtpagent(self); end
35
- def headerlist; return ['X-Mailer']; end
35
+ def headerlist; return %w[x-mailer]; end
36
36
 
37
37
  # Parse bounce messages from IMailServer
38
38
  # @param [Hash] mhead Message headers of a bounce email
@@ -77,7 +77,7 @@ module Sisimai::Bite::Email
77
77
  end
78
78
 
79
79
  if readcursor & Indicators[:'message-rfc822'] > 0
80
- # After "message/rfc822"
80
+ # Inside of the original message part
81
81
  if e.empty?
82
82
  blanklines += 1
83
83
  break if blanklines > 1
@@ -85,7 +85,7 @@ module Sisimai::Bite::Email
85
85
  end
86
86
  rfc822list << e
87
87
  else
88
- # Before "message/rfc822"
88
+ # Error message part
89
89
  break if readcursor & Indicators[:'message-rfc822'] > 0
90
90
 
91
91
  # Unknown user: kijitora@example.com
@@ -140,14 +140,14 @@ module Sisimai::Bite::Email
140
140
  ReSMTP.each_key do |r|
141
141
  # Detect SMTP command from the message
142
142
  next unless e['diagnosis'] =~ ReSMTP[r]
143
- e['command'] = r.to_s.upcase
143
+ e['command'] = r.upcase
144
144
  break
145
145
  end
146
146
 
147
147
  ReFailures.each_key do |r|
148
148
  # Verify each regular expression of session errors
149
149
  next unless e['diagnosis'] =~ ReFailures[r]
150
- e['reason'] = r.to_s
150
+ e['reason'] = r
151
151
  break
152
152
  end
153
153
  e.each_key { |a| e[a] ||= '' }
@@ -33,10 +33,8 @@ module Sisimai::Bite::Email
33
33
  match = 0
34
34
  tryto = [
35
35
  'Mail could not be delivered',
36
- # メッセージを配信できません。
37
- '=?iso-2022-jp?B?GyRCJWElQyU7ITwlOCRyR1s/LiRHJC0kXiQ7JHMhIxsoQg==?=',
38
- # メール配信に失敗しました
39
- '=?iso-2022-jp?B?GyRCJWEhPCVrR1s/LiRLPDpHVCQ3JF4kNyQ/GyhCDQo=?=',
36
+ 'メッセージを配信できません。',
37
+ 'メール配信に失敗しました',
40
38
  ]
41
39
  match += 1 if mhead['from'].start_with?('"InterScan MSS"')
42
40
  match += 1 if tryto.any? { |a| mhead['subject'] == a }
@@ -68,7 +66,7 @@ module Sisimai::Bite::Email
68
66
  end
69
67
 
70
68
  if readcursor & Indicators[:'message-rfc822'] > 0
71
- # After "message/rfc822"
69
+ # Inside of the original message part
72
70
  if e.empty?
73
71
  blanklines += 1
74
72
  break if blanklines > 1
@@ -76,7 +74,7 @@ module Sisimai::Bite::Email
76
74
  end
77
75
  rfc822list << e
78
76
  else
79
- # Before "message/rfc822"
77
+ # Error message part
80
78
  next if (readcursor & Indicators[:deliverystatus]) == 0
81
79
  next if e.empty?
82
80