sisimai 4.25.6 → 4.25.11
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.
- checksums.yaml +4 -4
- data/.travis.yml +4 -3
- data/ANALYTICAL-PRECISION +1 -1
- data/Benchmarks.mk +1 -1
- data/ChangeLog.md +71 -2
- data/Developers.mk +2 -2
- data/Makefile +1 -1
- data/README-JA.md +16 -16
- data/README.md +16 -16
- data/Repository.mk +1 -1
- data/lib/sisimai.rb +3 -3
- data/lib/sisimai/address.rb +6 -3
- data/lib/sisimai/arf.rb +25 -21
- data/lib/sisimai/data.rb +8 -29
- data/lib/sisimai/datetime.rb +18 -17
- data/lib/sisimai/lhost/amazonses.rb +1 -1
- data/lib/sisimai/lhost/domino.rb +29 -4
- data/lib/sisimai/lhost/einsundeins.rb +1 -1
- data/lib/sisimai/lhost/exchange2007.rb +1 -1
- data/lib/sisimai/lhost/exim.rb +12 -8
- data/lib/sisimai/lhost/ezweb.rb +1 -1
- data/lib/sisimai/lhost/fml.rb +0 -2
- data/lib/sisimai/lhost/gsuite.rb +5 -0
- data/lib/sisimai/lhost/imailserver.rb +1 -1
- data/lib/sisimai/lhost/mailfoundry.rb +3 -4
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +2 -2
- data/lib/sisimai/lhost/mxlogic.rb +1 -1
- data/lib/sisimai/lhost/notes.rb +1 -1
- data/lib/sisimai/lhost/office365.rb +1 -1
- data/lib/sisimai/lhost/postfix.rb +3 -10
- data/lib/sisimai/lhost/qmail.rb +7 -7
- data/lib/sisimai/lhost/sendgrid.rb +2 -2
- data/lib/sisimai/lhost/sendmail.rb +1 -1
- data/lib/sisimai/lhost/verizon.rb +4 -4
- data/lib/sisimai/lhost/x3.rb +4 -0
- data/lib/sisimai/lhost/x4.rb +8 -8
- data/lib/sisimai/lhost/x5.rb +7 -3
- data/lib/sisimai/mail.rb +2 -21
- data/lib/sisimai/mda.rb +2 -2
- data/lib/sisimai/message.rb +47 -83
- data/lib/sisimai/reason/blocked.rb +40 -26
- data/lib/sisimai/reason/exceedlimit.rb +4 -1
- data/lib/sisimai/reason/expired.rb +2 -0
- data/lib/sisimai/reason/filtered.rb +1 -0
- data/lib/sisimai/reason/hostunknown.rb +3 -0
- data/lib/sisimai/reason/mailererror.rb +1 -1
- data/lib/sisimai/reason/norelaying.rb +5 -0
- data/lib/sisimai/reason/notaccept.rb +2 -0
- data/lib/sisimai/reason/policyviolation.rb +4 -0
- data/lib/sisimai/reason/rejected.rb +5 -1
- data/lib/sisimai/reason/securityerror.rb +5 -6
- data/lib/sisimai/reason/spamdetected.rb +17 -15
- data/lib/sisimai/reason/suspend.rb +1 -0
- data/lib/sisimai/reason/systemerror.rb +2 -0
- data/lib/sisimai/reason/userunknown.rb +25 -21
- data/lib/sisimai/rfc1894.rb +24 -22
- data/lib/sisimai/rfc3464.rb +4 -5
- data/lib/sisimai/rfc3834.rb +1 -1
- data/lib/sisimai/rfc5322.rb +8 -4
- data/lib/sisimai/rhost.rb +6 -8
- data/lib/sisimai/rhost/cox.rb +112 -0
- data/lib/sisimai/rhost/exchangeonline.rb +8 -1
- data/lib/sisimai/rhost/googleapps.rb +4 -1
- data/lib/sisimai/rhost/spectrum.rb +73 -0
- data/lib/sisimai/smtp/error.rb +8 -6
- data/lib/sisimai/smtp/reply.rb +1 -1
- data/lib/sisimai/smtp/status.rb +1 -1
- data/lib/sisimai/time.rb +1 -2
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/README.md +5 -4
- data/set-of-emails/maildir/bsd/arf-25.eml +61 -0
- data/set-of-emails/maildir/bsd/lhost-aol-04.eml +23 -23
- data/set-of-emails/maildir/bsd/lhost-domino-02.eml +1 -2
- data/set-of-emails/maildir/bsd/lhost-exim-61.eml +40 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-38.eml +1 -1
- data/set-of-emails/maildir/bsd/lhost-postfix-66.eml +80 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-67.eml +80 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-68.eml +82 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-69.eml +80 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-70.eml +87 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-71.eml +81 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-72.eml +81 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-73.eml +79 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-74.eml +83 -0
- data/set-of-emails/maildir/bsd/lhost-sendmail-08.eml +1 -1
- data/set-of-emails/maildir/bsd/lhost-sendmail-11.eml +1 -1
- data/set-of-emails/maildir/bsd/lhost-sendmail-57.eml +59 -0
- data/set-of-emails/maildir/bsd/lhost-sendmail-58.eml +70 -0
- data/set-of-emails/maildir/bsd/lhost-sendmail-59.eml +68 -0
- data/set-of-emails/maildir/bsd/lhost-x3-06.eml +53 -0
- data/set-of-emails/maildir/bsd/rhost-cox-01.eml +192 -0
- data/set-of-emails/maildir/bsd/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
- data/set-of-emails/maildir/bsd/{rhost-exchange-online-02.eml → rhost-exchangeonline-02.eml} +0 -0
- data/set-of-emails/maildir/bsd/{rhost-exchange-online-03.eml → rhost-exchangeonline-03.eml} +0 -0
- data/set-of-emails/maildir/bsd/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
- data/set-of-emails/maildir/bsd/{rhost-google-apps-02.eml → rhost-googleapps-02.eml} +0 -0
- data/set-of-emails/maildir/bsd/rhost-spectrum-01.eml +111 -0
- data/set-of-emails/maildir/dos/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
- data/set-of-emails/maildir/dos/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
- data/set-of-emails/maildir/mac/{rhost-exchange-online-01.eml → rhost-exchangeonline-01.eml} +0 -0
- data/set-of-emails/maildir/mac/{rhost-google-apps-01.eml → rhost-googleapps-01.eml} +0 -0
- data/sisimai-java.gemspec +4 -4
- data/sisimai.gemspec +4 -4
- metadata +39 -20
data/lib/sisimai/data.rb
CHANGED
@@ -41,7 +41,6 @@ module Sisimai
|
|
41
41
|
|
42
42
|
RetryIndex = Sisimai::Reason.retry
|
43
43
|
RFC822Head = Sisimai::RFC5322.HEADERFIELDS(:all)
|
44
|
-
AddrHeader = { addresser: RFC822Head[:addresser], recipient: RFC822Head[:recipient] }.freeze
|
45
44
|
|
46
45
|
# Constructor of Sisimai::Data
|
47
46
|
# @param [Hash] argvs Data
|
@@ -96,35 +95,12 @@ module Sisimai
|
|
96
95
|
|
97
96
|
messageobj = data
|
98
97
|
rfc822data = messageobj.rfc822
|
99
|
-
fieldorder = { :recipient => [], :addresser => [] }
|
100
98
|
objectlist = []
|
101
|
-
givenorder = argvs[:order] || {}
|
102
99
|
delivered1 = argvs[:delivered] || false
|
103
100
|
|
104
101
|
return nil unless messageobj.ds
|
105
102
|
return nil unless messageobj.rfc822
|
106
103
|
|
107
|
-
# Decide the order of email headers: user specified or system default.
|
108
|
-
if givenorder.is_a?(Hash) && !givenorder.empty?
|
109
|
-
# If the order of headers for searching is specified, use the order
|
110
|
-
# for detecting an email address.
|
111
|
-
fieldorder.each_key do |e|
|
112
|
-
# The order should be "Array Reference".
|
113
|
-
next unless givenorder[e]
|
114
|
-
next unless givenorder[e].is_a? Array
|
115
|
-
next if givenorder[e].empty?
|
116
|
-
fieldorder[e] += givenorder[e]
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
fieldorder.each_key do |e|
|
121
|
-
# If the order is empty, use default order.
|
122
|
-
next unless fieldorder[e].empty?
|
123
|
-
|
124
|
-
# Load default order of each accessor.
|
125
|
-
fieldorder[e] = AddrHeader[e]
|
126
|
-
end
|
127
|
-
|
128
104
|
eachobject = messageobj.ds.dup
|
129
105
|
while e = eachobject.shift do
|
130
106
|
# Create parameters for new() constructor.
|
@@ -152,7 +128,7 @@ module Sisimai
|
|
152
128
|
|
153
129
|
# EMAIL_ADDRESS:
|
154
130
|
# Detect email address from message/rfc822 part
|
155
|
-
|
131
|
+
RFC822Head[:addresser].each do |f|
|
156
132
|
# Check each header in message/rfc822 part
|
157
133
|
next unless rfc822data[f]
|
158
134
|
next if rfc822data[f].empty?
|
@@ -313,10 +289,13 @@ module Sisimai
|
|
313
289
|
|
314
290
|
if o.reason.empty? || RetryIndex[o.reason]
|
315
291
|
# Decide the reason of email bounce
|
316
|
-
r = ''
|
317
|
-
|
318
|
-
|
319
|
-
|
292
|
+
r = ''; r = Sisimai::Rhost.get(o) if Sisimai::Rhost.match(o.rhost)
|
293
|
+
if r.empty?
|
294
|
+
# Failed to detect a bounce reason by the value of "rhost"
|
295
|
+
r = Sisimai::Rhost.get(o, o.destination) if Sisimai::Rhost.match(o.destination)
|
296
|
+
r = Sisimai::Reason.get(o) if r.empty?
|
297
|
+
r = 'undefined' if r.empty?
|
298
|
+
end
|
320
299
|
o.reason = r
|
321
300
|
end
|
322
301
|
|
data/lib/sisimai/datetime.rb
CHANGED
@@ -43,7 +43,7 @@ module Sisimai
|
|
43
43
|
abbr: %w[Sun Mon Tue Wed Thu Fri Sat],
|
44
44
|
}.freeze
|
45
45
|
|
46
|
-
|
46
|
+
TimeZones = {
|
47
47
|
# http://en.wikipedia.org/wiki/List_of_time_zone_abbreviations
|
48
48
|
#'ACDT' => '+1030', # Australian Central Daylight Time UTC+10:30
|
49
49
|
#'ACST' => '+0930', # Australian Central Standard Time UTC+09:30
|
@@ -207,24 +207,24 @@ module Sisimai
|
|
207
207
|
end
|
208
208
|
|
209
209
|
# Month name list
|
210
|
-
# @param [
|
210
|
+
# @param [Boolean] argv1 Require full name or not
|
211
211
|
# @return [Array, String] Month name list or month name
|
212
212
|
# @example Get the names of each month
|
213
|
-
# monthname()
|
214
|
-
# monthname(
|
215
|
-
def monthname(argv1 =
|
216
|
-
value = argv1
|
213
|
+
# monthname() #=> [ 'Jan', 'Feb', ... ]
|
214
|
+
# monthname(true) #=> [ 'January', 'February', 'March', ... ]
|
215
|
+
def monthname(argv1 = false)
|
216
|
+
value = argv1 ? :full : :abbr
|
217
217
|
return MonthName[value]
|
218
218
|
end
|
219
219
|
|
220
220
|
# List of day of week
|
221
|
-
# @param [
|
221
|
+
# @param [Boolean] argv1 Require full name
|
222
222
|
# @return [Array, String] List of day of week or day of week
|
223
223
|
# @example Get the names of each day of week
|
224
|
-
# dayofweek()
|
225
|
-
# dayofweek(
|
226
|
-
def dayofweek(argv1 =
|
227
|
-
value = argv1
|
224
|
+
# dayofweek() #=> [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ]
|
225
|
+
# dayofweek(true) #=> [ 'Sunday', 'Monday', 'Tuesday', ... ]
|
226
|
+
def dayofweek(argv1 = false)
|
227
|
+
value = argv1 ? :full : :abbr
|
228
228
|
return DayOfWeek[value]
|
229
229
|
end
|
230
230
|
|
@@ -257,9 +257,10 @@ module Sisimai
|
|
257
257
|
|
258
258
|
while p = timetokens.shift do
|
259
259
|
# Parse each piece of time
|
260
|
-
if p =~ /\A[A-Z][a-z]{2}[,]?\z/
|
260
|
+
if p =~ /\A[A-Z][a-z]{2,}[,]?\z/
|
261
261
|
# Day of week or Day of week; Thu, Apr, ...
|
262
|
-
p.
|
262
|
+
p.gsub!(/,\z/, '') if p.end_with?(',') # "Thu," => "Thu"
|
263
|
+
p = p[0,3] if p.size > 3
|
263
264
|
|
264
265
|
if DayOfWeek[:abbr].include?(p)
|
265
266
|
# Day of week; Mon, Thu, Sun,...
|
@@ -273,7 +274,7 @@ module Sisimai
|
|
273
274
|
# Year or Day; 2005, 31, 04, 1, ...
|
274
275
|
if p.to_i > 31
|
275
276
|
# The piece is the value of an year
|
276
|
-
v[:Y] = p
|
277
|
+
v[:Y] = p.to_i
|
277
278
|
else
|
278
279
|
# The piece is the value of a day
|
279
280
|
if v[:d]
|
@@ -399,7 +400,7 @@ module Sisimai
|
|
399
400
|
# abbr2tz('JST') #=> '+0900'
|
400
401
|
def abbr2tz(argv1)
|
401
402
|
return nil unless argv1.is_a?(::String)
|
402
|
-
return
|
403
|
+
return TimeZones[argv1]
|
403
404
|
end
|
404
405
|
|
405
406
|
# Convert to second
|
@@ -428,7 +429,7 @@ module Sisimai
|
|
428
429
|
return ztime
|
429
430
|
|
430
431
|
elsif argv1 =~ /\A[A-Za-z]+\z/
|
431
|
-
return tz2second(
|
432
|
+
return tz2second(TimeZones[argv1])
|
432
433
|
else
|
433
434
|
return nil
|
434
435
|
end
|
@@ -441,7 +442,7 @@ module Sisimai
|
|
441
442
|
# @example Get timezone offset string of specified seconds
|
442
443
|
# second2tz(12345) #=> '+0325'
|
443
444
|
def second2tz(argv1)
|
444
|
-
return '+0000' unless argv1.is_a?(
|
445
|
+
return '+0000' unless argv1.is_a?(::Integer)
|
445
446
|
return nil if argv1.abs > TZ_OFFSET # UTC+14 + 1(DST?)
|
446
447
|
|
447
448
|
digit = { :operator => '+' }
|
@@ -182,7 +182,7 @@ module Sisimai::Lhost
|
|
182
182
|
v['status'] = Sisimai::SMTP::Status.find(v['diagnosis']) || ''
|
183
183
|
v['replycode'] = Sisimai::SMTP::Reply.find(v['diagnosis']) || ''
|
184
184
|
v['reason'] = 'delivered'
|
185
|
-
v['action'] = '
|
185
|
+
v['action'] = 'delivered'
|
186
186
|
|
187
187
|
v['date'] = o['timestamp'] || p['mail']['timestamp']
|
188
188
|
v['date'].sub!(/[.]\d+Z\z/, '')
|
data/lib/sisimai/lhost/domino.rb
CHANGED
@@ -7,12 +7,13 @@ module Sisimai::Lhost
|
|
7
7
|
require 'sisimai/lhost'
|
8
8
|
|
9
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
ReBackbone = %r|^Content-Type:[ ]message/
|
10
|
+
ReBackbone = %r|^Content-Type:[ ]message/rfc822|.freeze
|
11
11
|
StartingOf = { message: ['Your message'] }.freeze
|
12
12
|
MessagesOf = {
|
13
13
|
'userunknown' => [
|
14
14
|
'not listed in Domino Directory',
|
15
15
|
'not listed in public Name & Address Book',
|
16
|
+
"dans l'annuaire Domino", # TODO: "non répertorié dans l'annuaire Domino",
|
16
17
|
'Domino ディレクトリには見つかりません',
|
17
18
|
],
|
18
19
|
'filtered' => ['Cannot route mail to user'],
|
@@ -25,7 +26,11 @@ module Sisimai::Lhost
|
|
25
26
|
# @return [Hash] Bounce data list and message/rfc822 part
|
26
27
|
# @return [Nil] it failed to parse or the arguments are missing
|
27
28
|
def make(mhead, mbody)
|
28
|
-
return nil unless mhead['subject'].start_with?('DELIVERY FAILURE:')
|
29
|
+
return nil unless mhead['subject'].start_with?('DELIVERY FAILURE:', 'DELIVERY_FAILURE:')
|
30
|
+
|
31
|
+
require 'sisimai/rfc1894'
|
32
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
33
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
29
34
|
|
30
35
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
31
36
|
emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
|
@@ -87,6 +92,24 @@ module Sisimai::Lhost
|
|
87
92
|
elsif cv = e.match(/\A[ ][ ]Subject: (.+)\z/)
|
88
93
|
# Subject: Nyaa
|
89
94
|
subjecttxt = cv[1]
|
95
|
+
|
96
|
+
elsif f = Sisimai::RFC1894.match(e)
|
97
|
+
# There are some fields defined in RFC3464, try to match
|
98
|
+
o = Sisimai::RFC1894.field(e) || next
|
99
|
+
next if o[-1] == 'addr'
|
100
|
+
|
101
|
+
if o[-1] == 'code'
|
102
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
103
|
+
v['spec'] = o[1] if v['spec'].to_s.empty?
|
104
|
+
v['diagnosis'] = o[2] if v['diagnosis'].to_s.empty?
|
105
|
+
else
|
106
|
+
# Other DSN fields defined in RFC3464
|
107
|
+
next unless fieldtable[o[0]]
|
108
|
+
v[fieldtable[o[0]]] = o[2]
|
109
|
+
|
110
|
+
next unless f == 1
|
111
|
+
permessage[fieldtable[o[0]]] = o[2]
|
112
|
+
end
|
90
113
|
end
|
91
114
|
end
|
92
115
|
end
|
@@ -95,12 +118,14 @@ module Sisimai::Lhost
|
|
95
118
|
dscontents.each do |e|
|
96
119
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
97
120
|
e['recipient'] = Sisimai::Address.s3s4(e['recipient'])
|
121
|
+
e['lhost'] ||= permessage['rhost']
|
122
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
98
123
|
|
99
124
|
MessagesOf.each_key do |r|
|
100
125
|
# Check each regular expression of Domino error messages
|
101
126
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
102
|
-
e['reason']
|
103
|
-
e['status']
|
127
|
+
e['reason'] = r
|
128
|
+
e['status'] ||= Sisimai::SMTP::Status.code(r.to_s, false) || ''
|
104
129
|
break
|
105
130
|
end
|
106
131
|
end
|
@@ -52,7 +52,7 @@ module Sisimai::Lhost
|
|
52
52
|
# http://postmaster.1and1.com/en/error-messages?ip=%1s
|
53
53
|
v = dscontents[-1]
|
54
54
|
|
55
|
-
if cv = e.match(/\A([^ ]+[@][^ ]
|
55
|
+
if cv = e.match(/\A([^ ]+[@][^ ]+?)[:]?\z/)
|
56
56
|
# general@example.eu
|
57
57
|
if v['recipient']
|
58
58
|
# There are multiple recipient addresses in the message body.
|
@@ -24,7 +24,7 @@ module Sisimai::Lhost
|
|
24
24
|
error: %r/ ((?:RESOLVER|QUEUE)[.][A-Za-z]+(?:[.]\w+)?);/,
|
25
25
|
rhost: %r{\A(?:
|
26
26
|
Generating[ ]server # en-US
|
27
|
-
|Serveur[ ]de[ ]g
|
27
|
+
|Serveur[ ]de[ ]g[^ ]+ration[ ] # fr-FR/Serveur de génération
|
28
28
|
|Server[ ]di[ ]generazione # it-CH
|
29
29
|
):[ ]?(.*)
|
30
30
|
}x,
|
data/lib/sisimai/lhost/exim.rb
CHANGED
@@ -12,7 +12,7 @@ module Sisimai::Lhost
|
|
12
12
|
# deliver.c:6425| else fprintf(f,
|
13
13
|
# deliver.c:6426|"------ This is a copy of the message's headers. ------\n");
|
14
14
|
ReBackbone = %r{^(?:
|
15
|
-
[-]+[ ]This[ ]is[ ]a[ ]copy[ ]of[ ](?:the|your)[ ]message
|
15
|
+
[-]+[ ]This[ ]is[ ]a[ ]copy[ ]of[ ](?:the|your)[ ]message,[ ]including[ ]all[ ]the[ ]headers[.][ ][-]+
|
16
16
|
|Content-Type:[ ]*message/rfc822\n(?:[\s\t]+.*?\n\n)?
|
17
17
|
)
|
18
18
|
}x.freeze
|
@@ -36,13 +36,14 @@ module Sisimai::Lhost
|
|
36
36
|
# deliver.c:6305|"address(es) failed:\n", sender_address);
|
37
37
|
# deliver.c:6306| }
|
38
38
|
alias: %r/\A([ ]+an undisclosed address)\z/,
|
39
|
-
frozen: %r/\AMessage
|
39
|
+
frozen: %r/\AMessage [^ ]+ (?:has been frozen|was frozen on arrival)/,
|
40
40
|
message: %r{\A(?>
|
41
41
|
This[ ]message[ ]was[ ]created[ ]automatically[ ]by[ ]mail[ ]delivery[ ]software[.]
|
42
42
|
|A[ ]message[ ]that[ ]you[ ]sent[ ]was[ ]rejected[ ]by[ ]the[ ]local[ ]scanning[ ]code
|
43
43
|
|A[ ]message[ ]that[ ]you[ ]sent[ ]contained[ ]one[ ]or[ ]more[ ]recipient[ ]addresses[ ]
|
44
|
-
|
|
45
|
-
|
|
44
|
+
|A[ ]message[ ]that[ ]you[ ]sent[ ]could[ ]not[ ]be[ ]delivered[ ]to[ ]all[ ]of[ ]its[ ]recipients
|
45
|
+
|Message[ ][^ ]+[ ](?:has[ ]been[ ]frozen|was[ ]frozen[ ]on[ ]arrival)
|
46
|
+
|The[ ][^ ]+[ ]router[ ]encountered[ ]the[ ]following[ ]error[(]s[)]:
|
46
47
|
)
|
47
48
|
}x,
|
48
49
|
}.freeze
|
@@ -134,7 +135,7 @@ module Sisimai::Lhost
|
|
134
135
|
match += 1 if mhead['message-id'].to_s =~ %r/\A[<]\w{7}[-]\w{6}[-]\w{2}[@]/
|
135
136
|
match += 1 if mhead['subject'] =~ %r{(?:
|
136
137
|
Mail[ ]delivery[ ]failed(:[ ]returning[ ]message[ ]to[ ]sender)?
|
137
|
-
|Warning:[ ]message[ ]
|
138
|
+
|Warning:[ ]message[ ][^ ]+[ ]delayed[ ]+
|
138
139
|
|Delivery[ ]Status[ ]Notification
|
139
140
|
|Mail[ ]failure
|
140
141
|
|Message[ ]frozen
|
@@ -264,7 +265,10 @@ module Sisimai::Lhost
|
|
264
265
|
# Content-type: message/delivery-status
|
265
266
|
nextcursor = 1 if e.start_with?(StartingOf[:deliverystatus][0])
|
266
267
|
v['alterrors'] ||= ''
|
267
|
-
|
268
|
+
if e.start_with?("\s", "\t")
|
269
|
+
e.sub!(/\A[\s\t]+/, '')
|
270
|
+
v['alterrors'] << e + ' ' unless v['alterrors'].include?(e)
|
271
|
+
end
|
268
272
|
end
|
269
273
|
else
|
270
274
|
if dscontents.size == recipients
|
@@ -275,7 +279,7 @@ module Sisimai::Lhost
|
|
275
279
|
else
|
276
280
|
# Error message when email address above does not include '@'
|
277
281
|
# and domain part.
|
278
|
-
if e =~ %r<\A[ ]+pipe[ ]to[ ][|]
|
282
|
+
if e =~ %r<\A[ ]+pipe[ ]to[ ][|]/[^ ]+>
|
279
283
|
# pipe to |/path/to/prog ...
|
280
284
|
# generated by kijitora@example.com
|
281
285
|
v['diagnosis'] = e
|
@@ -374,7 +378,7 @@ module Sisimai::Lhost
|
|
374
378
|
rxdiagnosis = %r/e['diagnosis']/i
|
375
379
|
# Override the value of diagnostic code message because
|
376
380
|
# the value of alterrors includes the value of diagnosis.
|
377
|
-
e['diagnosis'] = e['alterrors'] if e['alterrors']
|
381
|
+
e['diagnosis'] = e['alterrors'] if e['alterrors'].downcase.include?(e['diagnosis'].downcase)
|
378
382
|
end
|
379
383
|
end
|
380
384
|
e.delete('alterrors')
|
data/lib/sisimai/lhost/ezweb.rb
CHANGED
@@ -125,7 +125,7 @@ module Sisimai::Lhost
|
|
125
125
|
v['command'] = cv[1]
|
126
126
|
else
|
127
127
|
# Check error message
|
128
|
-
if rxmessages.any? { |
|
128
|
+
if rxmessages.any? { |messages| messages.any? { |message| e =~ message } }
|
129
129
|
# Check with regular expressions of each error
|
130
130
|
v['diagnosis'] ||= ''
|
131
131
|
v['diagnosis'] << ' ' << e
|
data/lib/sisimai/lhost/fml.rb
CHANGED
@@ -59,14 +59,12 @@ module Sisimai::Lhost
|
|
59
59
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
60
60
|
emailsteak = Sisimai::RFC5322.fillet(mbody, ReBackbone)
|
61
61
|
bodyslices = emailsteak[0].split("\n")
|
62
|
-
readcursor = 0 # (Integer) Points the current cursor position
|
63
62
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
64
63
|
v = nil
|
65
64
|
|
66
65
|
while e = bodyslices.shift do
|
67
66
|
# Read error messages and delivery status lines from the head of the email
|
68
67
|
# to the previous line of the beginning of the original message.
|
69
|
-
next if (readcursor & Indicators[:deliverystatus]) == 0
|
70
68
|
next if e.empty?
|
71
69
|
|
72
70
|
# Duplicated Message-ID in <2ndml@example.com>.
|
data/lib/sisimai/lhost/gsuite.rb
CHANGED
@@ -82,6 +82,11 @@ module Sisimai::Lhost
|
|
82
82
|
next unless fieldtable[o[0]]
|
83
83
|
v[fieldtable[o[0]]] = o[2]
|
84
84
|
|
85
|
+
if fieldtable[o[0]] == 'lhost'
|
86
|
+
# Do not set an email address as a hostname in "lhost" value
|
87
|
+
v['lhost'] = '' if v['lhost'].include?('@')
|
88
|
+
end
|
89
|
+
|
85
90
|
next unless f == 1
|
86
91
|
permessage[fieldtable[o[0]]] = o[2]
|
87
92
|
end
|
@@ -9,7 +9,7 @@ module Sisimai::Lhost
|
|
9
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
10
|
ReBackbone = %r|^Content-Type:[ ]message/rfc822|.freeze
|
11
11
|
StartingOf = {
|
12
|
-
message: ['
|
12
|
+
message: ['Unable to deliver message to:'],
|
13
13
|
error: ['Delivery failed for the following reason:'],
|
14
14
|
}.freeze
|
15
15
|
|
@@ -34,8 +34,7 @@ module Sisimai::Lhost
|
|
34
34
|
# to the previous line of the beginning of the original message.
|
35
35
|
if readcursor == 0
|
36
36
|
# Beginning of the bounce message or delivery status part
|
37
|
-
readcursor |= Indicators[:deliverystatus] if e
|
38
|
-
next
|
37
|
+
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
39
38
|
end
|
40
39
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
41
40
|
next if e.empty?
|
@@ -44,7 +43,7 @@ module Sisimai::Lhost
|
|
44
43
|
# Delivery failed for the following reason:
|
45
44
|
# Server mx22.example.org[192.0.2.222] failed with: 550 <kijitora@example.org> No such user here
|
46
45
|
#
|
47
|
-
# This has been a permanent failure.
|
46
|
+
# This has been a permanent failure. No further delivery attempts will be made.
|
48
47
|
v = dscontents[-1]
|
49
48
|
|
50
49
|
if cv = e.match(/\AUnable to deliver message to: [<]([^ ]+[@][^ ]+)[>]\z/)
|
@@ -32,10 +32,10 @@ module Sisimai::Lhost
|
|
32
32
|
regularexp = nil
|
33
33
|
v = nil
|
34
34
|
|
35
|
-
boundary00 = Sisimai::MIME.boundary(mhead['content-type']) || ''
|
35
|
+
boundary00 = Sisimai::MIME.boundary(mhead['content-type'], 1) || ''
|
36
36
|
regularexp = if boundary00.size > 0
|
37
37
|
# Convert to regular expression
|
38
|
-
Regexp.new('\A' << Regexp.escape(
|
38
|
+
Regexp.new('\A' << Regexp.escape(boundary00) << '\z')
|
39
39
|
else
|
40
40
|
regularexp = %r/\A[ \t]*[+]+[ \t]*\z/
|
41
41
|
end
|
@@ -85,7 +85,7 @@ module Sisimai::Lhost
|
|
85
85
|
match += 1 if mhead['from'].start_with?('Mail Delivery System')
|
86
86
|
match += 1 if mhead['subject'] =~ %r{(?:
|
87
87
|
Mail[ ]delivery[ ]failed(:[ ]returning[ ]message[ ]to[ ]sender)?
|
88
|
-
|Warning:[ ]message[ ]
|
88
|
+
|Warning:[ ]message[ ][^ ]+[ ]delayed[ ]+
|
89
89
|
|Delivery[ ]Status[ ]Notification
|
90
90
|
)
|
91
91
|
}x
|
data/lib/sisimai/lhost/notes.rb
CHANGED
@@ -14,7 +14,7 @@ module Sisimai::Lhost
|
|
14
14
|
'User not listed in public Name & Address Book',
|
15
15
|
'ディレクトリのリストにありません',
|
16
16
|
],
|
17
|
-
networkerror
|
17
|
+
'networkerror' => ['Message has exceeded maximum hop count'],
|
18
18
|
}.freeze
|
19
19
|
|
20
20
|
# Parse bounce messages from Lotus Notes
|
@@ -188,7 +188,7 @@ module Sisimai::Lhost
|
|
188
188
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
189
189
|
if e['status'].empty? || e['status'].end_with?('.0.0')
|
190
190
|
# There is no value of Status header or the value is 5.0.0, 4.0.0
|
191
|
-
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
|
191
|
+
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || e['status']
|
192
192
|
end
|
193
193
|
|
194
194
|
ReCommands.each_key do |p|
|