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
@@ -19,7 +19,7 @@ module Sisimai::Bite::Email
|
|
19
19
|
# X-YMail-JAS: Pb65aU4VM1mei...
|
20
20
|
# X-YMail-OSG: bTIbpDEVM1lHz...
|
21
21
|
# X-Originating-IP: [192.0.2.9]
|
22
|
-
def headerlist; return [
|
22
|
+
def headerlist; return %w[x-ymailisg]; end
|
23
23
|
|
24
24
|
# Parse bounce messages from Yahoo! MAIL
|
25
25
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -62,7 +62,7 @@ module Sisimai::Bite::Email
|
|
62
62
|
end
|
63
63
|
|
64
64
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
65
|
-
#
|
65
|
+
# Inside of the original message part
|
66
66
|
if e.empty?
|
67
67
|
blanklines += 1
|
68
68
|
break if blanklines > 1
|
@@ -70,7 +70,7 @@ module Sisimai::Bite::Email
|
|
70
70
|
end
|
71
71
|
rfc822list << e
|
72
72
|
else
|
73
|
-
#
|
73
|
+
# Error message part
|
74
74
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
75
75
|
next if e.empty?
|
76
76
|
|
@@ -22,7 +22,7 @@ module Sisimai::Bite::Email
|
|
22
22
|
# X-Yandex-Forward: 10104c00ad0726da5f37374723b1e0c8
|
23
23
|
# X-Yandex-Queue-ID: 367D79E130D
|
24
24
|
# X-Yandex-Sender: rfc822; shironeko@yandex.example.com
|
25
|
-
def headerlist; return [
|
25
|
+
def headerlist; return %w[x-yandex-uniq]; end
|
26
26
|
|
27
27
|
# Parse bounce messages from Yandex.Mail
|
28
28
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -39,6 +39,10 @@ module Sisimai::Bite::Email
|
|
39
39
|
return nil unless mhead['x-yandex-uniq']
|
40
40
|
return nil unless mhead['from'] == 'mailer-daemon@yandex.ru'
|
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
|
havepassed = ['']
|
@@ -47,11 +51,6 @@ module Sisimai::Bite::Email
|
|
47
51
|
readcursor = 0 # (Integer) Points the current cursor position
|
48
52
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
49
53
|
commandset = [] # (Array) ``in reply to * command'' list
|
50
|
-
connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
|
51
|
-
connheader = {
|
52
|
-
'date' => '', # The value of Arrival-Date header
|
53
|
-
'lhost' => '', # The value of Reporting-MTA header
|
54
|
-
}
|
55
54
|
v = nil
|
56
55
|
|
57
56
|
while e = hasdivided.shift do
|
@@ -60,7 +59,7 @@ module Sisimai::Bite::Email
|
|
60
59
|
p = havepassed[-2]
|
61
60
|
|
62
61
|
if readcursor == 0
|
63
|
-
# Beginning of the bounce message or delivery
|
62
|
+
# Beginning of the bounce message or message/delivery-status part
|
64
63
|
if e.start_with?(StartingOf[:message][0])
|
65
64
|
readcursor |= Indicators[:deliverystatus]
|
66
65
|
next
|
@@ -68,7 +67,7 @@ module Sisimai::Bite::Email
|
|
68
67
|
end
|
69
68
|
|
70
69
|
if (readcursor & Indicators[:'message-rfc822']) == 0
|
71
|
-
# Beginning of the original message part
|
70
|
+
# Beginning of the original message part(message/rfc822)
|
72
71
|
if e.start_with?(StartingOf[:rfc822][0])
|
73
72
|
readcursor |= Indicators[:'message-rfc822']
|
74
73
|
next
|
@@ -76,7 +75,7 @@ module Sisimai::Bite::Email
|
|
76
75
|
end
|
77
76
|
|
78
77
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
79
|
-
#
|
78
|
+
# message/rfc822 OR text/rfc822-headers part
|
80
79
|
if e.empty?
|
81
80
|
blanklines += 1
|
82
81
|
break if blanklines > 1
|
@@ -84,98 +83,71 @@ module Sisimai::Bite::Email
|
|
84
83
|
end
|
85
84
|
rfc822list << e
|
86
85
|
else
|
87
|
-
#
|
86
|
+
# message/delivery-status part
|
88
87
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
89
88
|
next if e.empty?
|
90
89
|
|
91
|
-
if
|
92
|
-
#
|
93
|
-
|
94
|
-
# Action: failed
|
95
|
-
# Status: 5.1.1
|
96
|
-
# Remote-MTA: dns; mx.example.jp
|
97
|
-
# Diagnostic-Code: smtp; 550 5.1.1 <kijitora@example.jp>... User Unknown
|
98
|
-
#
|
99
|
-
# --367D79E130D.1417885948/forward1h.mail.yandex.net
|
100
|
-
# Content-Description: Undelivered Message
|
101
|
-
# Content-Type: message/rfc822
|
90
|
+
if f = Sisimai::RFC1894.match(e)
|
91
|
+
# "e" matched with any field defined in RFC3464
|
92
|
+
next unless o = Sisimai::RFC1894.field(e)
|
102
93
|
v = dscontents[-1]
|
103
94
|
|
104
|
-
if
|
95
|
+
if o[-1] == 'addr'
|
105
96
|
# Final-Recipient: rfc822; kijitora@example.jp
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
v
|
97
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
98
|
+
if o[0] == 'final-recipient'
|
99
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
100
|
+
if v['recipient']
|
101
|
+
# There are multiple recipient addresses in the message body.
|
102
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
103
|
+
v = dscontents[-1]
|
104
|
+
end
|
105
|
+
v['recipient'] = o[2]
|
106
|
+
recipients += 1
|
107
|
+
else
|
108
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
109
|
+
v['alias'] = o[2]
|
110
110
|
end
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
# Action: failed
|
116
|
-
v['action'] = cv[1]
|
117
|
-
|
118
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
119
|
-
# Status:5.2.0
|
120
|
-
v['status'] = cv[1]
|
121
|
-
|
122
|
-
elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
123
|
-
# Remote-MTA: DNS; mx.example.jp
|
124
|
-
v['rhost'] = cv[1].downcase
|
111
|
+
elsif o[-1] == 'code'
|
112
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
113
|
+
v['spec'] = o[1]
|
114
|
+
v['diagnosis'] = o[2]
|
125
115
|
else
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
133
|
-
# Continued line of the value of Diagnostic-Code header
|
134
|
-
v['diagnosis'] << ' ' << cv[1]
|
135
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
136
|
-
end
|
116
|
+
# Other DSN fields defined in RFC3464
|
117
|
+
next unless fieldtable.key?(o[0])
|
118
|
+
v[fieldtable[o[0]]] = o[2]
|
119
|
+
|
120
|
+
next unless f == 1
|
121
|
+
permessage[fieldtable[o[0]]] = o[2]
|
137
122
|
end
|
138
123
|
else
|
139
|
-
#
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
next unless connheader['lhost'].empty?
|
148
|
-
connheader['lhost'] = cv[1].downcase
|
149
|
-
connvalues += 1
|
150
|
-
|
151
|
-
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
152
|
-
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
153
|
-
next unless connheader['date'].empty?
|
154
|
-
connheader['date'] = cv[1]
|
155
|
-
connvalues += 1
|
124
|
+
# The line does not begin with a DSN field defined in RFC3464
|
125
|
+
if cv = e.match(/[ \t][(]in reply to .*([A-Z]{4}).*/)
|
126
|
+
# 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
|
127
|
+
commandset << cv[1]
|
128
|
+
|
129
|
+
elsif cv = e.match(/([A-Z]{4})[ \t]*.*command[)]\z/)
|
130
|
+
# to MAIL command)
|
131
|
+
commandset << cv[1]
|
156
132
|
else
|
157
|
-
#
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
commandset << cv[1]
|
163
|
-
|
164
|
-
elsif cv = e.match(/([A-Z]{4})[ \t]*.*command[)]\z/)
|
165
|
-
# to MAIL command)
|
166
|
-
commandset << cv[1]
|
167
|
-
end
|
133
|
+
# Continued line of the value of Diagnostic-Code field
|
134
|
+
next unless p.start_with?('Diagnostic-Code:')
|
135
|
+
next unless cv = e.match(/\A[ \t]+(.+)\z/)
|
136
|
+
v['diagnosis'] << ' ' << cv[1]
|
137
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
168
138
|
end
|
169
139
|
end
|
170
|
-
end
|
140
|
+
end # End of message/delivery-status
|
171
141
|
end
|
172
142
|
return nil unless recipients > 0
|
173
143
|
|
174
144
|
dscontents.each do |e|
|
175
145
|
# Set default values if each value is empty.
|
176
|
-
|
146
|
+
e['lhost'] ||= permessage['rhost']
|
147
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
148
|
+
|
177
149
|
e['command'] = commandset.shift || ''
|
178
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].
|
150
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
179
151
|
e['agent'] = self.smtpagent
|
180
152
|
end
|
181
153
|
|
@@ -11,7 +11,7 @@ module Sisimai::Bite::Email
|
|
11
11
|
message: ['This message was created automatically by mail delivery'],
|
12
12
|
rfc822: ['from mail.zoho.com by mx.zohomail.com'],
|
13
13
|
}.freeze
|
14
|
-
MessagesOf = { expired
|
14
|
+
MessagesOf = { 'expired' => ['Host not reachable'] }.freeze
|
15
15
|
|
16
16
|
def description; return 'Zoho Mail: https://www.zoho.com'; end
|
17
17
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
@@ -19,7 +19,7 @@ module Sisimai::Bite::Email
|
|
19
19
|
# X-ZohoMail: Si CHF_MF_NL SS_10 UW48 UB48 FMWL UW48 UB48 SGR3_1_09124_42
|
20
20
|
# X-Zoho-Virus-Status: 2
|
21
21
|
# X-Mailer: Zoho Mail
|
22
|
-
def headerlist; return [
|
22
|
+
def headerlist; return %w[x-zohomail]; end
|
23
23
|
|
24
24
|
# Parse bounce messages from Zoho Mail
|
25
25
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -69,7 +69,7 @@ module Sisimai::Bite::Email
|
|
69
69
|
end
|
70
70
|
|
71
71
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
72
|
-
#
|
72
|
+
# Inside of the original message part
|
73
73
|
if e.empty?
|
74
74
|
blanklines += 1
|
75
75
|
break if blanklines > 1
|
@@ -77,7 +77,7 @@ module Sisimai::Bite::Email
|
|
77
77
|
end
|
78
78
|
rfc822list << e
|
79
79
|
else
|
80
|
-
#
|
80
|
+
# Error message part
|
81
81
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
82
82
|
next if e.empty?
|
83
83
|
|
@@ -133,12 +133,12 @@ module Sisimai::Bite::Email
|
|
133
133
|
|
134
134
|
dscontents.each do |e|
|
135
135
|
e['agent'] = self.smtpagent
|
136
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].
|
136
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
137
137
|
|
138
138
|
MessagesOf.each_key do |r|
|
139
139
|
# Verify each regular expression of session errors
|
140
140
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
141
|
-
e['reason'] = r
|
141
|
+
e['reason'] = r
|
142
142
|
break
|
143
143
|
end
|
144
144
|
end
|
@@ -9,17 +9,17 @@ module Sisimai::Bite::JSON
|
|
9
9
|
|
10
10
|
# https://docs.aws.amazon.com/en_us/ses/latest/DeveloperGuide/notification-contents.html
|
11
11
|
BounceType = {
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
'Permanent' => {
|
13
|
+
'General' => '',
|
14
|
+
'NoEmail' => '',
|
15
|
+
'Suppressed' => '',
|
16
16
|
},
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
'Transient' => {
|
18
|
+
'General' => '',
|
19
|
+
'MailboxFull' => 'mailboxfull',
|
20
|
+
'MessageTooLarge' => 'mesgtoobig',
|
21
|
+
'ContentRejected' => '',
|
22
|
+
'AttachmentRejected' => '',
|
23
23
|
},
|
24
24
|
}.freeze
|
25
25
|
|
@@ -54,12 +54,12 @@ module Sisimai::Bite::JSON
|
|
54
54
|
break if e == '__END_OF_EMAIL_MESSAGE__'
|
55
55
|
|
56
56
|
# The line starts with " ", continued from !\n.
|
57
|
-
e
|
57
|
+
e.lstrip! if foldedline
|
58
58
|
foldedline = false
|
59
59
|
|
60
60
|
if e.end_with?('!')
|
61
61
|
# ... long long line ...![\n]
|
62
|
-
e
|
62
|
+
e.chomp!('!')
|
63
63
|
foldedline = true
|
64
64
|
end
|
65
65
|
jsonstring << e
|
@@ -107,15 +107,15 @@ module Sisimai::Bite::JSON
|
|
107
107
|
rfc822head = {} # (Hash) Check flags for headers in RFC822 part
|
108
108
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
109
109
|
labeltable = {
|
110
|
-
|
111
|
-
|
110
|
+
'Bounce' => 'bouncedRecipients',
|
111
|
+
'Complaint' => 'complainedRecipients',
|
112
112
|
}
|
113
113
|
v = nil
|
114
114
|
|
115
115
|
if %w[Bounce Complaint].index(argvs['notificationType'])
|
116
116
|
# { "notificationType":"Bounce", "bounce": { "bounceType":"Permanent",...
|
117
117
|
o = argvs[argvs['notificationType'].downcase].dup
|
118
|
-
r = o[labeltable[argvs['notificationType']
|
118
|
+
r = o[labeltable[argvs['notificationType']]] || []
|
119
119
|
|
120
120
|
while e = r.shift do
|
121
121
|
# 'bouncedRecipients' => [ { 'emailAddress' => 'bounce@si...' }, ... ]
|
@@ -152,13 +152,13 @@ module Sisimai::Bite::JSON
|
|
152
152
|
# 'reportingMTA' => 'dsn; a27-23.smtp-out.us-west-2.amazonses.com',
|
153
153
|
if cv = o['reportingMTA'].match(/\Adsn;[ ](.+)\z/) then v['lhost'] = cv[1] end
|
154
154
|
|
155
|
-
if BounceType.key?(o['bounceType']
|
156
|
-
BounceType[o['bounceType']
|
155
|
+
if BounceType.key?(o['bounceType']) &&
|
156
|
+
BounceType[o['bounceType']].key?(o['bounceSubType'])
|
157
157
|
# 'bounce' => {
|
158
158
|
# 'bounceType' => 'Permanent',
|
159
159
|
# 'bounceSubType' => 'General'
|
160
160
|
# },
|
161
|
-
v['reason'] = BounceType[o['bounceType']
|
161
|
+
v['reason'] = BounceType[o['bounceType']][o['bounceSubType']]
|
162
162
|
end
|
163
163
|
else
|
164
164
|
# 'complainedRecipients' => [ {
|
@@ -197,8 +197,8 @@ module Sisimai::Bite::JSON
|
|
197
197
|
v['recipient'] = e
|
198
198
|
v['lhost'] = o['reportingMTA'] || ''
|
199
199
|
v['diagnosis'] = o['smtpResponse'] || ''
|
200
|
-
v['status'] = Sisimai::SMTP::Status.find(v['diagnosis'])
|
201
|
-
v['replycode'] = Sisimai::SMTP::Reply.find(v['diagnosis'])
|
200
|
+
v['status'] = Sisimai::SMTP::Status.find(v['diagnosis']) || ''
|
201
|
+
v['replycode'] = Sisimai::SMTP::Reply.find(v['diagnosis']) || ''
|
202
202
|
v['reason'] = 'delivered'
|
203
203
|
v['action'] = 'deliverable'
|
204
204
|
|
@@ -103,8 +103,8 @@ module Sisimai::Bite::JSON
|
|
103
103
|
v['status'] = statuscode
|
104
104
|
end
|
105
105
|
|
106
|
-
v['status'] ||= Sisimai::SMTP::Status.find(diagnostic)
|
107
|
-
v['replycode'] ||= Sisimai::SMTP::Reply.find(diagnostic)
|
106
|
+
v['status'] ||= Sisimai::SMTP::Status.find(diagnostic) || ''
|
107
|
+
v['replycode'] ||= Sisimai::SMTP::Reply.find(diagnostic) || ''
|
108
108
|
v['diagnosis'] = argvs['reason'] || ''
|
109
109
|
v['agent'] = self.smtpagent
|
110
110
|
|
data/lib/sisimai/data.rb
CHANGED
@@ -41,7 +41,6 @@ module Sisimai
|
|
41
41
|
RetryIndex = Sisimai::Reason.retry
|
42
42
|
RFC822Head = Sisimai::RFC5322.HEADERFIELDS(:all)
|
43
43
|
AddrHeader = { addresser: RFC822Head[:addresser], recipient: RFC822Head[:recipient] }.freeze
|
44
|
-
ActionHead = { failure: 'failed', expired: 'delayed' }.freeze
|
45
44
|
|
46
45
|
# Constructor of Sisimai::Data
|
47
46
|
# @param [Hash] argvs Data
|
@@ -79,7 +78,7 @@ module Sisimai
|
|
79
78
|
@feedbacktype = argvs['feedbacktype'] || ''
|
80
79
|
@action = argvs['action'] || ''
|
81
80
|
@replycode = argvs['replycode'] || ''
|
82
|
-
@replycode = Sisimai::SMTP::Reply.find(argvs['diagnosticcode']) if @replycode.empty?
|
81
|
+
@replycode = Sisimai::SMTP::Reply.find(argvs['diagnosticcode']).to_s if @replycode.empty?
|
83
82
|
@softbounce = argvs['softbounce'] || ''
|
84
83
|
end
|
85
84
|
|
@@ -154,11 +153,11 @@ module Sisimai
|
|
154
153
|
# Detect email address from message/rfc822 part
|
155
154
|
fieldorder[:addresser].each do |f|
|
156
155
|
# Check each header in message/rfc822 part
|
157
|
-
|
158
|
-
next unless rfc822data
|
159
|
-
next if rfc822data[
|
156
|
+
next unless rfc822data.key?(f)
|
157
|
+
next unless rfc822data[f]
|
158
|
+
next if rfc822data[f].empty?
|
160
159
|
|
161
|
-
j = Sisimai::Address.find(rfc822data[
|
160
|
+
j = Sisimai::Address.find(rfc822data[f]) || []
|
162
161
|
next if j.empty?
|
163
162
|
p['addresser'] = j[0]
|
164
163
|
break
|
@@ -183,8 +182,8 @@ module Sisimai
|
|
183
182
|
# Date information did not exist in message/delivery-status part,...
|
184
183
|
RFC822Head[:date].each do |f|
|
185
184
|
# Get the value of Date header or other date related header.
|
186
|
-
next unless rfc822data[f
|
187
|
-
datevalues << rfc822data[f
|
185
|
+
next unless rfc822data[f]
|
186
|
+
datevalues << rfc822data[f]
|
188
187
|
end
|
189
188
|
|
190
189
|
# Set "date" getting from the value of "Date" in the bounce message
|
@@ -227,23 +226,25 @@ module Sisimai
|
|
227
226
|
%w[rhost lhost].each do |v|
|
228
227
|
p[v].delete!('[]()') # Remove square brackets and curly brackets from the host variable
|
229
228
|
p[v].sub!(/\A.+=/, '') # Remove string before "="
|
230
|
-
p[v].chomp!("\r")
|
229
|
+
p[v].chomp!("\r") if p[v].end_with?("\r") # Remove CR at the end of the value
|
231
230
|
|
232
231
|
# Check space character in each value and get the first element
|
233
232
|
p[v] = p[v].split(' ', 2).shift if p[v].include?(' ')
|
234
|
-
p[v].chomp!('.')
|
233
|
+
p[v].chomp!('.') if p[v].end_with?('.') # Remove "." at the end of the value
|
235
234
|
end
|
236
235
|
|
237
236
|
# Subject: header of the original message
|
238
237
|
p['subject'] = rfc822data['subject'] || ''
|
239
|
-
p['subject']
|
238
|
+
p['subject'].scrub!('?')
|
239
|
+
p['subject'].chomp!("\r") if p['subject'].end_with?("\r");
|
240
240
|
|
241
241
|
# The value of "List-Id" header
|
242
242
|
p['listid'] = rfc822data['list-id'] || ''
|
243
243
|
unless p['listid'].empty?
|
244
244
|
# Get the value of List-Id header like "List name <list-id@example.org>"
|
245
245
|
if cv = p['listid'].match(/\A.*([<].+[>]).*\z/) then p['listid'] = cv[1] end
|
246
|
-
p['listid']
|
246
|
+
p['listid'].delete!('<>')
|
247
|
+
p['listid'].chomp!("\r") if p['listid'].end_with?("\r")
|
247
248
|
p['listid'] = '' if p['listid'].include?(' ')
|
248
249
|
end
|
249
250
|
|
@@ -266,13 +267,13 @@ module Sisimai
|
|
266
267
|
vm = 0
|
267
268
|
re = nil
|
268
269
|
|
269
|
-
|
270
|
+
if vs
|
270
271
|
# How many times does the D.S.N. appeared
|
271
272
|
vm += p['diagnosticcode'].scan(/\b#{vs}\b/).size
|
272
273
|
p['deliverystatus'] = vs if vs =~ /\A[45][.][1-9][.][1-9]\z/
|
273
274
|
end
|
274
275
|
|
275
|
-
|
276
|
+
if vr
|
276
277
|
# How many times does the SMTP reply code appeared
|
277
278
|
vm += p['diagnosticcode'].scan(/\b#{vr}\b/).size
|
278
279
|
p['replycode'] ||= vr
|
@@ -292,26 +293,13 @@ module Sisimai
|
|
292
293
|
end
|
293
294
|
end
|
294
295
|
p['diagnostictype'] ||= 'X-UNIX' if p['reason'] == 'mailererror'
|
295
|
-
p['diagnostictype'] ||= 'SMTP' unless %w[feedback vacation].
|
296
|
+
p['diagnostictype'] ||= 'SMTP' unless %w[feedback vacation].include?(p['reason'])
|
296
297
|
|
297
298
|
# Check the value of SMTP command
|
298
|
-
p['smtpcommand'] = '' unless %w[EHLO HELO MAIL RCPT DATA QUIT].
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
# Action: expanded (to multi-recipient alias)
|
303
|
-
if cv = p['action'].match(/\A(.+?) .+/) then p['action'] = cv[1] end
|
304
|
-
|
305
|
-
unless %w[failed delayed delivered relayed expanded].index(p['action'])
|
306
|
-
# The value of "action" is not in the following values:
|
307
|
-
# "failed" / "delayed" / "delivered" / "relayed" / "expanded"
|
308
|
-
ActionHead.each_key do |q|
|
309
|
-
next unless p['action'] == q.to_s
|
310
|
-
p['action'] = ActionHead[q]
|
311
|
-
break
|
312
|
-
end
|
313
|
-
end
|
314
|
-
else
|
299
|
+
p['smtpcommand'] = '' unless %w[EHLO HELO MAIL RCPT DATA QUIT].include?(p['smtpcommand'])
|
300
|
+
|
301
|
+
if p['action'].empty?
|
302
|
+
# Check the value of "action"
|
315
303
|
if p['reason'] == 'expired'
|
316
304
|
# Action: delayed
|
317
305
|
p['action'] = 'delayed'
|
@@ -324,7 +312,7 @@ module Sisimai
|
|
324
312
|
o = Sisimai::Data.new(p)
|
325
313
|
next unless o.recipient
|
326
314
|
|
327
|
-
if o.reason.empty? || RetryIndex.
|
315
|
+
if o.reason.empty? || RetryIndex.key?(o.reason)
|
328
316
|
# Decide the reason of email bounce
|
329
317
|
r = ''
|
330
318
|
r = Sisimai::Rhost.get(o) if Sisimai::Rhost.match(o.rhost) # Remote host dependent error
|
@@ -333,7 +321,7 @@ module Sisimai
|
|
333
321
|
o.reason = r
|
334
322
|
end
|
335
323
|
|
336
|
-
if %w[delivered feedback vacation].
|
324
|
+
if %w[delivered feedback vacation].include?(o.reason)
|
337
325
|
# The value of reason is "vacation" or "feedback"
|
338
326
|
o.softbounce = -1
|
339
327
|
o.replycode = '' unless o.reason == 'delivered'
|
@@ -344,9 +332,8 @@ module Sisimai
|
|
344
332
|
|
345
333
|
if o.softbounce.to_s.empty?
|
346
334
|
# The value is not set yet
|
347
|
-
textasargv
|
348
|
-
softorhard
|
349
|
-
|
335
|
+
textasargv = (p['deliverystatus'] + ' ' + p['diagnosticcode']).lstrip
|
336
|
+
softorhard = Sisimai::SMTP::Error.soft_or_hard(o.reason, textasargv) || ''
|
350
337
|
o.softbounce = if softorhard.size > 0
|
351
338
|
# Returned value is "soft" or "hard"
|
352
339
|
(softorhard == 'soft') ? 1 : 0
|
@@ -363,7 +350,7 @@ module Sisimai
|
|
363
350
|
tmpfailure = getchecked.nil? ? false : (getchecked ? false : true)
|
364
351
|
pseudocode = Sisimai::SMTP::Status.code(o.reason, tmpfailure)
|
365
352
|
|
366
|
-
|
353
|
+
if pseudocode
|
367
354
|
# Set the value of "deliverystatus" and "softbounce"
|
368
355
|
o.deliverystatus = pseudocode
|
369
356
|
|
@@ -399,7 +386,7 @@ module Sisimai
|
|
399
386
|
def damn
|
400
387
|
data = {}
|
401
388
|
@@rwaccessors.each do |e|
|
402
|
-
next if %w[addresser recipient timestamp].
|
389
|
+
next if %w[addresser recipient timestamp].include?(e.to_s)
|
403
390
|
data[e.to_s] = self.send(e) || ''
|
404
391
|
end
|
405
392
|
data['addresser'] = self.addresser.address
|
@@ -414,7 +401,7 @@ module Sisimai
|
|
414
401
|
# @return [String, Nil] Dumped data or nil if the value of the first
|
415
402
|
# argument is neither "json" nor "yaml"
|
416
403
|
def dump(type = 'json')
|
417
|
-
return nil unless %w[json yaml].
|
404
|
+
return nil unless %w[json yaml].include?(type)
|
418
405
|
referclass = 'Sisimai::Data::' << type.upcase
|
419
406
|
|
420
407
|
begin
|