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
@@ -49,6 +49,10 @@ module Sisimai::Bite::Email
|
|
49
49
|
# :from => %r/ [(]Mail Delivery System[)]\z/,
|
50
50
|
return nil unless mhead['subject'] == 'Undelivered Mail Returned to Sender'
|
51
51
|
|
52
|
+
require 'sisimai/rfc1894'
|
53
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
54
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
55
|
+
|
52
56
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
53
57
|
hasdivided = mbody.split("\n")
|
54
58
|
havepassed = ['']
|
@@ -57,11 +61,6 @@ module Sisimai::Bite::Email
|
|
57
61
|
readcursor = 0 # (Integer) Points the current cursor position
|
58
62
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
59
63
|
commandset = [] # (Array) ``in reply to * command'' list
|
60
|
-
connvalues = 0 # (Integer) Flag, 1 if all the value of connheader have been set
|
61
|
-
connheader = {
|
62
|
-
'date' => '', # The value of Arrival-Date header
|
63
|
-
'lhost' => '', # The value of Received-From-MTA header
|
64
|
-
}
|
65
64
|
anotherset = {} # Another error information
|
66
65
|
v = nil
|
67
66
|
|
@@ -71,7 +70,7 @@ module Sisimai::Bite::Email
|
|
71
70
|
p = havepassed[-2]
|
72
71
|
|
73
72
|
if readcursor == 0
|
74
|
-
# Beginning of the bounce message or delivery
|
73
|
+
# Beginning of the bounce message or message/delivery-status part
|
75
74
|
if e =~ MarkingsOf[:message]
|
76
75
|
readcursor |= Indicators[:deliverystatus]
|
77
76
|
next
|
@@ -79,7 +78,7 @@ module Sisimai::Bite::Email
|
|
79
78
|
end
|
80
79
|
|
81
80
|
if (readcursor & Indicators[:'message-rfc822']) == 0
|
82
|
-
# Beginning of the original message part
|
81
|
+
# Beginning of the original message part(message/rfc822)
|
83
82
|
if e.start_with?(StartingOf[:rfc822][0], StartingOf[:rfc822][1])
|
84
83
|
readcursor |= Indicators[:'message-rfc822']
|
85
84
|
next
|
@@ -87,7 +86,7 @@ module Sisimai::Bite::Email
|
|
87
86
|
end
|
88
87
|
|
89
88
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
90
|
-
#
|
89
|
+
# message/rfc822 OR text/rfc822-headers part
|
91
90
|
if e.empty?
|
92
91
|
blanklines += 1
|
93
92
|
break if blanklines > 1
|
@@ -95,71 +94,43 @@ module Sisimai::Bite::Email
|
|
95
94
|
end
|
96
95
|
rfc822list << e
|
97
96
|
else
|
98
|
-
#
|
97
|
+
# message/delivery-status part
|
99
98
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
100
99
|
next if e.empty?
|
101
100
|
|
102
|
-
if
|
103
|
-
#
|
104
|
-
|
105
|
-
# Action: failed
|
106
|
-
# Status: 5.1.1
|
107
|
-
# Remote-MTA: DNS; mx.example.jp
|
108
|
-
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
109
|
-
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
101
|
+
if f = Sisimai::RFC1894.match(e)
|
102
|
+
# "e" matched with any field defined in RFC3464
|
103
|
+
next unless o = Sisimai::RFC1894.field(e)
|
110
104
|
v = dscontents[-1]
|
111
|
-
if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*(.+)\z/)
|
112
|
-
# Final-Recipient: RFC822; userunknown@example.jp
|
113
|
-
if v['recipient']
|
114
|
-
# There are multiple recipient addresses in the message body.
|
115
|
-
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
116
|
-
v = dscontents[-1]
|
117
|
-
end
|
118
|
-
v['recipient'] = cv[1]
|
119
|
-
recipients += 1
|
120
|
-
|
121
|
-
elsif cv = e.match(/\AX-Actual-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/) ||
|
122
|
-
e.match(/\AOriginal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
|
123
|
-
# X-Actual-Recipient: RFC822; kijitora@example.co.jp
|
124
|
-
# Original-Recipient: rfc822;kijitora@example.co.jp
|
125
|
-
v['alias'] = cv[1]
|
126
|
-
|
127
|
-
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
128
|
-
# Action: failed
|
129
|
-
v['action'] = cv[1].downcase
|
130
105
|
|
131
|
-
|
132
|
-
#
|
133
|
-
#
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
#
|
149
|
-
|
150
|
-
v['
|
106
|
+
if o[-1] == 'addr'
|
107
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
108
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
109
|
+
if o[0] == 'final-recipient'
|
110
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
111
|
+
if v['recipient']
|
112
|
+
# There are multiple recipient addresses in the message body.
|
113
|
+
dscontents << Sisimai::Bite.DELIVERYSTATUS
|
114
|
+
v = dscontents[-1]
|
115
|
+
end
|
116
|
+
v['recipient'] = o[2]
|
117
|
+
recipients += 1
|
118
|
+
else
|
119
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
120
|
+
v['alias'] = o[2]
|
121
|
+
end
|
122
|
+
elsif o[-1] == 'code'
|
123
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
124
|
+
v['spec'] = o[1]
|
125
|
+
v['spec'] = 'SMTP' if v['spec'] == 'X-POSTFIX'
|
126
|
+
v['diagnosis'] = o[2]
|
151
127
|
else
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
v['diagnosis'] = cv[2]
|
156
|
-
v['spec'] = 'SMTP' if v['spec'] == 'X-POSTFIX'
|
128
|
+
# Other DSN fields defined in RFC3464
|
129
|
+
next unless fieldtable.key?(o[0])
|
130
|
+
v[fieldtable[o[0]]] = o[2]
|
157
131
|
|
158
|
-
|
159
|
-
|
160
|
-
v['diagnosis'] << ' ' << cv[1]
|
161
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
162
|
-
end
|
132
|
+
next unless f == 1
|
133
|
+
permessage[fieldtable[o[0]]] = o[2]
|
163
134
|
end
|
164
135
|
else
|
165
136
|
# If you do so, please include this problem report. You can
|
@@ -170,58 +141,52 @@ module Sisimai::Bite::Email
|
|
170
141
|
# <userunknown@example.co.jp>: host mx.example.co.jp[192.0.2.153] said: 550
|
171
142
|
# 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
|
172
143
|
# command)
|
173
|
-
if cv = e.match(
|
174
|
-
#
|
175
|
-
|
176
|
-
|
177
|
-
anotherset['diagnosis'] << ' ' << e
|
144
|
+
if p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
145
|
+
# Continued line of the value of Diagnostic-Code header
|
146
|
+
v['diagnosis'] << ' ' << cv[1]
|
147
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
178
148
|
|
179
|
-
elsif cv = e.match(
|
180
|
-
#
|
181
|
-
|
182
|
-
anotherset['diagnosis'] ||= ''
|
183
|
-
anotherset['diagnosis'] << ' ' << e
|
149
|
+
elsif cv = e.match(/\A(X-Postfix-Sender):[ ]*rfc822;[ ]*(.+)\z/)
|
150
|
+
# X-Postfix-Sender: rfc822; shironeko@example.org
|
151
|
+
rfc822list << cv[1] << ': ' << cv[2]
|
184
152
|
|
185
153
|
else
|
186
|
-
if cv = e.match(
|
187
|
-
#
|
188
|
-
|
189
|
-
|
190
|
-
|
154
|
+
if cv = e.match(/[ \t][(]in reply to ([A-Z]{4}).*/)
|
155
|
+
# 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
|
156
|
+
commandset << cv[1]
|
157
|
+
anotherset['diagnosis'] ||= ''
|
158
|
+
anotherset['diagnosis'] << ' ' << e
|
159
|
+
|
160
|
+
elsif cv = e.match(/([A-Z]{4})[ \t]*.*command[)]\z/)
|
161
|
+
# to MAIL command)
|
162
|
+
commandset << cv[1]
|
163
|
+
anotherset['diagnosis'] ||= ''
|
164
|
+
anotherset['diagnosis'] << ' ' << e
|
191
165
|
|
192
|
-
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
193
|
-
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
194
|
-
next unless connheader['date'].empty?
|
195
|
-
connheader['date'] = cv[1]
|
196
|
-
connvalues += 1
|
197
|
-
|
198
|
-
elsif cv = e.match(/\A(X-Postfix-Sender):[ ]*rfc822;[ ]*(.+)\z/)
|
199
|
-
# X-Postfix-Sender: rfc822; shironeko@example.org
|
200
|
-
rfc822list << (cv[1] << ': ' << cv[2])
|
201
166
|
else
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
167
|
+
# Alternative error message and recipient
|
168
|
+
if cv = e.match(/\A[<]([^ ]+[@][^ ]+)[>] [(]expanded from [<](.+)[>][)]:[ \t]*(.+)\z/)
|
169
|
+
# <r@example.ne.jp> (expanded from <kijitora@example.org>): user ...
|
170
|
+
anotherset['recipient'] = cv[1]
|
171
|
+
anotherset['alias'] = cv[2]
|
172
|
+
anotherset['diagnosis'] = cv[3]
|
173
|
+
|
174
|
+
elsif cv = e.match(/\A[<]([^ ]+[@][^ ]+)[>]:(.*)\z/)
|
175
|
+
# <kijitora@exmaple.jp>: ...
|
176
|
+
anotherset['recipient'] = cv[1]
|
177
|
+
anotherset['diagnosis'] = cv[2]
|
178
|
+
else
|
179
|
+
# Get error message continued from the previous line
|
180
|
+
next unless anotherset['diagnosis']
|
181
|
+
if e =~ /\A[ \t]{4}(.+)\z/
|
182
|
+
# host mx.example.jp said:...
|
183
|
+
anotherset['diagnosis'] << ' ' << e
|
184
|
+
end
|
219
185
|
end
|
220
186
|
end
|
221
|
-
end
|
222
187
|
end
|
223
188
|
end
|
224
|
-
end # End of
|
189
|
+
end # End of message/delivery-status
|
225
190
|
end
|
226
191
|
|
227
192
|
unless recipients > 0
|
@@ -236,7 +201,8 @@ module Sisimai::Bite::Email
|
|
236
201
|
|
237
202
|
dscontents.each do |e|
|
238
203
|
# Set default values if each value is empty.
|
239
|
-
|
204
|
+
e['lhost'] ||= permessage['rhost']
|
205
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
240
206
|
|
241
207
|
e['agent'] = self.smtpagent
|
242
208
|
e['command'] = commandset.shift || ''
|
@@ -258,7 +224,7 @@ module Sisimai::Bite::Email
|
|
258
224
|
if e['status'] == '' || e['status'].start_with?('4.0.0', '5.0.0')
|
259
225
|
# Check the value of D.S.N. in anotherset
|
260
226
|
as = Sisimai::SMTP::Status.find(anotherset['diagnosis'])
|
261
|
-
if
|
227
|
+
if as && as[-3, 3] != '0.0'
|
262
228
|
# The D.S.N. is neither an empty nor *.0.0
|
263
229
|
e['status'] = as
|
264
230
|
end
|
@@ -267,7 +233,7 @@ module Sisimai::Bite::Email
|
|
267
233
|
if e['replycode'] == '' || e['replycode'].start_with?('400', '500')
|
268
234
|
# Check the value of SMTP reply code in anotherset
|
269
235
|
ar = Sisimai::SMTP::Reply.find(anotherset['diagnosis'])
|
270
|
-
if
|
236
|
+
if ar && ar[-2, 2].to_i != 0
|
271
237
|
# The SMTP reply code is neither an empty nor *00
|
272
238
|
e['replycode'] = ar
|
273
239
|
end
|
@@ -23,21 +23,21 @@ module Sisimai::Bite::Email
|
|
23
23
|
ReSMTP = {
|
24
24
|
# Error text regular expressions which defined in qmail-remote.c
|
25
25
|
# qmail-remote.c:225| if (smtpcode() != 220) quit("ZConnected to "," but greeting failed");
|
26
|
-
conn
|
26
|
+
'conn' => %r/(?:Error:)?Connected to .+ but greeting failed[.]/,
|
27
27
|
# qmail-remote.c:231| if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected");
|
28
|
-
ehlo
|
28
|
+
'ehlo' => %r/(?:Error:)?Connected to .+ but my name was rejected[.]/,
|
29
29
|
# qmail-remote.c:238| if (code >= 500) quit("DConnected to "," but sender was rejected");
|
30
30
|
# reason = rejected
|
31
|
-
mail
|
31
|
+
'mail' => %r/(?:Error:)?Connected to .+ but sender was rejected[.]/,
|
32
32
|
# qmail-remote.c:249| out("h"); outhost(); out(" does not like recipient.\n");
|
33
33
|
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
34
34
|
# reason = userunknown
|
35
|
-
rcpt
|
35
|
+
'rcpt' => %r/(?:Error:)?.+ does not like recipient[.]/,
|
36
36
|
# qmail-remote.c:265| if (code >= 500) quit("D"," failed on DATA command");
|
37
37
|
# qmail-remote.c:266| if (code >= 400) quit("Z"," failed on DATA command");
|
38
38
|
# qmail-remote.c:271| if (code >= 500) quit("D"," failed after I sent the message");
|
39
39
|
# qmail-remote.c:272| if (code >= 400) quit("Z"," failed after I sent the message");
|
40
|
-
data
|
40
|
+
'data' => %r{(?:
|
41
41
|
(?:Error:)?.+[ ]failed[ ]on[ ]DATA[ ]command[.]
|
42
42
|
|(?:Error:)?.+[ ]failed[ ]after[ ]I[ ]sent[ ]the[ ]message[.]
|
43
43
|
)
|
@@ -57,10 +57,10 @@ module Sisimai::Bite::Email
|
|
57
57
|
ReIsOnHold = %r/\A[^ ]+ does not like recipient[.][ ]+.+this message has been in the queue too long[.]\z/
|
58
58
|
FailOnLDAP = {
|
59
59
|
# qmail-ldap-1.03-20040101.patch:19817 - 19866
|
60
|
-
suspend
|
61
|
-
userunknown
|
62
|
-
exceedlimit
|
63
|
-
systemerror
|
60
|
+
'suspend' => ['Mailaddress is administrative?le?y disabled'], # 5.2.1
|
61
|
+
'userunknown' => ['Sorry, no mailbox here by that name'], # 5.1.1
|
62
|
+
'exceedlimit' => ['The message exeeded the maximum size the user accepts'], # 5.2.3
|
63
|
+
'systemerror' => [
|
64
64
|
'Automatic homedir creator crashed', # 4.3.0
|
65
65
|
'Illegal value in LDAP attribute', # 5.3.5
|
66
66
|
'LDAP attribute is not given but mandatory', # 5.3.5
|
@@ -77,22 +77,22 @@ module Sisimai::Bite::Email
|
|
77
77
|
MessagesOf = {
|
78
78
|
# qmail-local.c:589| strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)");
|
79
79
|
# qmail-remote.c:253| out("s"); outhost(); out(" does not like recipient.\n");
|
80
|
-
userunknown
|
80
|
+
'userunknown' => ['no mailbox here by that name', 'does not like recipient.'],
|
81
81
|
# error_str.c:192| X(EDQUOT,"disk quota exceeded")
|
82
|
-
mailboxfull
|
82
|
+
'mailboxfull' => ['disk quota exceeded'],
|
83
83
|
# qmail-qmtpd.c:233| ... result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)";
|
84
84
|
# qmail-smtpd.c:391| ... out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return;
|
85
|
-
mesgtoobig
|
85
|
+
'mesgtoobig' => ['Message size exceeds fixed maximum message size:'],
|
86
86
|
# qmail-remote.c:68| Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie();
|
87
87
|
# qmail-remote.c:78| Sorry, I couldn't find any host named ");
|
88
|
-
hostunknown
|
89
|
-
systemfull
|
90
|
-
systemerror
|
88
|
+
'hostunknown' => ["Sorry, I couldn't find any host "],
|
89
|
+
'systemfull' => ['Requested action not taken: mailbox unavailable (not enough free space)'],
|
90
|
+
'systemerror' => [
|
91
91
|
'bad interpreter: No such file or directory',
|
92
92
|
'system error',
|
93
93
|
'Unable to',
|
94
94
|
],
|
95
|
-
networkerror
|
95
|
+
'networkerror' => [
|
96
96
|
"Sorry, I wasn't able to establish an SMTP connection",
|
97
97
|
"Sorry, I couldn't find a mail exchanger or IP address",
|
98
98
|
"Sorry. Although I'm listed as a best-preference MX or A for that host",
|
@@ -151,7 +151,7 @@ module Sisimai::Bite::Email
|
|
151
151
|
end
|
152
152
|
|
153
153
|
if readcursor & Indicators[:'message-rfc822'] > 0
|
154
|
-
#
|
154
|
+
# Inside of the original message part
|
155
155
|
if e.empty?
|
156
156
|
blanklines += 1
|
157
157
|
break if blanklines > 1
|
@@ -159,7 +159,7 @@ module Sisimai::Bite::Email
|
|
159
159
|
end
|
160
160
|
rfc822list << e
|
161
161
|
else
|
162
|
-
#
|
162
|
+
# Error message part
|
163
163
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
164
164
|
next if e.empty?
|
165
165
|
|
@@ -203,7 +203,7 @@ module Sisimai::Bite::Email
|
|
203
203
|
ReSMTP.each_key do |r|
|
204
204
|
# Verify each regular expression of SMTP commands
|
205
205
|
next unless e['diagnosis'] =~ ReSMTP[r]
|
206
|
-
e['command'] = r.
|
206
|
+
e['command'] = r.upcase
|
207
207
|
break
|
208
208
|
end
|
209
209
|
|
@@ -234,12 +234,12 @@ module Sisimai::Bite::Email
|
|
234
234
|
if e['alterrors']
|
235
235
|
# Check the value of "alterrors"
|
236
236
|
next unless MessagesOf[r].any? { |a| e['alterrors'].include?(a) }
|
237
|
-
e['reason'] = r
|
237
|
+
e['reason'] = r
|
238
238
|
end
|
239
239
|
break if e['reason']
|
240
240
|
|
241
241
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
242
|
-
e['reason'] = r
|
242
|
+
e['reason'] = r
|
243
243
|
break
|
244
244
|
end
|
245
245
|
|
@@ -247,7 +247,7 @@ module Sisimai::Bite::Email
|
|
247
247
|
FailOnLDAP.each_key do |r|
|
248
248
|
# Verify each regular expression of LDAP errors
|
249
249
|
next unless FailOnLDAP[r].any? { |a| e['diagnosis'].include?(a) }
|
250
|
-
e['reason'] = r
|
250
|
+
e['reason'] = r
|
251
251
|
break
|
252
252
|
end
|
253
253
|
end
|
@@ -258,7 +258,7 @@ module Sisimai::Bite::Email
|
|
258
258
|
end
|
259
259
|
end
|
260
260
|
|
261
|
-
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
|
261
|
+
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
|
262
262
|
e.each_key { |a| e[a] ||= '' }
|
263
263
|
end
|
264
264
|
|
@@ -15,10 +15,10 @@ module Sisimai::Bite::Email
|
|
15
15
|
}.freeze
|
16
16
|
MessagesOf = {
|
17
17
|
# The followings are error messages in Rule sets/*/Actions/Template
|
18
|
-
filtered
|
19
|
-
mesgtoobig
|
20
|
-
mailboxfull
|
21
|
-
contenterror
|
18
|
+
'filtered' => ['Mailbox does not exist'],
|
19
|
+
'mesgtoobig' => ['Message too large'],
|
20
|
+
'mailboxfull' => ['Mailbox full'],
|
21
|
+
'contenterror' => ['Message content rejected'],
|
22
22
|
}.freeze
|
23
23
|
|
24
24
|
def description; return 'Amazon SES(Receiving): http://aws.amazon.com/ses/'; end
|
@@ -26,7 +26,7 @@ module Sisimai::Bite::Email
|
|
26
26
|
|
27
27
|
# X-SES-Outgoing: 2015.10.01-54.240.27.7
|
28
28
|
# Feedback-ID: 1.us-west-2.HX6/J9OVlHTadQhEu1+wdF9DBj6n6Pa9sW5Y/0pSOi8=:AmazonSES
|
29
|
-
def headerlist; return [
|
29
|
+
def headerlist; return %w[x-ses-outgoing]; end
|
30
30
|
|
31
31
|
# Parse bounce messages from Amazon SES/Receiving
|
32
32
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -44,6 +44,10 @@ module Sisimai::Bite::Email
|
|
44
44
|
# :received => %r/.+[.]smtp-out[.].+[.]amazonses[.]com\b/,
|
45
45
|
return nil unless mhead['x-ses-outgoing']
|
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 == 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,90 +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
|
-
# Original-Recipient: rfc822; kijitora@neko.example.jp
|
99
|
-
# Diagnostic-Code: smtp; 550 5.1.1 Mailbox does not exist
|
100
|
-
# Status: 5.1.1
|
94
|
+
if f = Sisimai::RFC1894.match(e)
|
95
|
+
# "e" matched with any field defined in RFC3464
|
96
|
+
next unless o = Sisimai::RFC1894.field(e)
|
101
97
|
v = dscontents[-1]
|
102
98
|
|
103
|
-
if
|
104
|
-
# Final-Recipient:
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
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]
|
109
114
|
end
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
e.match(/\AOriginal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
|
115
|
-
# X-Actual-Recipient: RFC822; kijitora@example.co.jp
|
116
|
-
# Original-Recipient: rfc822; kijitora@example.co.jp
|
117
|
-
v['alias'] = cv[1]
|
118
|
-
|
119
|
-
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
120
|
-
# Action: failed
|
121
|
-
v['action'] = cv[1].downcase
|
122
|
-
|
123
|
-
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
124
|
-
# Status: 5.1.1
|
125
|
-
v['status'] = cv[1]
|
126
|
-
|
127
|
-
elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
128
|
-
# Remote-MTA: DNS; mx.example.jp
|
129
|
-
v['rhost'] = cv[1].downcase
|
130
|
-
|
131
|
-
elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
|
132
|
-
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
133
|
-
v['date'] = 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]
|
134
119
|
else
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
# Continued line of the value of Diagnostic-Code header
|
142
|
-
v['diagnosis'] << ' ' << cv[1]
|
143
|
-
havepassed[-1] = 'Diagnostic-Code: ' << e
|
144
|
-
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]
|
145
126
|
end
|
146
127
|
else
|
147
|
-
#
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
#
|
153
|
-
# Reporting-MTA: dns; inbound-smtp.us-west-2.amazonaws.com
|
154
|
-
if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
155
|
-
# Reporting-MTA: dns; mx.example.jp
|
156
|
-
next unless connheader['lhost'].empty?
|
157
|
-
connheader['lhost'] = cv[1].downcase
|
158
|
-
connvalues += 1
|
159
|
-
|
160
|
-
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
161
|
-
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
162
|
-
next unless connheader['date'].empty?
|
163
|
-
connheader['date'] = cv[1]
|
164
|
-
connvalues += 1
|
165
|
-
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
|
166
133
|
end
|
167
|
-
end
|
134
|
+
end # End of message/delivery-status
|
168
135
|
end
|
169
136
|
return nil unless recipients > 0
|
170
137
|
|
171
138
|
dscontents.each do |e|
|
172
139
|
# Set default values if each value is empty.
|
173
|
-
|
174
|
-
e[
|
140
|
+
e['lhost'] ||= permessage['rhost']
|
141
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
142
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
175
143
|
|
176
144
|
if e['status'].to_s.start_with?('5.0.0', '5.1.0', '4.0.0', '4.1.0')
|
177
145
|
# Get other D.S.N. value from the error message
|
@@ -181,18 +149,17 @@ module Sisimai::Bite::Email
|
|
181
149
|
# 5.1.0 - Unknown address error 550-'5.7.1 ...
|
182
150
|
errormessage = cv[1]
|
183
151
|
end
|
184
|
-
|
185
|
-
e['status'] = pseudostatus unless pseudostatus.empty?
|
152
|
+
e['status'] = Sisimai::SMTP::Status.find(errormessage) || e['status']
|
186
153
|
end
|
187
154
|
|
188
155
|
MessagesOf.each_key do |r|
|
189
156
|
# Verify each regular expression of session errors
|
190
157
|
next unless MessagesOf[r].any? { |a| e['diagnosis'].include?(a) }
|
191
|
-
e['reason'] = r
|
158
|
+
e['reason'] = r
|
192
159
|
break
|
193
160
|
end
|
194
161
|
|
195
|
-
e['reason'] ||= Sisimai::SMTP::Status.name(e['status'])
|
162
|
+
e['reason'] ||= Sisimai::SMTP::Status.name(e['status']) || ''
|
196
163
|
e['agent'] = self.smtpagent
|
197
164
|
end
|
198
165
|
|