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
@@ -10,7 +10,7 @@ module Sisimai::Bite::Email
|
|
10
10
|
Indicators = Sisimai::Bite::Email.INDICATORS
|
11
11
|
StartingOf = { message: ['This report relates to a message you sent with the following header fields:'] }.freeze
|
12
12
|
MarkingsOf = { rfc822: %r!\A(?:Content-type:[ ]*message/rfc822|Return-path:[ ]*)! }.freeze
|
13
|
-
MessagesOf = { hostunknown
|
13
|
+
MessagesOf = { 'hostunknown' => ['Illegal host/domain name found'] }.freeze
|
14
14
|
|
15
15
|
def description; return 'Oracle Communications Messaging Server'; end
|
16
16
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
@@ -60,7 +60,7 @@ module Sisimai::Bite::Email
|
|
60
60
|
end
|
61
61
|
|
62
62
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
63
|
-
#
|
63
|
+
# Inside of the original message part
|
64
64
|
if e.empty?
|
65
65
|
blanklines += 1
|
66
66
|
break if blanklines > 1
|
@@ -68,7 +68,7 @@ module Sisimai::Bite::Email
|
|
68
68
|
end
|
69
69
|
rfc822list << e
|
70
70
|
else
|
71
|
-
#
|
71
|
+
# Error message part
|
72
72
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
73
73
|
next if e.empty?
|
74
74
|
|
@@ -126,12 +126,11 @@ module Sisimai::Bite::Email
|
|
126
126
|
sessionlog = cv[2] # smtp session
|
127
127
|
v['rhost'] = remotehost
|
128
128
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
129
|
+
# The value does not include ".", use IP address instead.
|
130
|
+
# (TCP|17.111.174.67|47323|192.0.2.225|25)
|
131
|
+
next unless cv = sessionlog.match(/\A[(]TCP|(.+)|\d+|(.+)|\d+[)]/)
|
132
|
+
v['lhost'] = cv[1]
|
133
|
+
v['rhost'] = cv[2] unless remotehost =~ /[^.]+[.][^.]+/
|
135
134
|
else
|
136
135
|
# Original-envelope-id: 0NFC009FLKOUVMA0@mr21p30im-asmtp004.me.com
|
137
136
|
# Reporting-MTA: dns;mr21p30im-asmtp004.me.com (tcp-daemon)
|
@@ -172,7 +171,7 @@ module Sisimai::Bite::Email
|
|
172
171
|
MessagesOf.each_key do |r|
|
173
172
|
# Verify each regular expression of session errors
|
174
173
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
175
|
-
e['reason'] = r
|
174
|
+
e['reason'] = r
|
176
175
|
break
|
177
176
|
end
|
178
177
|
e.each_key { |a| e[a] ||= '' }
|
@@ -17,7 +17,7 @@ module Sisimai::Bite::Email
|
|
17
17
|
|
18
18
|
def description; return 'Digital Arts m-FILTER'; end
|
19
19
|
def smtpagent; return 'Email::mFILTER'; end
|
20
|
-
def headerlist; return [
|
20
|
+
def headerlist; return %w[x-mailer]; end
|
21
21
|
|
22
22
|
# Parse bounce messages from Digital Arts m-FILTER
|
23
23
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -59,7 +59,7 @@ module Sisimai::Bite::Email
|
|
59
59
|
end
|
60
60
|
|
61
61
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
62
|
-
#
|
62
|
+
# Inside of the original message part
|
63
63
|
if e.empty?
|
64
64
|
blanklines += 1
|
65
65
|
break if blanklines > 1
|
@@ -67,7 +67,7 @@ module Sisimai::Bite::Email
|
|
67
67
|
end
|
68
68
|
rfc822list << e
|
69
69
|
else
|
70
|
-
#
|
70
|
+
# Error message part
|
71
71
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
72
72
|
next if e.empty?
|
73
73
|
|
@@ -125,21 +125,21 @@ module Sisimai::Bite::Email
|
|
125
125
|
return nil unless recipients > 0
|
126
126
|
|
127
127
|
dscontents.each do |e|
|
128
|
-
|
129
|
-
# Get localhost and remote host name from Received header.
|
130
|
-
rheads = mhead['received']
|
131
|
-
rhosts = Sisimai::RFC5322.received(rheads[-1])
|
132
|
-
|
133
|
-
e['lhost'] ||= Sisimai::RFC5322.received(rheads[0]).shift
|
134
|
-
while ee = rhosts.shift do
|
135
|
-
# Avoid "... by m-FILTER"
|
136
|
-
next unless ee.include?('.')
|
137
|
-
e['rhost'] = ee
|
138
|
-
end
|
139
|
-
end
|
128
|
+
e.each_key { |a| e[a] ||= '' }
|
140
129
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
141
130
|
e['agent'] = self.smtpagent
|
142
|
-
|
131
|
+
|
132
|
+
# Get localhost and remote host name from Received header.
|
133
|
+
next if mhead['received'].empty?
|
134
|
+
rheads = mhead['received']
|
135
|
+
rhosts = Sisimai::RFC5322.received(rheads[-1])
|
136
|
+
|
137
|
+
e['lhost'] ||= Sisimai::RFC5322.received(rheads[0]).shift
|
138
|
+
while ee = rhosts.shift do
|
139
|
+
# Avoid "... by m-FILTER"
|
140
|
+
next unless ee.include?('.')
|
141
|
+
e['rhost'] = ee
|
142
|
+
end
|
143
143
|
end
|
144
144
|
|
145
145
|
rfc822part = Sisimai::RFC5322.weedout(rfc822list)
|
@@ -21,11 +21,11 @@ module Sisimai::Bite::Email
|
|
21
21
|
MessagesOf = {
|
22
22
|
# find exim/ -type f -exec grep 'message = US' {} /dev/null \;
|
23
23
|
# route.c:1158| DEBUG(D_uid) debug_printf("getpwnam() returned NULL (user not found)\n");
|
24
|
-
userunknown
|
24
|
+
'userunknown' => ['user not found'],
|
25
25
|
# transports/smtp.c:3524| addr->message = US"all host address lookups failed permanently";
|
26
26
|
# routers/dnslookup.c:331| addr->message = US"all relevant MX records point to non-existent hosts";
|
27
27
|
# route.c:1826| uschar *message = US"Unrouteable address";
|
28
|
-
hostunknown
|
28
|
+
'hostunknown' => [
|
29
29
|
'all host address lookups failed permanently',
|
30
30
|
'all relevant MX records point to non-existent hosts',
|
31
31
|
'Unrouteable address',
|
@@ -33,10 +33,10 @@ module Sisimai::Bite::Email
|
|
33
33
|
# transports/appendfile.c:2567| addr->user_message = US"mailbox is full";
|
34
34
|
# transports/appendfile.c:3049| addr->message = string_sprintf("mailbox is full "
|
35
35
|
# transports/appendfile.c:3050| "(quota exceeded while writing to file %s)", filename);
|
36
|
-
mailboxfull
|
36
|
+
'mailboxfull' => ['mailbox is full', 'error: quota exceed'],
|
37
37
|
# routers/dnslookup.c:328| addr->message = US"an MX or SRV record indicated no SMTP service";
|
38
38
|
# transports/smtp.c:3502| addr->message = US"no host found for existing SMTP connection";
|
39
|
-
notaccept
|
39
|
+
'notaccept' => [
|
40
40
|
'an MX or SRV record indicated no SMTP service',
|
41
41
|
'no host found for existing SMTP connection',
|
42
42
|
],
|
@@ -44,7 +44,7 @@ module Sisimai::Bite::Email
|
|
44
44
|
# parser.c:701| if(bracket_count++ > 5) FAILED(US"angle-brackets nested too deep");
|
45
45
|
# parser.c:738| FAILED(US"domain missing in source-routed address");
|
46
46
|
# parser.c:747| : string_sprintf("malformed address: %.32s may not follow %.*s",
|
47
|
-
syntaxerror
|
47
|
+
'syntaxerror' => [
|
48
48
|
'angle-brackets nested too deep',
|
49
49
|
'expected word or "<"',
|
50
50
|
'domain missing in source-routed address',
|
@@ -53,14 +53,14 @@ module Sisimai::Bite::Email
|
|
53
53
|
# deliver.c:5614| addr->message = US"delivery to file forbidden";
|
54
54
|
# deliver.c:5624| addr->message = US"delivery to pipe forbidden";
|
55
55
|
# transports/pipe.c:1156| addr->user_message = US"local delivery failed";
|
56
|
-
systemerror
|
56
|
+
'systemerror' => [
|
57
57
|
'delivery to file forbidden',
|
58
58
|
'delivery to pipe forbidden',
|
59
59
|
'local delivery failed',
|
60
60
|
'LMTP error after ',
|
61
61
|
],
|
62
62
|
# deliver.c:5425| new->message = US"Too many \"Received\" headers - suspected mail loop";
|
63
|
-
contenterror
|
63
|
+
'contenterror' => ['Too many "Received" headers'],
|
64
64
|
}.freeze
|
65
65
|
DelayedFor = [
|
66
66
|
'retry timeout exceeded',
|
@@ -77,7 +77,7 @@ module Sisimai::Bite::Email
|
|
77
77
|
# X-MX-Bounce: mta/src/queue/bounce
|
78
78
|
# X-MXL-NoteHash: ffffffffffffffff-0000000000000000000000000000000000000000
|
79
79
|
# X-MXL-Hash: 4c9d4d411993da17-bbd4212b6c887f6c23bab7db4bd87ef5edc00758
|
80
|
-
def headerlist; return [
|
80
|
+
def headerlist; return %w[x-mxl-notehash x-mxl-hash x-mx-bounce]; end
|
81
81
|
|
82
82
|
# Parse bounce messages from MXLogic
|
83
83
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -132,7 +132,7 @@ module Sisimai::Bite::Email
|
|
132
132
|
end
|
133
133
|
|
134
134
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
135
|
-
#
|
135
|
+
# Inside of the original message part
|
136
136
|
if e.empty?
|
137
137
|
blanklines += 1
|
138
138
|
break if blanklines > 1
|
@@ -140,7 +140,7 @@ module Sisimai::Bite::Email
|
|
140
140
|
end
|
141
141
|
rfc822list << e
|
142
142
|
else
|
143
|
-
#
|
143
|
+
# Error message part
|
144
144
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
145
145
|
next if e.empty?
|
146
146
|
|
@@ -222,7 +222,7 @@ module Sisimai::Bite::Email
|
|
222
222
|
MessagesOf.each_key do |r|
|
223
223
|
# Check each regular expression
|
224
224
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
225
|
-
e['reason'] = r
|
225
|
+
e['reason'] = r
|
226
226
|
break
|
227
227
|
end
|
228
228
|
|
@@ -12,7 +12,7 @@ module Sisimai::Bite::Email
|
|
12
12
|
rfc822: ['------- Returned Message '],
|
13
13
|
}.freeze
|
14
14
|
MessagesOf = {
|
15
|
-
userunknown
|
15
|
+
'userunknown' => [
|
16
16
|
'User not listed in public Name & Address Book',
|
17
17
|
'ディレクトリのリストにありません',
|
18
18
|
],
|
@@ -74,7 +74,7 @@ module Sisimai::Bite::Email
|
|
74
74
|
end
|
75
75
|
|
76
76
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
77
|
-
#
|
77
|
+
# Inside of the original message part
|
78
78
|
if e.empty?
|
79
79
|
blanklines += 1
|
80
80
|
break if blanklines > 1
|
@@ -82,7 +82,7 @@ module Sisimai::Bite::Email
|
|
82
82
|
end
|
83
83
|
rfc822list << e
|
84
84
|
else
|
85
|
-
#
|
85
|
+
# Error message part
|
86
86
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
87
87
|
|
88
88
|
# ------- Failure Reasons --------
|
@@ -150,9 +150,8 @@ module Sisimai::Bite::Email
|
|
150
150
|
MessagesOf.each_key do |r|
|
151
151
|
# Check each regular expression of Notes error messages
|
152
152
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
153
|
-
e['reason'] = r
|
154
|
-
|
155
|
-
e['status'] = pseudostatus unless pseudostatus.empty?
|
153
|
+
e['reason'] = r
|
154
|
+
e['status'] = Sisimai::SMTP::Status.code(r.to_s) || ''
|
156
155
|
break
|
157
156
|
end
|
158
157
|
e.each_key { |a| e[a] ||= '' }
|
@@ -65,14 +65,15 @@ module Sisimai::Bite::Email
|
|
65
65
|
# X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Apr 2015 23:34:45.6789 (JST)
|
66
66
|
# X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted
|
67
67
|
# X-MS-Exchange-Transport-CrossTenantHeadersStamped: ...
|
68
|
-
return [
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
68
|
+
return %w[
|
69
|
+
content-language
|
70
|
+
x-ms-exchange-message-is-ndr
|
71
|
+
x-microsoft-antispam-prvs
|
72
|
+
x-exchange-antispam-report-test
|
73
|
+
x-exchange-antispam-report-cfa-test
|
74
|
+
x-ms-exchange-crosstenant-originalarrivaltime
|
75
|
+
x-ms-exchange-crosstenant-fromentityheader
|
76
|
+
x-ms-exchange-transport-crosstenantheadersstamped
|
76
77
|
]
|
77
78
|
end
|
78
79
|
|
@@ -105,6 +106,10 @@ module Sisimai::Bite::Email
|
|
105
106
|
end
|
106
107
|
return nil if match < 2
|
107
108
|
|
109
|
+
require 'sisimai/rfc1894'
|
110
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
111
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
112
|
+
|
108
113
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
109
114
|
hasdivided = mbody.split("\n")
|
110
115
|
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
@@ -134,7 +139,7 @@ module Sisimai::Bite::Email
|
|
134
139
|
end
|
135
140
|
|
136
141
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
137
|
-
#
|
142
|
+
# Inside of the original message part
|
138
143
|
if e.empty?
|
139
144
|
blanklines += 1
|
140
145
|
break if blanklines > 1
|
@@ -142,7 +147,7 @@ module Sisimai::Bite::Email
|
|
142
147
|
end
|
143
148
|
rfc822list << e
|
144
149
|
else
|
145
|
-
#
|
150
|
+
# Error message part
|
146
151
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
147
152
|
next if e.empty?
|
148
153
|
|
@@ -168,35 +173,14 @@ module Sisimai::Bite::Email
|
|
168
173
|
else
|
169
174
|
if endoferror
|
170
175
|
# After "Original message headers:"
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
v['action'] = cv[1].downcase
|
180
|
-
|
181
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
182
|
-
# Status:5.2.0
|
183
|
-
v['status'] = cv[1]
|
184
|
-
|
185
|
-
elsif cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
186
|
-
# Reporting-MTA: dns;BLU004-OMC3S13.hotmail.example.com
|
187
|
-
connheader['lhost'] = cv[1].downcase
|
188
|
-
|
189
|
-
elsif cv = e.match(/\AReceived-From-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
190
|
-
# Reporting-MTA: dns;BLU004-OMC3S13.hotmail.example.com
|
191
|
-
connheader['rhost'] = cv[1].downcase
|
192
|
-
|
193
|
-
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
194
|
-
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
195
|
-
next if connheader['date']
|
196
|
-
connheader['date'] = cv[1]
|
197
|
-
else
|
198
|
-
htmlbegins = true if e.start_with?('<html>')
|
199
|
-
end
|
176
|
+
next unless f = Sisimai::RFC1894.match(e)
|
177
|
+
next unless o = Sisimai::RFC1894.field(e)
|
178
|
+
next unless fieldtable.key?(o[0])
|
179
|
+
next if o[0] =~ /\A(?:diagnostic-code|final-recipient)\z/
|
180
|
+
v[fieldtable[o[0]]] = o[2]
|
181
|
+
|
182
|
+
next unless f == 1
|
183
|
+
permessage[fieldtable[o[0]]] = o[2]
|
200
184
|
else
|
201
185
|
if e == StartingOf[:error][0]
|
202
186
|
# Diagnostic information for administrators:
|
@@ -222,7 +206,7 @@ module Sisimai::Bite::Email
|
|
222
206
|
|
223
207
|
dscontents.each do |e|
|
224
208
|
# Set default values if each value is empty.
|
225
|
-
|
209
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
226
210
|
|
227
211
|
e['agent'] = self.smtpagent
|
228
212
|
e['status'] ||= ''
|
@@ -230,8 +214,7 @@ module Sisimai::Bite::Email
|
|
230
214
|
|
231
215
|
if e['status'].empty? || e['status'].end_with?('.0.0')
|
232
216
|
# There is no value of Status header or the value is 5.0.0, 4.0.0
|
233
|
-
|
234
|
-
e['status'] = pseudostatus unless pseudostatus.empty?
|
217
|
+
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
|
235
218
|
end
|
236
219
|
|
237
220
|
ReCommands.each_key do |p|
|
@@ -38,17 +38,17 @@ module Sisimai::Bite::Email
|
|
38
38
|
}.freeze
|
39
39
|
MessagesOf = {
|
40
40
|
# smtpd/queue.c:221| envelope_set_errormsg(&evp, "Envelope expired");
|
41
|
-
expired
|
41
|
+
'expired' => ['Envelope expired'],
|
42
42
|
# smtpd/mta.c:976| relay->failstr = "Invalid domain name";
|
43
43
|
# smtpd/mta.c:980| relay->failstr = "Domain does not exist";
|
44
|
-
hostunknown
|
44
|
+
'hostunknown' => [
|
45
45
|
'Invalid domain name',
|
46
46
|
'Domain does not exist',
|
47
47
|
],
|
48
48
|
# smtp/mta.c:1085| relay->failstr = "Destination seem to reject all mails";
|
49
|
-
notaccept
|
49
|
+
'notaccept' => ['Destination seem to reject all mails'],
|
50
50
|
# smtpd/mta.c:972| relay->failstr = "Temporary failure in MX lookup";
|
51
|
-
networkerror
|
51
|
+
'networkerror' => [
|
52
52
|
'Address family mismatch on destination MXs',
|
53
53
|
'All routes to destination blocked',
|
54
54
|
'bad DNS lookup error code',
|
@@ -62,7 +62,7 @@ module Sisimai::Bite::Email
|
|
62
62
|
'Temporary failure in MX lookup',
|
63
63
|
],
|
64
64
|
# smtpd/mta.c:1013| relay->failstr = "Could not retrieve credentials";
|
65
|
-
securityerror
|
65
|
+
'securityerror' => ['Could not retrieve credentials'],
|
66
66
|
}.freeze
|
67
67
|
|
68
68
|
def description; return 'OpenSMTPD'; end
|
@@ -111,7 +111,7 @@ module Sisimai::Bite::Email
|
|
111
111
|
end
|
112
112
|
|
113
113
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
114
|
-
#
|
114
|
+
# Inside of the original message part
|
115
115
|
if e.empty?
|
116
116
|
blanklines += 1
|
117
117
|
break if blanklines > 1
|
@@ -119,7 +119,7 @@ module Sisimai::Bite::Email
|
|
119
119
|
end
|
120
120
|
rfc822list << e
|
121
121
|
else
|
122
|
-
#
|
122
|
+
# Error message part
|
123
123
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
124
124
|
next if e.empty?
|
125
125
|
|
@@ -157,7 +157,7 @@ module Sisimai::Bite::Email
|
|
157
157
|
MessagesOf.each_key do |r|
|
158
158
|
# Verify each regular expression of session errors
|
159
159
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
160
|
-
e['reason'] = r
|
160
|
+
e['reason'] = r
|
161
161
|
break
|
162
162
|
end
|
163
163
|
e.each_key { |a| e[a] ||= '' }
|
@@ -13,8 +13,8 @@ module Sisimai::Bite::Email
|
|
13
13
|
rfc822: ['Content-Type: message/rfc822'],
|
14
14
|
}.freeze
|
15
15
|
MessagesOf = {
|
16
|
-
hostunknown
|
17
|
-
userunknown
|
16
|
+
'hostunknown' => ['The mail could not be delivered to the recipient because the domain is not reachable'],
|
17
|
+
'userunknown' => ['Requested action not taken: mailbox unavailable'],
|
18
18
|
}.freeze
|
19
19
|
|
20
20
|
def description; return 'Microsoft Outlook.com: https://www.outlook.com/'; end
|
@@ -22,7 +22,7 @@ module Sisimai::Bite::Email
|
|
22
22
|
|
23
23
|
# X-Message-Delivery: Vj0xLjE7RD0wO0dEPTA7U0NMPTk7bD0xO3VzPTE=
|
24
24
|
# X-Message-Info: AuEzbeVr9u5fkDpn2vR5iCu5wb6HBeY4iruBjnutBzpStnUabbM...
|
25
|
-
def headerlist; return [
|
25
|
+
def headerlist; return %w[x-message-delivery x-message-info]; end
|
26
26
|
|
27
27
|
# Parse bounce messages from Microsoft Outlook.com
|
28
28
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -44,6 +44,10 @@ module Sisimai::Bite::Email
|
|
44
44
|
match += 1 if mhead['received'].any? { |a| a.include?('.hotmail.com') }
|
45
45
|
return nil if match < 2
|
46
46
|
|
47
|
+
require 'sisimai/rfc1894'
|
48
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
49
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
50
|
+
|
47
51
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
48
52
|
hasdivided = mbody.split("\n")
|
49
53
|
havepassed = ['']
|
@@ -51,11 +55,6 @@ module Sisimai::Bite::Email
|
|
51
55
|
blanklines = 0 # (Integer) The number of blank lines
|
52
56
|
readcursor = 0 # (Integer) Points the current cursor position
|
53
57
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
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,76 +87,59 @@ 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
|
-
# Delivery to the following recipients failed.
|
99
|
-
#
|
100
|
-
# kijitora@example.jp
|
101
|
-
#
|
102
|
-
# Final-Recipient: rfc822;kijitora@example.jp
|
103
|
-
# Action: failed
|
104
|
-
# Status: 5.2.2
|
105
|
-
# Diagnostic-Code: smtp;550 5.2.2 <kijitora@example.jp>... Mailbox Full
|
94
|
+
if f = Sisimai::RFC1894.match(e)
|
95
|
+
# "e" matched with any field defined in RFC3464
|
96
|
+
next unless o = Sisimai::RFC1894.field(e)
|
106
97
|
v = dscontents[-1]
|
107
98
|
|
108
|
-
if
|
109
|
-
# Final-Recipient: rfc822;kijitora@example.jp
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
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]
|
114
114
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
# Action: failed
|
120
|
-
v['action'] = cv[1].downcase
|
121
|
-
|
122
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
123
|
-
# Status:5.2.0
|
124
|
-
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]
|
125
119
|
else
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
# Continued line of the value of Diagnostic-Code header
|
133
|
-
v['diagnosis'] << ' ' << cv[1]
|
134
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
135
|
-
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]
|
136
126
|
end
|
137
127
|
else
|
138
|
-
#
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
next unless connheader['lhost'].empty?
|
144
|
-
connheader['lhost'] = cv[1].downcase
|
145
|
-
connvalues += 1
|
146
|
-
|
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
|
-
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
|
153
133
|
end
|
154
|
-
end
|
134
|
+
end # End of message/delivery-status
|
155
135
|
end
|
156
136
|
return nil unless recipients > 0
|
157
137
|
|
158
138
|
dscontents.each do |e|
|
159
139
|
# Set default values if each value is empty.
|
160
|
-
|
140
|
+
e['lhost'] ||= permessage['rhost']
|
141
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
142
|
+
|
161
143
|
e['agent'] = self.smtpagent
|
162
144
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
163
145
|
|
@@ -176,7 +158,7 @@ module Sisimai::Bite::Email
|
|
176
158
|
MessagesOf.each_key do |r|
|
177
159
|
# Verify each regular expression of session errors
|
178
160
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
179
|
-
e['reason'] = r
|
161
|
+
e['reason'] = r
|
180
162
|
break
|
181
163
|
end
|
182
164
|
end
|