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
@@ -13,7 +13,7 @@ module Sisimai::Bite::Email
|
|
13
13
|
message: ['The following message to <', 'An error occurred while trying to deliver the mail'],
|
14
14
|
rfc822: ['content-type: message/rfc822'],
|
15
15
|
}.freeze
|
16
|
-
MessagesOf = { expired
|
16
|
+
MessagesOf = { 'expired' => ['Delivery expired'] }.freeze
|
17
17
|
|
18
18
|
def description; return 'Amazon SES(Sending): http://aws.amazon.com/ses/'; end
|
19
19
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
@@ -22,7 +22,7 @@ module Sisimai::Bite::Email
|
|
22
22
|
# X-Original-To: 000001321defbd2a-788e31c8-2be1-422f-a8d4-cf7765cc9ed7-000000@email-bounces.amazonses.com
|
23
23
|
# X-AWS-Outgoing: 199.255.192.156
|
24
24
|
# X-SES-Outgoing: 2016.10.12-54.240.27.6
|
25
|
-
def headerlist; return [
|
25
|
+
def headerlist; return %w[x-aws-outgoing x-ses-outgoing x-amz-sns-message-id]; end
|
26
26
|
|
27
27
|
# Parse bounce messages from Amazon SES
|
28
28
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -45,6 +45,10 @@ module Sisimai::Bite::Email
|
|
45
45
|
match += 1 if mhead['x-ses-outgoing']
|
46
46
|
return nil unless match > 0
|
47
47
|
|
48
|
+
require 'sisimai/rfc1894'
|
49
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
50
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
51
|
+
|
48
52
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
49
53
|
hasdivided = mbody.split("\n")
|
50
54
|
havepassed = ['']
|
@@ -52,10 +56,6 @@ module Sisimai::Bite::Email
|
|
52
56
|
blanklines = 0 # (Integer) The number of blank lines
|
53
57
|
readcursor = 0 # (Integer) Points the current cursor position
|
54
58
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
55
|
-
connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
|
56
|
-
connheader = {
|
57
|
-
'lhost' => '', # The value of Reporting-MTA header
|
58
|
-
}
|
59
59
|
v = nil
|
60
60
|
|
61
61
|
while e = hasdivided.shift do
|
@@ -64,7 +64,7 @@ module Sisimai::Bite::Email
|
|
64
64
|
p = havepassed[-2]
|
65
65
|
|
66
66
|
if readcursor == 0
|
67
|
-
# Beginning of the bounce message or delivery
|
67
|
+
# Beginning of the bounce message or message/delivery-status part
|
68
68
|
if e.start_with?(StartingOf[:message][0], StartingOf[:message][1])
|
69
69
|
readcursor |= Indicators[:deliverystatus]
|
70
70
|
next
|
@@ -72,7 +72,7 @@ module Sisimai::Bite::Email
|
|
72
72
|
end
|
73
73
|
|
74
74
|
if (readcursor & Indicators[:'message-rfc822']) == 0
|
75
|
-
# Beginning of the original message part
|
75
|
+
# Beginning of the original message part(message/rfc822)
|
76
76
|
if e == StartingOf[:rfc822][0]
|
77
77
|
readcursor |= Indicators[:'message-rfc822']
|
78
78
|
next
|
@@ -80,8 +80,7 @@ module Sisimai::Bite::Email
|
|
80
80
|
end
|
81
81
|
|
82
82
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
83
|
-
#
|
84
|
-
# After "message/rfc822"
|
83
|
+
# message/rfc822 OR text/rfc822-headers part
|
85
84
|
if e.empty?
|
86
85
|
blanklines += 1
|
87
86
|
break if blanklines > 1
|
@@ -89,86 +88,51 @@ module Sisimai::Bite::Email
|
|
89
88
|
end
|
90
89
|
rfc822list << e
|
91
90
|
else
|
92
|
-
#
|
91
|
+
# message/delivery-status part
|
93
92
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
94
93
|
next if e.empty?
|
95
94
|
|
96
|
-
if
|
97
|
-
#
|
98
|
-
|
99
|
-
# Status: 5.0.0 (permanent failure)
|
100
|
-
# Remote-MTA: dns; [192.0.2.9]
|
101
|
-
# Diagnostic-Code: smtp; 5.1.0 - Unknown address error 550-'5.7.1
|
102
|
-
# <000001321defbd2a-788e31c8-2be1-422f-a8d4-cf7765cc9ed7-000000@email-bounces.amazonses.com>...
|
103
|
-
# Access denied' (delivery attempts: 0)
|
104
|
-
#
|
105
|
-
# --JuU8e.4gyIcCrxq.1RFbQY.3Vu7Hs+
|
106
|
-
# content-type: message/rfc822
|
95
|
+
if f = Sisimai::RFC1894.match(e)
|
96
|
+
# "e" matched with any field defined in RFC3464
|
97
|
+
next unless o = Sisimai::RFC1894.field(e)
|
107
98
|
v = dscontents[-1]
|
108
99
|
|
109
|
-
if
|
110
|
-
# Final-Recipient:
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
v
|
100
|
+
if o[-1] == 'addr'
|
101
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
102
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
103
|
+
if o[0] == 'final-recipient'
|
104
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
105
|
+
if v['recipient']
|
106
|
+
# There are multiple recipient addresses in the message body.
|
107
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
108
|
+
v = dscontents[-1]
|
109
|
+
end
|
110
|
+
v['recipient'] = o[2]
|
111
|
+
recipients += 1
|
112
|
+
else
|
113
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
114
|
+
v['alias'] = o[2]
|
115
115
|
end
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
# X-Actual-Recipient: RFC822; kijitora@example.co.jp
|
121
|
-
v['alias'] = cv[1]
|
122
|
-
|
123
|
-
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
124
|
-
# Action: failed
|
125
|
-
v['action'] = cv[1].downcase
|
126
|
-
|
127
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
128
|
-
# Status: 5.1.1
|
129
|
-
# Status:5.2.0
|
130
|
-
# Status: 5.1.0 (permanent failure)
|
131
|
-
v['status'] = cv[1]
|
132
|
-
|
133
|
-
elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
134
|
-
# Remote-MTA: DNS; mx.example.jp
|
135
|
-
v['rhost'] = cv[1].downcase
|
136
|
-
|
137
|
-
elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
|
138
|
-
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
139
|
-
v['date'] = cv[1]
|
116
|
+
elsif o[-1] == 'code'
|
117
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
118
|
+
v['spec'] = o[1]
|
119
|
+
v['diagnosis'] = o[2]
|
140
120
|
else
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
# Continued line of the value of Diagnostic-Code header
|
148
|
-
v['diagnosis'] << ' ' << cv[1]
|
149
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
150
|
-
end
|
121
|
+
# Other DSN fields defined in RFC3464
|
122
|
+
next unless fieldtable.key?(o[0])
|
123
|
+
v[fieldtable[o[0]]] = o[2]
|
124
|
+
|
125
|
+
next unless f == 1
|
126
|
+
permessage[fieldtable[o[0]]] = o[2]
|
151
127
|
end
|
152
128
|
else
|
153
|
-
#
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
# --JuU8e.4gyIcCrxq.1RFbQY.3Vu7Hs+
|
159
|
-
# content-type: message/delivery-status
|
160
|
-
#
|
161
|
-
# Reporting-MTA: dns; a192-79.smtp-out.amazonses.com
|
162
|
-
#
|
163
|
-
if cv = e.match(/\AReporting-MTA:[ ]*[DNSdns]+;[ ]*(.+)\z/)
|
164
|
-
# Reporting-MTA: dns; mx.example.jp
|
165
|
-
next unless connheader['lhost'].empty?
|
166
|
-
connheader['lhost'] = cv[1].downcase
|
167
|
-
connvalues += 1
|
168
|
-
end
|
169
|
-
|
129
|
+
# Continued line of the value of Diagnostic-Code field
|
130
|
+
next unless p.start_with?('Diagnostic-Code:')
|
131
|
+
next unless cv = e.match(/\A[ \t]+(.+)\z/)
|
132
|
+
v['diagnosis'] << ' ' << cv[1]
|
133
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
170
134
|
end
|
171
|
-
end
|
135
|
+
end # End of message/delivery-status
|
172
136
|
end
|
173
137
|
|
174
138
|
if recipients == 0 && mbody =~ /notificationType/
|
@@ -186,25 +150,27 @@ module Sisimai::Bite::Email
|
|
186
150
|
|
187
151
|
dscontents.each do |e|
|
188
152
|
# Set default values if each value is empty.
|
189
|
-
|
153
|
+
e['lhost'] ||= permessage['rhost']
|
154
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
190
155
|
|
191
156
|
e['agent'] = self.smtpagent
|
192
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].to_s.
|
157
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].to_s.tr("\n", ' '))
|
193
158
|
|
194
159
|
if e['status'].to_s.start_with?('5.0.0', '5.1.0', '4.0.0', '4.1.0')
|
195
160
|
# Get other D.S.N. value from the error message
|
196
161
|
errormessage = e['diagnosis']
|
197
162
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
163
|
+
if cv = e['diagnosis'].match(/["'](\d[.]\d[.]\d.+)['"]/)
|
164
|
+
# 5.1.0 - Unknown address error 550-'5.7.1 ...
|
165
|
+
errormessage = cv[1]
|
166
|
+
end
|
167
|
+
e['status'] = Sisimai::SMTP::Status.find(errormessage) || e['status']
|
202
168
|
end
|
203
169
|
|
204
170
|
MessagesOf.each_key do |r|
|
205
171
|
# Verify each regular expression of session errors
|
206
172
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
207
|
-
e['reason'] = r
|
173
|
+
e['reason'] = r
|
208
174
|
break
|
209
175
|
end
|
210
176
|
|
@@ -19,7 +19,7 @@ module Sisimai::Bite::Email
|
|
19
19
|
# X-Mailer: Amazon WorkMail
|
20
20
|
# X-Original-Mailer: Amazon WorkMail
|
21
21
|
# X-Ses-Outgoing: 2016.01.14-54.240.27.159
|
22
|
-
def headerlist; return [
|
22
|
+
def headerlist; return %w[x-ses-outgoing x-original-mailer]; end
|
23
23
|
|
24
24
|
# Parse bounce messages from Amazon WorkMail
|
25
25
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -47,21 +47,21 @@ module Sisimai::Bite::Email
|
|
47
47
|
end
|
48
48
|
return nil if match < 2
|
49
49
|
|
50
|
+
require 'sisimai/rfc1894'
|
51
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
52
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
53
|
+
|
50
54
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
51
55
|
hasdivided = mbody.split("\n")
|
52
56
|
rfc822list = [] # (Array) Each line in message/rfc822 part string
|
53
57
|
blanklines = 0 # (Integer) The number of blank lines
|
54
58
|
readcursor = 0 # (Integer) Points the current cursor position
|
55
59
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
56
|
-
connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
|
57
|
-
connheader = {
|
58
|
-
'lhost' => '', # The value of Reporting-MTA header
|
59
|
-
}
|
60
60
|
v = nil
|
61
61
|
|
62
62
|
while e = hasdivided.shift do
|
63
63
|
if readcursor == 0
|
64
|
-
# Beginning of the bounce message or delivery
|
64
|
+
# Beginning of the bounce message or message/delivery-status part
|
65
65
|
if e == StartingOf[:message][0]
|
66
66
|
readcursor |= Indicators[:deliverystatus]
|
67
67
|
next
|
@@ -69,7 +69,7 @@ module Sisimai::Bite::Email
|
|
69
69
|
end
|
70
70
|
|
71
71
|
if (readcursor & Indicators[:'message-rfc822']) == 0
|
72
|
-
# Beginning of the original message part
|
72
|
+
# Beginning of the original message part(message/rfc822)
|
73
73
|
if e == StartingOf[:rfc822][0]
|
74
74
|
readcursor |= Indicators[:'message-rfc822']
|
75
75
|
next
|
@@ -77,7 +77,7 @@ module Sisimai::Bite::Email
|
|
77
77
|
end
|
78
78
|
|
79
79
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
80
|
-
#
|
80
|
+
# message/rfc822 OR text/rfc822-headers part
|
81
81
|
if e.empty?
|
82
82
|
blanklines += 1
|
83
83
|
break if blanklines > 1
|
@@ -85,51 +85,42 @@ module Sisimai::Bite::Email
|
|
85
85
|
end
|
86
86
|
rfc822list << e
|
87
87
|
else
|
88
|
-
#
|
88
|
+
# message/delivery-status part
|
89
89
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
90
90
|
next if e.empty?
|
91
91
|
|
92
|
-
if
|
93
|
-
#
|
94
|
-
|
95
|
-
# Diagnostic-Code: smtp; 554 4.4.7 Message expired: unable to deliver in 840 minutes.<421 4.4.2 Connection timed out>
|
96
|
-
# Status: 4.4.7
|
92
|
+
if f = Sisimai::RFC1894.match(e)
|
93
|
+
# "e" matched with any field defined in RFC3464
|
94
|
+
o = Sisimai::RFC1894.field(e) || next
|
97
95
|
v = dscontents[-1]
|
98
96
|
|
99
|
-
if
|
100
|
-
# Final-Recipient:
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
v
|
97
|
+
if o[-1] == 'addr'
|
98
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
99
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
100
|
+
if o[0] == 'final-recipient'
|
101
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
102
|
+
if v['recipient']
|
103
|
+
# There are multiple recipient addresses in the message body.
|
104
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
105
|
+
v = dscontents[-1]
|
106
|
+
end
|
107
|
+
v['recipient'] = o[2]
|
108
|
+
recipients += 1
|
109
|
+
else
|
110
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
111
|
+
v['alias'] = o[2]
|
105
112
|
end
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
# Action: failed
|
111
|
-
v['action'] = cv[1].downcase
|
112
|
-
|
113
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
114
|
-
# Status: 5.1.1
|
115
|
-
v['status'] = cv[1]
|
113
|
+
elsif o[-1] == 'code'
|
114
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
115
|
+
v['spec'] = o[1]
|
116
|
+
v['diagnosis'] = o[2]
|
116
117
|
else
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
else
|
124
|
-
# Technical report:
|
125
|
-
#
|
126
|
-
# Reporting-MTA: dsn; a27-85.smtp-out.us-west-2.amazonses.com
|
127
|
-
#
|
128
|
-
if cv = e.match(/\AReporting-MTA:[ ]*[DNSdns]+;[ ]*(.+)\z/)
|
129
|
-
# Reporting-MTA: dns; mx.example.jp
|
130
|
-
next unless connheader['lhost'].empty?
|
131
|
-
connheader['lhost'] = cv[1].downcase
|
132
|
-
connvalues += 1
|
118
|
+
# Other DSN fields defined in RFC3464
|
119
|
+
next unless fieldtable.key?(o[0])
|
120
|
+
v[fieldtable[o[0]]] = o[2]
|
121
|
+
|
122
|
+
next unless f == 1
|
123
|
+
permessage[fieldtable[o[0]]] = o[2]
|
133
124
|
end
|
134
125
|
end
|
135
126
|
|
@@ -138,31 +129,34 @@ module Sisimai::Bite::Email
|
|
138
129
|
# <meta name="Generator" content="Amazon WorkMail v3.0-2023.77">
|
139
130
|
# <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
140
131
|
break if e.start_with?('<!DOCTYPE HTML><html>')
|
141
|
-
end
|
132
|
+
end # End of message/delivery-status
|
142
133
|
end
|
143
134
|
return nil unless recipients > 0
|
144
135
|
|
145
136
|
dscontents.each do |e|
|
146
137
|
# Set default values if each value is empty.
|
147
|
-
|
138
|
+
e['lhost'] ||= permessage['rhost']
|
139
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
148
140
|
|
149
141
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
150
142
|
if e['status'].to_s.start_with?('5.0.0', '5.1.0', '4.0.0', '4.1.0')
|
151
143
|
# Get other D.S.N. value from the error message
|
152
144
|
errormessage = e['diagnosis']
|
153
145
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
e['status'] =
|
146
|
+
if cv = e['diagnosis'].match(/["'](\d[.]\d[.]\d.+)['"]/)
|
147
|
+
# 5.1.0 - Unknown address error 550-'5.7.1 ...
|
148
|
+
errormessage = cv[1]
|
149
|
+
end
|
150
|
+
e['status'] = Sisimai::SMTP::Status.find(errormessage) || e['status']
|
159
151
|
end
|
160
152
|
|
161
|
-
|
162
|
-
|
163
|
-
|
153
|
+
if cv = e['diagnosis'].match(/[<]([245]\d\d)[ ].+[>]/)
|
154
|
+
# 554 4.4.7 Message expired: unable to deliver in 840 minutes.
|
155
|
+
# <421 4.4.2 Connection timed out>
|
156
|
+
e['replycode'] = cv[1]
|
157
|
+
end
|
164
158
|
|
165
|
-
e['reason'] ||= Sisimai::SMTP::Status.name(e['status'])
|
159
|
+
e['reason'] ||= Sisimai::SMTP::Status.name(e['status']) || ''
|
166
160
|
e['agent'] = self.smtpagent
|
167
161
|
end
|
168
162
|
|
@@ -12,8 +12,8 @@ module Sisimai::Bite::Email
|
|
12
12
|
rfc822: ['Content-Type: message/rfc822'],
|
13
13
|
}.freeze
|
14
14
|
MessagesOf = {
|
15
|
-
hostunknown
|
16
|
-
notaccept
|
15
|
+
'hostunknown' => ['Host or domain name not found'],
|
16
|
+
'notaccept' => ['type=MX: Malformed or unexpected name server reply'],
|
17
17
|
}.freeze
|
18
18
|
|
19
19
|
def description; return 'Aol Mail: http://www.aol.com'; end
|
@@ -29,7 +29,7 @@ module Sisimai::Bite::Email
|
|
29
29
|
# X-BounceIO-Id: 9D38DE46-21BC-4309-83E1-5F0D788EFF1F.1_0
|
30
30
|
# X-Outbound-Mail-Relay-Queue-ID: 07391702BF4DC
|
31
31
|
# X-Outbound-Mail-Relay-Sender: rfc822; shironeko@aol.example.jp
|
32
|
-
def headerlist; return [
|
32
|
+
def headerlist; return %w[x-aol-ip]; end
|
33
33
|
|
34
34
|
# Parse bounce messages from Aol Mail
|
35
35
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -47,6 +47,10 @@ module Sisimai::Bite::Email
|
|
47
47
|
# :subject => %r/\AUndeliverable: /,
|
48
48
|
return nil unless mhead['x-aol-ip']
|
49
49
|
|
50
|
+
require 'sisimai/rfc1894'
|
51
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
52
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
53
|
+
|
50
54
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
51
55
|
hasdivided = mbody.split("\n")
|
52
56
|
havepassed = ['']
|
@@ -54,11 +58,6 @@ module Sisimai::Bite::Email
|
|
54
58
|
blanklines = 0 # (Integer) The number of blank lines
|
55
59
|
readcursor = 0 # (Integer) Points the current cursor position
|
56
60
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
57
|
-
connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
|
58
|
-
connheader = {
|
59
|
-
'date' => '', # The value of Arrival-Date header
|
60
|
-
'lhost' => '', # The value of Reporting-MTA header
|
61
|
-
}
|
62
61
|
v = nil
|
63
62
|
|
64
63
|
while e = hasdivided.shift do
|
@@ -67,7 +66,7 @@ module Sisimai::Bite::Email
|
|
67
66
|
p = havepassed[-2]
|
68
67
|
|
69
68
|
if readcursor == 0
|
70
|
-
# Beginning of the bounce message or delivery
|
69
|
+
# Beginning of the bounce message or message/delivery-status part
|
71
70
|
if e.start_with?(StartingOf[:message][0])
|
72
71
|
readcursor |= Indicators[:deliverystatus]
|
73
72
|
next
|
@@ -75,7 +74,7 @@ module Sisimai::Bite::Email
|
|
75
74
|
end
|
76
75
|
|
77
76
|
if (readcursor & Indicators[:'message-rfc822']) == 0
|
78
|
-
# Beginning of the original message part
|
77
|
+
# Beginning of the original message part(message/rfc822)
|
79
78
|
if e.start_with?(StartingOf[:rfc822][0])
|
80
79
|
readcursor |= Indicators[:'message-rfc822']
|
81
80
|
next
|
@@ -83,7 +82,7 @@ module Sisimai::Bite::Email
|
|
83
82
|
end
|
84
83
|
|
85
84
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
86
|
-
#
|
85
|
+
# message/rfc822 OR text/rfc822-headers part
|
87
86
|
if e.empty?
|
88
87
|
blanklines += 1
|
89
88
|
break if blanklines > 1
|
@@ -91,97 +90,72 @@ module Sisimai::Bite::Email
|
|
91
90
|
end
|
92
91
|
rfc822list << e
|
93
92
|
else
|
94
|
-
#
|
93
|
+
# message/delivery-status part
|
95
94
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
96
95
|
next if e.empty?
|
97
96
|
|
98
|
-
if
|
99
|
-
#
|
100
|
-
|
101
|
-
# Action: failed
|
102
|
-
# Status: 5.2.2
|
103
|
-
# Remote-MTA: dns; mx.example.co.jp
|
104
|
-
# Diagnostic-Code: smtp; 550 5.2.2 <kijitora@example.co.jp>... Mailbox Full
|
97
|
+
if f = Sisimai::RFC1894.match(e)
|
98
|
+
# "e" matched with any field defined in RFC3464
|
99
|
+
next unless o = Sisimai::RFC1894.field(e)
|
105
100
|
v = dscontents[-1]
|
106
101
|
|
107
|
-
if
|
108
|
-
# Final-Recipient:
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
v
|
102
|
+
if o[-1] == 'addr'
|
103
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
104
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
105
|
+
if o[0] == 'final-recipient'
|
106
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
107
|
+
if v['recipient']
|
108
|
+
# There are multiple recipient addresses in the message body.
|
109
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
110
|
+
v = dscontents[-1]
|
111
|
+
end
|
112
|
+
v['recipient'] = o[2]
|
113
|
+
recipients += 1
|
114
|
+
else
|
115
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
116
|
+
v['alias'] = o[2]
|
113
117
|
end
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
# Action: failed
|
119
|
-
v['action'] = cv[1].downcase
|
120
|
-
|
121
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
122
|
-
# Status:5.2.0
|
123
|
-
v['status'] = cv[1]
|
124
|
-
|
125
|
-
elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
126
|
-
# Remote-MTA: DNS; mx.example.jp
|
127
|
-
v['rhost'] = cv[1].downcase
|
118
|
+
elsif o[-1] == 'code'
|
119
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
120
|
+
v['spec'] = o[1]
|
121
|
+
v['diagnosis'] = o[2]
|
128
122
|
else
|
129
|
-
#
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
136
|
-
# Continued line of the value of Diagnostic-Code header
|
137
|
-
v['diagnosis'] << ' ' << cv[1]
|
138
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
139
|
-
end
|
123
|
+
# Other DSN fields defined in RFC3464
|
124
|
+
next unless fieldtable.key?(o[0])
|
125
|
+
v[fieldtable[o[0]]] = o[2]
|
126
|
+
|
127
|
+
next unless f == 1
|
128
|
+
permessage[fieldtable[o[0]]] = o[2]
|
140
129
|
end
|
141
130
|
else
|
142
|
-
#
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
# X-Outbound-Mail-Relay-Sender: rfc822; shironeko@aol.example.jp
|
148
|
-
# Arrival-Date: Fri, 21 Nov 2014 17:14:34 -0500 (EST)
|
149
|
-
if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
150
|
-
# Reporting-MTA: dns; mx.example.jp
|
151
|
-
next unless connheader['lhost'].empty?
|
152
|
-
connheader['lhost'] = cv[1].downcase
|
153
|
-
connvalues += 1
|
154
|
-
|
155
|
-
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
156
|
-
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
157
|
-
next unless connheader['date'].empty?
|
158
|
-
connheader['date'] = cv[1]
|
159
|
-
connvalues += 1
|
160
|
-
end
|
161
|
-
|
131
|
+
# Continued line of the value of Diagnostic-Code field
|
132
|
+
next unless p.start_with?('Diagnostic-Code:')
|
133
|
+
next unless cv = e.match(/\A[ \t]+(.+)\z/)
|
134
|
+
v['diagnosis'] << ' ' << cv[1]
|
135
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
162
136
|
end
|
163
|
-
end
|
137
|
+
end # End of message/delivery-status
|
164
138
|
end
|
165
139
|
return nil unless recipients > 0
|
166
140
|
|
167
141
|
dscontents.each do |e|
|
168
142
|
# Set default values if each value is empty.
|
169
|
-
|
143
|
+
e['lhost'] ||= permessage['rhost']
|
144
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
170
145
|
|
171
146
|
e['agent'] = self.smtpagent
|
172
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].
|
147
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
173
148
|
|
174
149
|
MessagesOf.each_key do |r|
|
175
150
|
# Verify each regular expression of session errors
|
176
151
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
177
|
-
e['reason'] = r
|
152
|
+
e['reason'] = r
|
178
153
|
break
|
179
154
|
end
|
180
155
|
|
181
156
|
if e['status'].empty? || e['status'].end_with?('.0.0')
|
182
157
|
# There is no value of Status header or the value is 5.0.0, 4.0.0
|
183
|
-
|
184
|
-
e['status'] = pseudostatus unless pseudostatus.empty?
|
158
|
+
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
|
185
159
|
end
|
186
160
|
end
|
187
161
|
|