sisimai 4.24.1-java → 4.25.0-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.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/ANALYTICAL-PRECISION +16 -25
- data/ChangeLog.md +41 -0
- data/Developers.mk +2 -2
- data/README-JA.md +13 -13
- data/README.md +13 -13
- data/lib/sisimai.rb +3 -7
- data/lib/sisimai/address.rb +25 -41
- data/lib/sisimai/arf.rb +58 -59
- data/lib/sisimai/bite.rb +0 -1
- data/lib/sisimai/bite/email.rb +7 -7
- data/lib/sisimai/bite/email/activehunter.rb +4 -3
- data/lib/sisimai/bite/email/amavis.rb +133 -0
- data/lib/sisimai/bite/email/amazonses.rb +53 -87
- data/lib/sisimai/bite/email/amazonworkmail.rb +51 -57
- data/lib/sisimai/bite/email/aol.rb +50 -76
- data/lib/sisimai/bite/email/apachejames.rb +2 -2
- data/lib/sisimai/bite/email/bigfoot.rb +47 -74
- data/lib/sisimai/bite/email/biglobe.rb +8 -9
- data/lib/sisimai/bite/email/courier.rb +56 -101
- data/lib/sisimai/bite/email/domino.rb +7 -8
- data/lib/sisimai/bite/email/einsundeins.rb +4 -5
- data/lib/sisimai/bite/email/exchange2003.rb +21 -22
- data/lib/sisimai/bite/email/exchange2007.rb +26 -28
- data/lib/sisimai/bite/email/exim.rb +48 -47
- data/lib/sisimai/bite/email/ezweb.rb +24 -36
- data/lib/sisimai/bite/email/facebook.rb +54 -79
- data/lib/sisimai/bite/email/fml.rb +10 -10
- data/lib/sisimai/bite/email/gmx.rb +6 -6
- data/lib/sisimai/bite/email/google.rb +12 -13
- data/lib/sisimai/bite/email/gsuite.rb +80 -108
- data/lib/sisimai/bite/email/imailserver.rb +16 -16
- data/lib/sisimai/bite/email/interscanmss.rb +4 -6
- data/lib/sisimai/bite/email/kddi.rb +9 -11
- data/lib/sisimai/bite/email/mailfoundry.rb +2 -2
- data/lib/sisimai/bite/email/mailmarshalsmtp.rb +2 -2
- data/lib/sisimai/bite/email/mailru.rb +12 -13
- data/lib/sisimai/bite/email/mcafee.rb +31 -25
- data/lib/sisimai/bite/email/messagelabs.rb +48 -87
- data/lib/sisimai/bite/email/messagingserver.rb +9 -10
- data/lib/sisimai/bite/email/mfilter.rb +16 -16
- data/lib/sisimai/bite/email/mxlogic.rb +11 -11
- data/lib/sisimai/bite/email/notes.rb +5 -6
- data/lib/sisimai/bite/email/office365.rb +25 -42
- data/lib/sisimai/bite/email/opensmtpd.rb +8 -8
- data/lib/sisimai/bite/email/outlook.rb +49 -67
- data/lib/sisimai/bite/email/postfix.rb +78 -112
- data/lib/sisimai/bite/email/qmail.rb +23 -23
- data/lib/sisimai/bite/email/receivingses.rb +53 -86
- data/lib/sisimai/bite/email/sendgrid.rb +65 -84
- data/lib/sisimai/bite/email/sendmail.rb +89 -117
- data/lib/sisimai/bite/email/surfcontrol.rb +15 -18
- data/lib/sisimai/bite/email/userdefined.rb +1 -1
- data/lib/sisimai/bite/email/v5sendmail.rb +3 -4
- data/lib/sisimai/bite/email/verizon.rb +7 -8
- data/lib/sisimai/bite/email/x1.rb +2 -2
- data/lib/sisimai/bite/email/x2.rb +2 -2
- data/lib/sisimai/bite/email/x3.rb +3 -3
- data/lib/sisimai/bite/email/x4.rb +22 -22
- data/lib/sisimai/bite/email/x5.rb +40 -49
- data/lib/sisimai/bite/email/yahoo.rb +3 -3
- data/lib/sisimai/bite/email/yandex.rb +54 -82
- data/lib/sisimai/bite/email/zoho.rb +6 -6
- data/lib/sisimai/bite/json/amazonses.rb +20 -20
- data/lib/sisimai/bite/json/sendgrid.rb +2 -2
- data/lib/sisimai/data.rb +27 -40
- data/lib/sisimai/datetime.rb +146 -162
- data/lib/sisimai/mda.rb +30 -31
- data/lib/sisimai/message/email.rb +83 -123
- data/lib/sisimai/message/json.rb +2 -4
- data/lib/sisimai/mime.rb +31 -34
- data/lib/sisimai/order/email.rb +23 -22
- data/lib/sisimai/reason.rb +61 -61
- data/lib/sisimai/reason/blocked.rb +139 -135
- data/lib/sisimai/reason/contenterror.rb +11 -10
- data/lib/sisimai/reason/exceedlimit.rb +4 -4
- data/lib/sisimai/reason/expired.rb +20 -20
- data/lib/sisimai/reason/filtered.rb +19 -18
- data/lib/sisimai/reason/hasmoved.rb +3 -3
- data/lib/sisimai/reason/hostunknown.rb +19 -19
- data/lib/sisimai/reason/mailboxfull.rb +49 -49
- data/lib/sisimai/reason/mailererror.rb +16 -16
- data/lib/sisimai/reason/mesgtoobig.rb +17 -17
- data/lib/sisimai/reason/networkerror.rb +19 -19
- data/lib/sisimai/reason/norelaying.rb +16 -16
- data/lib/sisimai/reason/notaccept.rb +9 -10
- data/lib/sisimai/reason/onhold.rb +1 -1
- data/lib/sisimai/reason/policyviolation.rb +21 -20
- data/lib/sisimai/reason/rejected.rb +53 -53
- data/lib/sisimai/reason/securityerror.rb +29 -29
- data/lib/sisimai/reason/spamdetected.rb +127 -127
- data/lib/sisimai/reason/suspend.rb +17 -17
- data/lib/sisimai/reason/systemerror.rb +22 -21
- data/lib/sisimai/reason/systemfull.rb +6 -6
- data/lib/sisimai/reason/toomanyconn.rb +19 -18
- data/lib/sisimai/reason/userunknown.rb +122 -121
- data/lib/sisimai/reason/vacation.rb +8 -8
- data/lib/sisimai/reason/virusdetected.rb +8 -8
- data/lib/sisimai/rfc1894.rb +142 -0
- data/lib/sisimai/rfc3464.rb +70 -70
- data/lib/sisimai/rfc3834.rb +15 -15
- data/lib/sisimai/rfc5322.rb +20 -36
- data/lib/sisimai/rhost.rb +1 -0
- data/lib/sisimai/rhost/exchangeonline.rb +31 -33
- data/lib/sisimai/rhost/franceptt.rb +23 -23
- data/lib/sisimai/rhost/godaddy.rb +28 -28
- data/lib/sisimai/rhost/googleapps.rb +39 -41
- data/lib/sisimai/rhost/kddi.rb +3 -3
- data/lib/sisimai/rhost/tencentqq.rb +51 -0
- data/lib/sisimai/smtp/error.rb +14 -21
- data/lib/sisimai/smtp/reply.rb +14 -13
- data/lib/sisimai/smtp/status.rb +178 -179
- data/lib/sisimai/string.rb +13 -12
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/README.md +1 -5
- data/set-of-emails/maildir/bsd/arf-23.eml +49 -0
- data/set-of-emails/maildir/bsd/email-amavis-01.eml +78 -0
- data/set-of-emails/maildir/bsd/email-amavis-02.eml +78 -0
- data/set-of-emails/maildir/bsd/email-exchange2007-04.eml +146 -0
- data/set-of-emails/maildir/bsd/email-exim-60.eml +94 -0
- data/set-of-emails/maildir/bsd/email-ezweb-08.eml +49 -0
- data/set-of-emails/maildir/bsd/email-google-19.eml +67 -0
- data/set-of-emails/maildir/bsd/email-mcafee-05.eml +74 -0
- data/set-of-emails/maildir/bsd/email-messagingserver-12.eml +99 -0
- data/set-of-emails/maildir/bsd/email-postfix-46.eml +81 -0
- data/set-of-emails/maildir/bsd/email-postfix-47.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-48.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-49.eml +141 -0
- data/set-of-emails/maildir/bsd/email-postfix-50.eml +143 -0
- data/set-of-emails/maildir/bsd/email-postfix-51.eml +73 -0
- data/set-of-emails/maildir/bsd/email-postfix-52.eml +79 -0
- data/set-of-emails/maildir/bsd/email-postfix-53.eml +76 -0
- data/set-of-emails/maildir/bsd/email-postfix-54.eml +73 -0
- data/set-of-emails/maildir/bsd/email-postfix-55.eml +74 -0
- data/set-of-emails/maildir/bsd/email-postfix-56.eml +78 -0
- data/set-of-emails/maildir/bsd/email-qmail-10.eml +50 -0
- data/set-of-emails/maildir/bsd/email-x2-05.eml +38 -0
- data/set-of-emails/maildir/bsd/rhost-google-apps-02.eml +88 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-01.eml +84 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-02.eml +84 -0
- data/set-of-emails/maildir/bsd/rhost-tencentqq-03.eml +81 -0
- data/set-of-emails/maildir/dos/email-amavis-01.eml +78 -0
- data/set-of-emails/maildir/dos/email-apachejames-01.eml +1 -2
- data/set-of-emails/maildir/dos/email-messagelabs-01.eml +67 -50
- data/set-of-emails/maildir/dos/email-x4-01.eml +31 -76
- data/set-of-emails/maildir/dos/rhost-tencentqq-01.eml +84 -0
- data/set-of-emails/maildir/mac/email-amavis-01.eml +1 -4
- data/set-of-emails/maildir/mac/email-apachejames-01.eml +1 -9
- data/set-of-emails/maildir/mac/email-messagelabs-01.eml +1 -9
- data/set-of-emails/maildir/mac/email-x4-01.eml +1 -5
- data/set-of-emails/maildir/mac/rhost-tencentqq-01.eml +1 -4
- metadata +35 -4
- data/set-of-emails/logo/horizontalversions.png +0 -0
- data/set-of-emails/logo/icon.png +0 -0
@@ -16,9 +16,9 @@ module Sisimai::Bite::Email
|
|
16
16
|
/x,
|
17
17
|
}.freeze
|
18
18
|
MessagesOf = {
|
19
|
-
mailboxfull
|
20
|
-
norelaying
|
21
|
-
hostunknown
|
19
|
+
'mailboxfull' => ['As their mailbox is full'],
|
20
|
+
'norelaying' => ['Due to the following SMTP relay error'],
|
21
|
+
'hostunknown' => ['As the remote domain doesnt exist'],
|
22
22
|
}.freeze
|
23
23
|
|
24
24
|
def description; return 'au by KDDI: http://www.au.kddi.com'; end
|
@@ -71,7 +71,7 @@ module Sisimai::Bite::Email
|
|
71
71
|
end
|
72
72
|
|
73
73
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
74
|
-
#
|
74
|
+
# Inside of the original message part
|
75
75
|
if e.empty?
|
76
76
|
blanklines += 1
|
77
77
|
break if blanklines > 1
|
@@ -79,7 +79,7 @@ module Sisimai::Bite::Email
|
|
79
79
|
end
|
80
80
|
rfc822list << e
|
81
81
|
else
|
82
|
-
#
|
82
|
+
# Error message part
|
83
83
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
84
84
|
next if e.empty?
|
85
85
|
|
@@ -93,12 +93,10 @@ module Sisimai::Bite::Email
|
|
93
93
|
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
94
94
|
v = dscontents[-1]
|
95
95
|
end
|
96
|
-
|
97
96
|
r = Sisimai::Address.s3s4(cv[1])
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
97
|
+
next unless Sisimai::RFC5322.is_emailaddress(r)
|
98
|
+
v['recipient'] = r
|
99
|
+
recipients += 1
|
102
100
|
|
103
101
|
elsif cv = e.match(/Your mail sent on: (.+)\z/)
|
104
102
|
# Your mail sent on: Thu, 29 Apr 2010 11:04:47 +0900
|
@@ -130,7 +128,7 @@ module Sisimai::Bite::Email
|
|
130
128
|
MessagesOf.each_key do |r|
|
131
129
|
# Verify each regular expression of session errors
|
132
130
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
133
|
-
e['reason'] = r
|
131
|
+
e['reason'] = r
|
134
132
|
break
|
135
133
|
end
|
136
134
|
end
|
@@ -58,7 +58,7 @@ module Sisimai::Bite::Email
|
|
58
58
|
end
|
59
59
|
|
60
60
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
61
|
-
#
|
61
|
+
# Inside of the original message part
|
62
62
|
if e.empty?
|
63
63
|
blanklines += 1
|
64
64
|
break if blanklines > 1
|
@@ -66,7 +66,7 @@ module Sisimai::Bite::Email
|
|
66
66
|
end
|
67
67
|
rfc822list << e
|
68
68
|
else
|
69
|
-
#
|
69
|
+
# Error message part
|
70
70
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
71
71
|
next if e.empty?
|
72
72
|
|
@@ -68,7 +68,7 @@ module Sisimai::Bite::Email
|
|
68
68
|
end
|
69
69
|
|
70
70
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
71
|
-
#
|
71
|
+
# Inside of the original message part
|
72
72
|
if e.empty?
|
73
73
|
blanklines += 1
|
74
74
|
break if blanklines > 1
|
@@ -76,7 +76,7 @@ module Sisimai::Bite::Email
|
|
76
76
|
end
|
77
77
|
rfc822list << e
|
78
78
|
else
|
79
|
-
#
|
79
|
+
# Error message part
|
80
80
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
81
81
|
break if e =~ regularexp
|
82
82
|
|
@@ -18,39 +18,39 @@ module Sisimai::Bite::Email
|
|
18
18
|
%r/SMTP error from remote (?:mail server|mailer) after end of ([A-Za-z]{4})/,
|
19
19
|
].freeze
|
20
20
|
MessagesOf = {
|
21
|
-
expired
|
21
|
+
'expired' => [
|
22
22
|
'retry timeout exceeded',
|
23
23
|
'No action is required on your part',
|
24
24
|
],
|
25
|
-
userunknown
|
26
|
-
hostunknown
|
25
|
+
'userunknown' => ['user not found'],
|
26
|
+
'hostunknown' => [
|
27
27
|
'all host address lookups failed permanently',
|
28
28
|
'all relevant MX records point to non-existent hosts',
|
29
29
|
'Unrouteable address',
|
30
30
|
],
|
31
|
-
mailboxfull
|
32
|
-
notaccept
|
31
|
+
'mailboxfull' => ['mailbox is full', 'error: quota exceed'],
|
32
|
+
'notaccept' => [
|
33
33
|
'an MX or SRV record indicated no SMTP service',
|
34
34
|
'no host found for existing SMTP connection',
|
35
35
|
],
|
36
|
-
syntaxerror
|
36
|
+
'syntaxerror' => [
|
37
37
|
'angle-brackets nested too deep',
|
38
38
|
'expected word or "<"',
|
39
39
|
'domain missing in source-routed address',
|
40
40
|
'malformed address:',
|
41
41
|
],
|
42
|
-
systemerror
|
42
|
+
'systemerror' => [
|
43
43
|
'delivery to file forbidden',
|
44
44
|
'delivery to pipe forbidden',
|
45
45
|
'local delivery failed',
|
46
46
|
'LMTP error after ',
|
47
47
|
],
|
48
|
-
contenterror
|
48
|
+
'contenterror' => ['Too many "Received" headers'],
|
49
49
|
}.freeze
|
50
50
|
|
51
51
|
def description; return '@mail.ru: https://mail.ru'; end
|
52
52
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
53
|
-
def headerlist; return [
|
53
|
+
def headerlist; return %w[x-failed-recipients]; end
|
54
54
|
|
55
55
|
# Parse bounce messages from @mail.ru
|
56
56
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -103,8 +103,7 @@ module Sisimai::Bite::Email
|
|
103
103
|
end
|
104
104
|
|
105
105
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
106
|
-
#
|
107
|
-
# After "message/rfc822"
|
106
|
+
# Inside of the original message part
|
108
107
|
if e.empty?
|
109
108
|
blanklines += 1
|
110
109
|
break if blanklines > 1
|
@@ -112,7 +111,7 @@ module Sisimai::Bite::Email
|
|
112
111
|
end
|
113
112
|
rfc822list << e
|
114
113
|
else
|
115
|
-
#
|
114
|
+
# Error message part
|
116
115
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
117
116
|
next if e.empty?
|
118
117
|
|
@@ -235,7 +234,7 @@ module Sisimai::Bite::Email
|
|
235
234
|
MessagesOf.each_key do |r|
|
236
235
|
# Check each regular expression
|
237
236
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
238
|
-
e['reason'] = r
|
237
|
+
e['reason'] = r
|
239
238
|
break
|
240
239
|
end
|
241
240
|
end
|
@@ -12,12 +12,18 @@ module Sisimai::Bite::Email
|
|
12
12
|
rfc822: ['Content-Type: message/rfc822'],
|
13
13
|
}.freeze
|
14
14
|
ReFailures = {
|
15
|
-
userunknown
|
15
|
+
'userunknown' => %r{(?:
|
16
|
+
[ ]User[ ][(].+[@].+[)][ ]unknown[.][ ]
|
17
|
+
|550[ ]Unknown[ ]user[ ][^ ]+[@][^ ]+
|
18
|
+
|550[ ][<].+?[@].+?[>][.]+[ ]User[ ]not[ ]exist
|
19
|
+
|No[ ]such[ ]user
|
20
|
+
)
|
21
|
+
}x,
|
16
22
|
}.freeze
|
17
23
|
|
18
24
|
def description; return 'McAfee Email Appliance'; end
|
19
25
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
20
|
-
def headerlist; return [
|
26
|
+
def headerlist; return %w[x-nai-header]; end
|
21
27
|
|
22
28
|
# Parse bounce messages from McAfee Email Appliance
|
23
29
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -35,6 +41,8 @@ module Sisimai::Bite::Email
|
|
35
41
|
return nil unless mhead['x-nai-header'].start_with?('Modified by McAfee ')
|
36
42
|
return nil unless mhead['subject'] == 'Delivery Status'
|
37
43
|
|
44
|
+
require 'sisimai/rfc1894'
|
45
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
38
46
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
39
47
|
hasdivided = mbody.split("\n")
|
40
48
|
havepassed = ['']
|
@@ -67,7 +75,7 @@ module Sisimai::Bite::Email
|
|
67
75
|
end
|
68
76
|
|
69
77
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
70
|
-
#
|
78
|
+
# Inside of the original message part
|
71
79
|
if e.empty?
|
72
80
|
blanklines += 1
|
73
81
|
break if blanklines > 1
|
@@ -75,7 +83,7 @@ module Sisimai::Bite::Email
|
|
75
83
|
end
|
76
84
|
rfc822list << e
|
77
85
|
else
|
78
|
-
#
|
86
|
+
# Error message part
|
79
87
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
80
88
|
next if e.empty?
|
81
89
|
|
@@ -101,28 +109,26 @@ module Sisimai::Bite::Email
|
|
101
109
|
diagnostic = cv[2]
|
102
110
|
recipients += 1
|
103
111
|
|
104
|
-
elsif
|
105
|
-
#
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
112
|
+
elsif f = Sisimai::RFC1894.match(e)
|
113
|
+
# "e" matched with any field defined in RFC3464
|
114
|
+
o = Sisimai::RFC1894.field(e)
|
115
|
+
unless o
|
116
|
+
# Fallback code for empty value or invalid formatted value
|
117
|
+
# - Original-Recipient: <kijitora@example.co.jp>
|
118
|
+
if cv = e.match(/\AOriginal-Recipient:[ ]*([^ ]+)\z/)
|
119
|
+
v['alias'] = Sisimai::Address.s3s4(cv[1])
|
120
|
+
end
|
121
|
+
next
|
122
|
+
end
|
123
|
+
next unless fieldtable.key?(o[0])
|
124
|
+
v[fieldtable[o[0]]] = o[2]
|
111
125
|
|
112
|
-
elsif cv = e.match(/\ARemote-MTA:[ ]*(.+)\z/)
|
113
|
-
# Remote-MTA: 192.0.2.192
|
114
|
-
v['rhost'] = cv[1].downcase
|
115
126
|
else
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
122
|
-
# Continued line of the value of Diagnostic-Code header
|
123
|
-
v['diagnosis'] << ' ' << cv[1]
|
124
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
125
|
-
end
|
127
|
+
# Continued line of the value of Diagnostic-Code field
|
128
|
+
next unless p.start_with?('Diagnostic-Code:')
|
129
|
+
next unless cv = e.match(/\A[ \t]+(.+)\z/)
|
130
|
+
v['diagnosis'] << ' ' << cv[1]
|
131
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
126
132
|
end
|
127
133
|
end
|
128
134
|
end
|
@@ -135,7 +141,7 @@ module Sisimai::Bite::Email
|
|
135
141
|
ReFailures.each_key do |r|
|
136
142
|
# Verify each regular expression of session errors
|
137
143
|
next unless e['diagnosis'] =~ ReFailures[r]
|
138
|
-
e['reason'] = r
|
144
|
+
e['reason'] = r
|
139
145
|
break
|
140
146
|
end
|
141
147
|
e.each_key { |a| e[a] ||= '' }
|
@@ -13,8 +13,8 @@ module Sisimai::Bite::Email
|
|
13
13
|
rfc822: ['Content-Type: text/rfc822-headers'],
|
14
14
|
}.freeze
|
15
15
|
ReFailures = {
|
16
|
-
userunknown
|
17
|
-
securityerror
|
16
|
+
'userunknown' => %r/(?:542 .+ Rejected|No such user)/,
|
17
|
+
'securityerror' => %r/Please turn on SMTP Authentication in your mail client/,
|
18
18
|
}.freeze
|
19
19
|
|
20
20
|
def description; return 'Symantec.cloud http://www.messagelabs.com'; end
|
@@ -25,7 +25,7 @@ module Sisimai::Bite::Email
|
|
25
25
|
# X-StarScan-Received:
|
26
26
|
# X-StarScan-Version: 6.12.5; banners=-,-,-
|
27
27
|
# X-VirusChecked: Checked
|
28
|
-
def headerlist; return [
|
28
|
+
def headerlist; return %w[x-msg-ref]; end
|
29
29
|
|
30
30
|
# Parse bounce messages from Symantec.cloud(MessageLabs)
|
31
31
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -43,6 +43,10 @@ module Sisimai::Bite::Email
|
|
43
43
|
return nil unless mhead['from'].include?('MAILER-DAEMON@messagelabs.com')
|
44
44
|
return nil unless mhead['subject'].start_with?('Mail Delivery Failure')
|
45
45
|
|
46
|
+
require 'sisimai/rfc1894'
|
47
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
48
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
49
|
+
|
46
50
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
47
51
|
hasdivided = mbody.split("\n")
|
48
52
|
havepassed = ['']
|
@@ -51,11 +55,6 @@ module Sisimai::Bite::Email
|
|
51
55
|
readcursor = 0 # (Integer) Points the current cursor position
|
52
56
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
53
57
|
commandset = [] # (Array) ``in reply to * command'' list
|
54
|
-
connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
|
55
|
-
connheader = {
|
56
|
-
'date' => '', # The value of Arrival-Date header
|
57
|
-
'lhost' => '', # The value of Reporting-MTA header
|
58
|
-
}
|
59
58
|
v = nil
|
60
59
|
|
61
60
|
while e = hasdivided.shift do
|
@@ -64,7 +63,7 @@ module Sisimai::Bite::Email
|
|
64
63
|
p = havepassed[-2]
|
65
64
|
|
66
65
|
if readcursor == 0
|
67
|
-
# Beginning of the bounce message or delivery
|
66
|
+
# Beginning of the bounce message or message/delivery-status part
|
68
67
|
if e.start_with?(StartingOf[:message][0])
|
69
68
|
readcursor |= Indicators[:deliverystatus]
|
70
69
|
next
|
@@ -72,7 +71,7 @@ module Sisimai::Bite::Email
|
|
72
71
|
end
|
73
72
|
|
74
73
|
if (readcursor & Indicators[:'message-rfc822']) == 0
|
75
|
-
# Beginning of the original message part
|
74
|
+
# Beginning of the original message part(message/rfc822)
|
76
75
|
if e == StartingOf[:rfc822][0]
|
77
76
|
readcursor |= Indicators[:'message-rfc822']
|
78
77
|
next
|
@@ -80,7 +79,7 @@ module Sisimai::Bite::Email
|
|
80
79
|
end
|
81
80
|
|
82
81
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
83
|
-
#
|
82
|
+
# message/rfc822 OR text/rfc822-headers part
|
84
83
|
if e.empty?
|
85
84
|
blanklines += 1
|
86
85
|
break if blanklines > 1
|
@@ -88,96 +87,58 @@ module Sisimai::Bite::Email
|
|
88
87
|
end
|
89
88
|
rfc822list << e
|
90
89
|
else
|
91
|
-
#
|
90
|
+
# message/delivery-status part
|
92
91
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
93
92
|
next if e.empty?
|
94
93
|
|
95
|
-
if
|
96
|
-
#
|
97
|
-
|
98
|
-
# I was unable to deliver your message to the following addresses:
|
99
|
-
#
|
100
|
-
# maria@dest.example.net
|
101
|
-
#
|
102
|
-
# Reason: 550 maria@dest.example.net... No such user
|
103
|
-
#
|
104
|
-
# The message subject was: Re: BOAS FESTAS!
|
105
|
-
# The message date was: Tue, 23 Dec 2014 20:39:24 +0000
|
106
|
-
# The message identifier was: DB/3F-17375-60D39495
|
107
|
-
# The message reference was: server-5.tower-143.messagelabs.com!1419367172!32=
|
108
|
-
# 691968!1
|
109
|
-
#
|
110
|
-
# Please do not reply to this email as it is sent from an unattended mailbox.
|
111
|
-
# Please visit www.messagelabs.com/support for more details
|
112
|
-
# about this error message and instructions to resolve this issue.
|
113
|
-
#
|
114
|
-
#
|
115
|
-
# --b0Nvs+XKfKLLRaP/Qo8jZhQPoiqeWi3KWPXMgw==
|
116
|
-
# Content-Type: message/delivery-status
|
117
|
-
#
|
118
|
-
# Reporting-MTA: dns; server-15.bemta-3.messagelabs.com
|
119
|
-
# Arrival-Date: Tue, 23 Dec 2014 20:39:34 +0000
|
120
|
-
#
|
121
|
-
# Action: failed
|
122
|
-
# Status: 5.0.0
|
123
|
-
# Last-Attempt-Date: Tue, 23 Dec 2014 20:39:35 +0000
|
124
|
-
# Remote-MTA: dns; mail.dest.example.net
|
125
|
-
# Diagnostic-Code: smtp; 550 maria@dest.example.net... No such user
|
126
|
-
# Final-Recipient: rfc822; maria@dest.example.net
|
94
|
+
if f = Sisimai::RFC1894.match(e)
|
95
|
+
# "e" matched with any field defined in RFC3464
|
96
|
+
next unless o = Sisimai::RFC1894.field(e)
|
127
97
|
v = dscontents[-1]
|
128
98
|
|
129
|
-
if
|
130
|
-
# Final-Recipient: rfc822;
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
v
|
99
|
+
if o[-1] == 'addr'
|
100
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
101
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
102
|
+
if o[0] == 'final-recipient'
|
103
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
104
|
+
if v['recipient']
|
105
|
+
# There are multiple recipient addresses in the message body.
|
106
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
107
|
+
v = dscontents[-1]
|
108
|
+
end
|
109
|
+
v['recipient'] = o[2]
|
110
|
+
recipients += 1
|
111
|
+
else
|
112
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
113
|
+
v['alias'] = o[2]
|
135
114
|
end
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
# Action: failed
|
141
|
-
v['action'] = cv[1].downcase
|
142
|
-
|
143
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
144
|
-
# Status: 5.0.0
|
145
|
-
v['status'] = cv[1]
|
115
|
+
elsif o[-1] == 'code'
|
116
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
117
|
+
v['spec'] = o[1]
|
118
|
+
v['diagnosis'] = o[2]
|
146
119
|
else
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
# Continued line of the value of Diagnostic-Code header
|
154
|
-
v['diagnosis'] << ' ' << cv[1]
|
155
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
156
|
-
end
|
120
|
+
# Other DSN fields defined in RFC3464
|
121
|
+
next unless fieldtable.key?(o[0])
|
122
|
+
v[fieldtable[o[0]]] = o[2]
|
123
|
+
|
124
|
+
next unless f == 1
|
125
|
+
permessage[fieldtable[o[0]]] = o[2]
|
157
126
|
end
|
158
127
|
else
|
159
|
-
#
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
connheader['lhost'] = cv[1].downcase
|
165
|
-
connvalues += 1
|
166
|
-
|
167
|
-
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
168
|
-
# Arrival-Date: Tue, 23 Dec 2014 20:39:34 +0000
|
169
|
-
next unless connheader['date'].empty?
|
170
|
-
connheader['date'] = cv[1]
|
171
|
-
connvalues += 1
|
172
|
-
end
|
128
|
+
# Continued line of the value of Diagnostic-Code field
|
129
|
+
next unless p.start_with?('Diagnostic-Code:')
|
130
|
+
next unless cv = e.match(/\A[ \t]+(.+)\z/)
|
131
|
+
v['diagnosis'] << ' ' << cv[1]
|
132
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
173
133
|
end
|
174
|
-
end
|
134
|
+
end # End of message/delivery-status
|
175
135
|
end
|
176
136
|
return nil unless recipients > 0
|
177
137
|
|
178
138
|
dscontents.each do |e|
|
179
139
|
# Set default values if each value is empty.
|
180
|
-
|
140
|
+
e['lhost'] ||= permessage['rhost']
|
141
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
181
142
|
e['command'] = commandset.shift || ''
|
182
143
|
e['agent'] = self.smtpagent
|
183
144
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
@@ -185,7 +146,7 @@ module Sisimai::Bite::Email
|
|
185
146
|
ReFailures.each_key do |r|
|
186
147
|
# Verify each regular expression of session errors
|
187
148
|
next unless e['diagnosis'] =~ ReFailures[r]
|
188
|
-
e['reason'] = r
|
149
|
+
e['reason'] = r
|
189
150
|
break
|
190
151
|
end
|
191
152
|
end
|