sisimai 4.25.16-java → 5.0.2-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/workflows/rake-test.yml +55 -0
- data/.travis.yml +3 -3
- data/ANALYTICAL-PRECISION +2 -2
- data/Benchmarks.mk +3 -3
- data/CONTRIBUTING +1 -1
- data/ChangeLog.md +451 -393
- data/Developers.mk +5 -6
- data/Gemfile +1 -1
- data/Makefile +15 -15
- data/README-JA.md +323 -149
- data/README.md +319 -149
- data/Rakefile +9 -3
- data/Repository.mk +2 -3
- data/lib/sisimai/address.rb +118 -74
- data/lib/sisimai/arf.rb +84 -82
- data/lib/sisimai/datetime.rb +5 -52
- data/lib/sisimai/{data → fact}/json.rb +7 -9
- data/lib/sisimai/fact/yaml.rb +31 -0
- data/lib/sisimai/fact.rb +506 -0
- data/lib/sisimai/lhost/activehunter.rb +12 -14
- data/lib/sisimai/lhost/amavis.rb +11 -14
- data/lib/sisimai/lhost/amazonses.rb +37 -42
- data/lib/sisimai/lhost/amazonworkmail.rb +15 -19
- data/lib/sisimai/lhost/aol.rb +12 -15
- data/lib/sisimai/lhost/apachejames.rb +19 -21
- data/lib/sisimai/lhost/barracuda.rb +10 -12
- data/lib/sisimai/lhost/bigfoot.rb +21 -22
- data/lib/sisimai/lhost/biglobe.rb +15 -16
- data/lib/sisimai/lhost/courier.rb +20 -20
- data/lib/sisimai/lhost/domino.rb +23 -20
- data/lib/sisimai/lhost/einsundeins.rb +23 -18
- data/lib/sisimai/lhost/exchange2003.rb +30 -29
- data/lib/sisimai/lhost/exchange2007.rb +70 -58
- data/lib/sisimai/lhost/exim.rb +179 -174
- data/lib/sisimai/lhost/ezweb.rb +31 -56
- data/lib/sisimai/lhost/facebook.rb +21 -34
- data/lib/sisimai/lhost/fml.rb +43 -48
- data/lib/sisimai/lhost/gmail.rb +29 -29
- data/lib/sisimai/lhost/gmx.rb +18 -17
- data/lib/sisimai/lhost/googlegroups.rb +11 -11
- data/lib/sisimai/lhost/gsuite.rb +21 -28
- data/lib/sisimai/lhost/imailserver.rb +25 -39
- data/lib/sisimai/lhost/interscanmss.rb +28 -31
- data/lib/sisimai/lhost/kddi.rb +22 -28
- data/lib/sisimai/lhost/mailfoundry.rb +11 -12
- data/lib/sisimai/lhost/mailmarshalsmtp.rb +25 -29
- data/lib/sisimai/lhost/mailru.rb +37 -40
- data/lib/sisimai/lhost/mcafee.rb +21 -31
- data/lib/sisimai/lhost/messagelabs.rb +17 -21
- data/lib/sisimai/lhost/messagingserver.rb +40 -37
- data/lib/sisimai/lhost/mfilter.rb +16 -17
- data/lib/sisimai/lhost/mxlogic.rb +24 -33
- data/lib/sisimai/lhost/notes.rb +17 -17
- data/lib/sisimai/lhost/office365.rb +64 -28
- data/lib/sisimai/lhost/opensmtpd.rb +12 -13
- data/lib/sisimai/lhost/outlook.rb +12 -16
- data/lib/sisimai/lhost/postfix.rb +179 -130
- data/lib/sisimai/lhost/powermta.rb +12 -14
- data/lib/sisimai/lhost/qmail.rb +44 -47
- data/lib/sisimai/lhost/receivingses.rb +15 -21
- data/lib/sisimai/lhost/sendgrid.rb +34 -34
- data/lib/sisimai/lhost/sendmail.rb +65 -53
- data/lib/sisimai/lhost/surfcontrol.rb +19 -19
- data/lib/sisimai/lhost/v5sendmail.rb +45 -39
- data/lib/sisimai/lhost/verizon.rb +35 -39
- data/lib/sisimai/lhost/x1.rb +18 -17
- data/lib/sisimai/lhost/x2.rb +17 -14
- data/lib/sisimai/lhost/x3.rb +19 -19
- data/lib/sisimai/lhost/x4.rb +72 -57
- data/lib/sisimai/lhost/x5.rb +17 -19
- data/lib/sisimai/lhost/x6.rb +41 -17
- data/lib/sisimai/lhost/yahoo.rb +17 -16
- data/lib/sisimai/lhost/yandex.rb +16 -21
- data/lib/sisimai/lhost/zoho.rb +16 -15
- data/lib/sisimai/lhost.rb +8 -10
- data/lib/sisimai/mail/maildir.rb +1 -3
- data/lib/sisimai/mail/mbox.rb +3 -4
- data/lib/sisimai/mail/memory.rb +0 -1
- data/lib/sisimai/mail/stdin.rb +1 -3
- data/lib/sisimai/mail.rb +3 -7
- data/lib/sisimai/mda.rb +28 -42
- data/lib/sisimai/message.rb +444 -326
- data/lib/sisimai/order.rb +5 -5
- data/lib/sisimai/reason/authfailure.rb +65 -0
- data/lib/sisimai/reason/badreputation.rb +53 -0
- data/lib/sisimai/reason/blocked.rb +96 -160
- data/lib/sisimai/reason/contenterror.rb +8 -9
- data/lib/sisimai/reason/delivered.rb +4 -6
- data/lib/sisimai/reason/exceedlimit.rb +10 -12
- data/lib/sisimai/reason/expired.rb +7 -8
- data/lib/sisimai/reason/feedback.rb +2 -3
- data/lib/sisimai/reason/filtered.rb +17 -19
- data/lib/sisimai/reason/hasmoved.rb +9 -10
- data/lib/sisimai/reason/hostunknown.rb +15 -15
- data/lib/sisimai/reason/mailboxfull.rb +11 -12
- data/lib/sisimai/reason/mailererror.rb +18 -20
- data/lib/sisimai/reason/mesgtoobig.rb +9 -11
- data/lib/sisimai/reason/networkerror.rb +5 -8
- data/lib/sisimai/reason/norelaying.rb +8 -11
- data/lib/sisimai/reason/notaccept.rb +13 -14
- data/lib/sisimai/reason/notcompliantrfc.rb +43 -0
- data/lib/sisimai/reason/onhold.rb +6 -9
- data/lib/sisimai/reason/policyviolation.rb +14 -12
- data/lib/sisimai/reason/rejected.rb +26 -24
- data/lib/sisimai/reason/requireptr.rb +69 -0
- data/lib/sisimai/reason/securityerror.rb +34 -36
- data/lib/sisimai/reason/spamdetected.rb +115 -147
- data/lib/sisimai/reason/speeding.rb +49 -0
- data/lib/sisimai/reason/suspend.rb +12 -11
- data/lib/sisimai/reason/syntaxerror.rb +11 -10
- data/lib/sisimai/reason/systemerror.rb +7 -9
- data/lib/sisimai/reason/systemfull.rb +7 -8
- data/lib/sisimai/reason/toomanyconn.rb +9 -11
- data/lib/sisimai/reason/undefined.rb +2 -3
- data/lib/sisimai/reason/userunknown.rb +129 -146
- data/lib/sisimai/reason/vacation.rb +3 -4
- data/lib/sisimai/reason/virusdetected.rb +10 -11
- data/lib/sisimai/reason.rb +59 -64
- data/lib/sisimai/rfc1894.rb +55 -28
- data/lib/sisimai/rfc2045.rb +373 -0
- data/lib/sisimai/rfc3464.rb +250 -308
- data/lib/sisimai/rfc3834.rb +42 -45
- data/lib/sisimai/rfc5322.rb +177 -146
- data/lib/sisimai/rfc5965.rb +31 -0
- data/lib/sisimai/rhost/cox.rb +5 -6
- data/lib/sisimai/rhost/franceptt.rb +6 -8
- data/lib/sisimai/rhost/godaddy.rb +12 -12
- data/lib/sisimai/rhost/google.rb +530 -0
- data/lib/sisimai/rhost/iua.rb +9 -10
- data/lib/sisimai/rhost/kddi.rb +6 -8
- data/lib/sisimai/rhost/{exchangeonline.rb → microsoft.rb} +115 -114
- data/lib/sisimai/rhost/mimecast.rb +51 -42
- data/lib/sisimai/rhost/nttdocomo.rb +12 -12
- data/lib/sisimai/rhost/spectrum.rb +10 -12
- data/lib/sisimai/rhost/{tencentqq.rb → tencent.rb} +7 -8
- data/lib/sisimai/rhost.rb +23 -31
- data/lib/sisimai/smtp/command.rb +59 -0
- data/lib/sisimai/smtp/error.rb +4 -7
- data/lib/sisimai/smtp/reply.rb +161 -74
- data/lib/sisimai/smtp/status.rb +507 -393
- data/lib/sisimai/smtp/transcript.rb +124 -0
- data/lib/sisimai/smtp.rb +0 -1
- data/lib/sisimai/string.rb +74 -5
- data/lib/sisimai/time.rb +1 -2
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +46 -31
- data/set-of-emails/maildir/bsd/lhost-domino-02.eml +6 -3
- data/set-of-emails/maildir/bsd/lhost-googlegroups-15.eml +174 -0
- data/set-of-emails/maildir/bsd/lhost-gsuite-15.eml +229 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-75.eml +51 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-76.eml +101 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-77.eml +74 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-78.eml +91 -0
- data/set-of-emails/maildir/bsd/lhost-receivingses-08.eml +88 -0
- data/set-of-emails/maildir/bsd/lhost-sendmail-60.eml +85 -0
- data/set-of-emails/maildir/bsd/rfc3464-43.eml +88 -0
- data/set-of-emails/maildir/bsd/rhost-google-03.eml +101 -0
- data/set-of-emails/maildir/bsd/rhost-google-04.eml +102 -0
- data/set-of-emails/maildir/bsd/rhost-google-05.eml +82 -0
- data/set-of-emails/maildir/bsd/rhost-google-06.eml +102 -0
- data/set-of-emails/maildir/bsd/rhost-google-07.eml +69 -0
- data/set-of-emails/maildir/bsd/rhost-google-08.eml +99 -0
- data/sisimai-java.gemspec +1 -1
- data/sisimai.gemspec +1 -1
- metadata +48 -26
- data/.rspec +0 -2
- data/lib/sisimai/data/yaml.rb +0 -33
- data/lib/sisimai/data.rb +0 -411
- data/lib/sisimai/mime.rb +0 -456
- data/lib/sisimai/rhost/googleapps.rb +0 -261
- /data/set-of-emails/maildir/bsd/{rfc3464-41.eml → rfc3834-05.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-googleapps-01.eml → rhost-google-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-googleapps-02.eml → rhost-google-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-01.eml → rhost-microsoft-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-02.eml → rhost-microsoft-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-exchangeonline-03.eml → rhost-microsoft-03.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-tencentqq-01.eml → rhost-tencent-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-tencentqq-02.eml → rhost-tencent-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{rhost-tencentqq-03.eml → rhost-tencent-03.eml} +0 -0
data/lib/sisimai/lhost/exim.rb
CHANGED
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
module Sisimai::Lhost
|
|
2
|
-
# Sisimai::Lhost::Exim parses a bounce email which created by Exim.
|
|
3
|
-
#
|
|
2
|
+
# Sisimai::Lhost::Exim parses a bounce email which created by Exim. Methods in the module are called
|
|
3
|
+
# from only Sisimai::Message.
|
|
4
4
|
module Exim
|
|
5
5
|
class << self
|
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Exim.pm
|
|
7
6
|
require 'sisimai/lhost'
|
|
8
7
|
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
MarkingsOf = {
|
|
21
|
-
# Error text regular expressions which defined in exim/src/deliver.c
|
|
9
|
+
Boundaries = [
|
|
10
|
+
# deliver.c:6423| if (bounce_return_body) fprintf(f,
|
|
11
|
+
# deliver.c:6424|"------ This is a copy of the message, including all the headers. ------\n");
|
|
12
|
+
# deliver.c:6425| else fprintf(f,
|
|
13
|
+
# deliver.c:6426|"------ This is a copy of the message's headers. ------\n");
|
|
14
|
+
'------ This is a copy of the message, including all the headers. ------',
|
|
15
|
+
'Content-Type: message/rfc822',
|
|
16
|
+
].freeze
|
|
17
|
+
StartingOf = {
|
|
18
|
+
# Error text strings which defined in exim/src/deliver.c
|
|
22
19
|
#
|
|
23
20
|
# deliver.c:6292| fprintf(f,
|
|
24
21
|
# deliver.c:6293|"This message was created automatically by mail delivery software.\n");
|
|
@@ -35,19 +32,19 @@ module Sisimai::Lhost
|
|
|
35
32
|
# deliver.c:6304|"could not be delivered to one or more of its recipients. The following\n"
|
|
36
33
|
# deliver.c:6305|"address(es) failed:\n", sender_address);
|
|
37
34
|
# deliver.c:6306| }
|
|
38
|
-
|
|
39
|
-
frozen:
|
|
40
|
-
message:
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
)
|
|
48
|
-
|
|
35
|
+
deliverystatus: ['Content-Type: message/delivery-status'],
|
|
36
|
+
frozen: [' has been frozen', ' was frozen on arrival'],
|
|
37
|
+
message: [
|
|
38
|
+
'This message was created automatically by mail delivery software.',
|
|
39
|
+
'A message that you sent was rejected by the local scannning code',
|
|
40
|
+
'A message that you sent contained one or more recipient addresses ',
|
|
41
|
+
'A message that you sent could not be delivered to all of its recipients',
|
|
42
|
+
' has been frozen',
|
|
43
|
+
' was frozen on arrival',
|
|
44
|
+
' router encountered the following error(s):',
|
|
45
|
+
],
|
|
49
46
|
}.freeze
|
|
50
|
-
|
|
47
|
+
MarkingsOf = { alias: ' an undisclosed address' }.freeze
|
|
51
48
|
ReCommands = [
|
|
52
49
|
# transports/smtp.c:564| *message = US string_sprintf("SMTP error from remote mail server after %s%s: "
|
|
53
50
|
# transports/smtp.c:837| string_sprintf("SMTP error from remote mail server after RCPT TO:<%s>: "
|
|
@@ -125,51 +122,47 @@ module Sisimai::Lhost
|
|
|
125
122
|
# @param [String] mbody Message body of a bounce email
|
|
126
123
|
# @return [Hash] Bounce data list and message/rfc822 part
|
|
127
124
|
# @return [Nil] it failed to parse or the arguments are missing
|
|
128
|
-
def
|
|
129
|
-
return nil if mhead['from']
|
|
125
|
+
def inquire(mhead, mbody)
|
|
126
|
+
return nil if mhead['from'].include?('.mail.ru')
|
|
130
127
|
|
|
131
128
|
# Message-Id: <E1P1YNN-0003AD-Ga@example.org>
|
|
132
129
|
# X-Failed-Recipients: kijitora@example.ed.jp
|
|
133
130
|
match = 0
|
|
131
|
+
msgid = mhead['message-id'] || ''
|
|
134
132
|
match += 1 if mhead['from'].start_with?('Mail Delivery System')
|
|
135
|
-
match += 1 if
|
|
136
|
-
match += 1 if
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
)
|
|
144
|
-
}x
|
|
133
|
+
match += 1 if msgid.start_with?('<') && msgid.index('-') == 8 && msgid.index('@') == 18
|
|
134
|
+
match += 1 if %w[
|
|
135
|
+
'Delivery Status Notification',
|
|
136
|
+
'Mail delivery failed',
|
|
137
|
+
'Mail failure',
|
|
138
|
+
'Message frozen',
|
|
139
|
+
'Warning: message ',
|
|
140
|
+
'error(s) in forwarding or filtering'].any? { |a| mhead['subject'].include?(a) }
|
|
145
141
|
return nil if match < 2
|
|
146
142
|
|
|
147
|
-
require 'sisimai/rfc1894'
|
|
148
143
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
|
149
144
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
|
150
|
-
|
|
151
|
-
bodyslices =
|
|
145
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
|
146
|
+
bodyslices = emailparts[0].split("\n")
|
|
152
147
|
readcursor = 0 # (Integer) Points the current cursor position
|
|
153
148
|
nextcursor = 0
|
|
154
149
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
|
155
|
-
localhost0 = '' # (String) Local MTA
|
|
156
150
|
boundary00 = '' # (String) Boundary string
|
|
157
151
|
v = nil
|
|
158
152
|
|
|
159
153
|
if mhead['content-type']
|
|
160
|
-
# Get the boundary string and set regular expression for matching with
|
|
161
|
-
|
|
162
|
-
boundary00 = Sisimai::MIME.boundary(mhead['content-type']) || ''
|
|
154
|
+
# Get the boundary string and set regular expression for matching with the boundary string.
|
|
155
|
+
boundary00 = Sisimai::RFC2045.boundary(mhead['content-type']) || ''
|
|
163
156
|
end
|
|
164
157
|
|
|
165
158
|
while e = bodyslices.shift do
|
|
166
|
-
# Read error messages and delivery status lines from the head of the email
|
|
167
|
-
#
|
|
159
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
|
160
|
+
# line of the beginning of the original message.
|
|
168
161
|
if readcursor == 0
|
|
169
162
|
# Beginning of the bounce message or message/delivery-status part
|
|
170
|
-
if
|
|
163
|
+
if StartingOf[:message].any? { |a| e.include?(a) }
|
|
171
164
|
readcursor |= Indicators[:deliverystatus]
|
|
172
|
-
next unless
|
|
165
|
+
next unless StartingOf[:frozen].any? { |a| e.include?(a) }
|
|
173
166
|
end
|
|
174
167
|
end
|
|
175
168
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
|
@@ -185,109 +178,130 @@ module Sisimai::Lhost
|
|
|
185
178
|
# host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
|
186
179
|
v = dscontents[-1]
|
|
187
180
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
#
|
|
192
|
-
#
|
|
193
|
-
#
|
|
194
|
-
#
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
181
|
+
cv = ''
|
|
182
|
+
ce = false
|
|
183
|
+
while true
|
|
184
|
+
# Check if the line matche the following patterns:
|
|
185
|
+
break unless e.start_with?(' ') # The line should start with " " (2 spaces)
|
|
186
|
+
break unless e.include?('@') # "@" should be included (email)
|
|
187
|
+
break unless e.include?('.') # "." should be included (domain part)
|
|
188
|
+
break unless e.include?('pipe to |') == false # Exclude "pipe to /path/to/prog" line
|
|
189
|
+
|
|
190
|
+
break unless e[2, 1] != ' '
|
|
191
|
+
break unless e[2, 1] != '<'
|
|
192
|
+
ce = true
|
|
193
|
+
break
|
|
194
|
+
end
|
|
199
195
|
|
|
196
|
+
if ce || e.include?(MarkingsOf[:alias])
|
|
197
|
+
# The line is including an email address
|
|
200
198
|
if v['recipient']
|
|
201
199
|
# There are multiple recipient addresses in the message body.
|
|
202
200
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
|
203
201
|
v = dscontents[-1]
|
|
204
202
|
end
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
#
|
|
209
|
-
#
|
|
210
|
-
#
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
#
|
|
214
|
-
#
|
|
215
|
-
#
|
|
216
|
-
|
|
217
|
-
|
|
203
|
+
|
|
204
|
+
if e.include?(MarkingsOf[:alias])
|
|
205
|
+
# The line does not include an email address
|
|
206
|
+
# deliver.c:4549| printed = US"an undisclosed address";
|
|
207
|
+
# an undisclosed address
|
|
208
|
+
# (generated from kijitora@example.jp)
|
|
209
|
+
cv = e[2, e.size]
|
|
210
|
+
else
|
|
211
|
+
# kijitora@example.jp
|
|
212
|
+
# sabineko@example.jp: forced freeze
|
|
213
|
+
# mikeneko@example.jp <nekochan@example.org>: ...
|
|
214
|
+
p1 = e.index(' <') || -1
|
|
215
|
+
p2 = e.index('>:') || -1
|
|
216
|
+
|
|
217
|
+
if p1 > 1 && p2 > 1
|
|
218
|
+
# There are an email address and an error message in the line
|
|
219
|
+
# parser.c:743| while (bracket_count-- > 0) if (*s++ != '>')
|
|
220
|
+
# parser.c:744| {
|
|
221
|
+
# parser.c:745| *errorptr = s[-1] == 0
|
|
222
|
+
# parser.c:746| ? US"'>' missing at end of address"
|
|
223
|
+
# parser.c:747| : string_sprintf("malformed address: %.32s may not follow %.*s",
|
|
224
|
+
# parser.c:748| s-1, (int)(s - US mailbox - 1), mailbox);
|
|
225
|
+
# parser.c:749| goto PARSE_FAILED;
|
|
226
|
+
# parser.c:750| }
|
|
227
|
+
cv = Sisimai::Address.s3s4(e[p1 + 1, p2 - p1 - 1])
|
|
228
|
+
v['diagnosis'] = Sisimai::String.sweep(e[p2 + 1, e.size])
|
|
229
|
+
else
|
|
230
|
+
# There is an email address only in the line
|
|
231
|
+
# kijitora@example.jp
|
|
232
|
+
cv = Sisimai::Address.s3s4(e[2, e.size])
|
|
233
|
+
end
|
|
218
234
|
end
|
|
219
|
-
v['recipient'] =
|
|
235
|
+
v['recipient'] = cv
|
|
220
236
|
recipients += 1
|
|
221
237
|
|
|
222
|
-
elsif
|
|
223
|
-
e.match(/\A[ ]+generated[ ]by[ ]([^ \t]+[@][^ \t]+)/)
|
|
238
|
+
elsif e.include?(' (generated from ') || e.include?(' generated by ')
|
|
224
239
|
# (generated from kijitora@example.jp)
|
|
225
240
|
# pipe to |/bin/echo "Some pipe output"
|
|
226
241
|
# generated by userx@myhost.test.ex
|
|
227
|
-
v['alias'] =
|
|
242
|
+
v['alias'] = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
|
|
243
|
+
|
|
228
244
|
else
|
|
229
245
|
next if e.empty?
|
|
230
246
|
|
|
231
|
-
if
|
|
247
|
+
if StartingOf[:frozen].any? { |a| e.include?(a) }
|
|
232
248
|
# Message *** has been frozen by the system filter.
|
|
233
249
|
# Message *** was frozen on arrival by ACL.
|
|
234
250
|
v['alterrors'] ||= ''
|
|
235
251
|
v['alterrors'] << e + ' '
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
else
|
|
257
|
-
# Other DSN fields defined in RFC3464
|
|
258
|
-
next unless fieldtable[o[0]]
|
|
259
|
-
v[fieldtable[o[0]]] = o[2]
|
|
260
|
-
end
|
|
252
|
+
elsif !boundary00.empty?
|
|
253
|
+
# --NNNNNNNNNN-eximdsn-MMMMMMMMMM
|
|
254
|
+
# Content-type: message/delivery-status
|
|
255
|
+
# ...
|
|
256
|
+
if Sisimai::RFC1894.match(e)
|
|
257
|
+
# "e" matched with any field defined in RFC3464
|
|
258
|
+
next unless o = Sisimai::RFC1894.field(e)
|
|
259
|
+
|
|
260
|
+
if o[-1] == 'addr'
|
|
261
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
|
262
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
263
|
+
next unless o[0] == 'final-recipient'
|
|
264
|
+
v['spec'] ||= o[2].include?('@') ? 'SMTP' : 'X-UNIX'
|
|
265
|
+
|
|
266
|
+
elsif o[-1] == 'code'
|
|
267
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
|
268
|
+
v['spec'] = o[1]
|
|
269
|
+
v['diagnosis'] = o[2]
|
|
270
|
+
|
|
261
271
|
else
|
|
262
|
-
#
|
|
263
|
-
next
|
|
272
|
+
# Other DSN fields defined in RFC3464
|
|
273
|
+
next unless fieldtable[o[0]]
|
|
274
|
+
v[fieldtable[o[0]]] = o[2]
|
|
275
|
+
end
|
|
276
|
+
else
|
|
277
|
+
# Error message ?
|
|
278
|
+
next if nextcursor == 1
|
|
264
279
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
end
|
|
280
|
+
# Content-type: message/delivery-status
|
|
281
|
+
nextcursor = 1 if e.start_with?(StartingOf[:deliverystatus][0])
|
|
282
|
+
v['alterrors'] ||= ''
|
|
283
|
+
if e.start_with?("\s", "\t")
|
|
284
|
+
e.sub!(/\A[\s\t]+/, '')
|
|
285
|
+
v['alterrors'] << e + ' ' unless v['alterrors'].include?(e)
|
|
272
286
|
end
|
|
287
|
+
end
|
|
288
|
+
else
|
|
289
|
+
# There is no boundary string in $boundary00
|
|
290
|
+
if dscontents.size == recipients
|
|
291
|
+
# Error message
|
|
292
|
+
next if e.empty?
|
|
293
|
+
v['diagnosis'] ||= ''
|
|
294
|
+
v['diagnosis'] << e + ' '
|
|
273
295
|
else
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
v['diagnosis']
|
|
296
|
+
# Error message when email address above does not include '@' and domain part.
|
|
297
|
+
if e.include?(' pipe to |/')
|
|
298
|
+
# pipe to |/path/to/prog ...
|
|
299
|
+
# generated by kijitora@example.com
|
|
300
|
+
v['diagnosis'] = e
|
|
279
301
|
else
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
# pipe to |/path/to/prog ...
|
|
284
|
-
# generated by kijitora@example.com
|
|
285
|
-
v['diagnosis'] = e
|
|
286
|
-
else
|
|
287
|
-
next unless e.start_with?(' ')
|
|
288
|
-
v['alterrors'] ||= ''
|
|
289
|
-
v['alterrors'] << e + ' '
|
|
290
|
-
end
|
|
302
|
+
next unless e.start_with?(' ')
|
|
303
|
+
v['alterrors'] ||= ''
|
|
304
|
+
v['alterrors'] << e + ' '
|
|
291
305
|
end
|
|
292
306
|
end
|
|
293
307
|
end
|
|
@@ -327,16 +341,13 @@ module Sisimai::Lhost
|
|
|
327
341
|
end
|
|
328
342
|
return nil unless recipients > 0
|
|
329
343
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
end
|
|
344
|
+
# Get the name of the local MTA
|
|
345
|
+
# Received: from marutamachi.example.org (c192128.example.net [192.0.2.128])
|
|
346
|
+
receivedby = mhead['received'] || []
|
|
347
|
+
recvdtoken = Sisimai::RFC5322.received(receivedby[-1])
|
|
335
348
|
|
|
336
349
|
dscontents.each do |e|
|
|
337
|
-
#
|
|
338
|
-
e['lhost'] ||= localhost0
|
|
339
|
-
|
|
350
|
+
# Check the error message, the rhost, the lhost, and the smtp command.
|
|
340
351
|
unless e['diagnosis']
|
|
341
352
|
# Empty Diagnostic-Code: or error message
|
|
342
353
|
unless boundary00.empty?
|
|
@@ -371,31 +382,26 @@ module Sisimai::Lhost
|
|
|
371
382
|
if e['diagnosis'].start_with?('-') || e['diagnosis'].end_with?('__')
|
|
372
383
|
# Override the value of diagnostic code message
|
|
373
384
|
e['diagnosis'] = e['alterrors'] unless e['alterrors'].empty?
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
# Override the value of diagnostic code message because
|
|
380
|
-
# the value of alterrors includes the value of diagnosis.
|
|
381
|
-
e['diagnosis'] = e['alterrors'] if e['alterrors'].downcase.include?(e['diagnosis'].downcase)
|
|
382
|
-
end
|
|
385
|
+
|
|
386
|
+
elsif e['diagnosis'].size < e['alterrors'].size
|
|
387
|
+
# Override the value of diagnostic code message because the value of alterrors includes
|
|
388
|
+
# the value of diagnosis.
|
|
389
|
+
e['diagnosis'] = e['alterrors'] if e['alterrors'].downcase.include?(e['diagnosis'].downcase)
|
|
383
390
|
end
|
|
384
391
|
e.delete('alterrors')
|
|
385
392
|
end
|
|
386
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
|
387
|
-
e['diagnosis']
|
|
393
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''; p1 = e['diagnosis'].index('__') || -1
|
|
394
|
+
e['diagnosis'] = e['diagnosis'][0, p1] if p1 > 1
|
|
388
395
|
|
|
389
396
|
unless e['rhost']
|
|
390
397
|
# Get the remote host name
|
|
391
398
|
# host neko.example.jp [192.0.2.222]: 550 5.1.1 <kijitora@example.jp>... User Unknown
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
e['rhost'] = Sisimai::RFC5322.received(mhead['received'][-1]).pop unless mhead['received'].empty?
|
|
397
|
-
end
|
|
399
|
+
p1 = e['diagnosis'].index('host ') || -1
|
|
400
|
+
p2 = e['diagnosis'].index(' ', p1 + 5) || -1
|
|
401
|
+
e['rhost'] = e['diagnosis'][p1 + 5, p2 - p1 - 5] if p1 > -1
|
|
402
|
+
e['rhost'] ||= recvdtoken[1]
|
|
398
403
|
end
|
|
404
|
+
e['lhost'] ||= recvdtoken[0]
|
|
399
405
|
|
|
400
406
|
unless e['command']
|
|
401
407
|
# Get the SMTP command name for the session
|
|
@@ -426,55 +432,54 @@ module Sisimai::Lhost
|
|
|
426
432
|
|
|
427
433
|
unless e['reason']
|
|
428
434
|
# The reason "expired"
|
|
429
|
-
e['reason']
|
|
435
|
+
e['reason'] = 'expired' if DelayedFor.any? { |a| e['diagnosis'].include?(a) }
|
|
436
|
+
e['reason'] ||= 'mailererror' if e['diagnosis'].include?('pipe to |')
|
|
430
437
|
end
|
|
431
438
|
end
|
|
432
439
|
end
|
|
433
440
|
|
|
434
441
|
# Prefer the value of smtp reply code in Diagnostic-Code:
|
|
435
|
-
# See eg/maildir-as-a-sample/new/exim-20.eml
|
|
436
442
|
# Action: failed
|
|
437
443
|
# Final-Recipient: rfc822;userx@test.ex
|
|
438
444
|
# Status: 5.0.0
|
|
439
445
|
# Remote-MTA: dns; 127.0.0.1
|
|
440
446
|
# Diagnostic-Code: smtp; 450 TEMPERROR: retry timeout exceeded
|
|
441
|
-
#
|
|
442
|
-
# of SMTP reply code in
|
|
443
|
-
|
|
444
|
-
|
|
447
|
+
#
|
|
448
|
+
# The value of "Status:" indicates permanent error but the value of SMTP reply code in
|
|
449
|
+
# Diagnostic-Code: field is "TEMPERROR"!!!!
|
|
450
|
+
cs = e['status'] || Sisimai::SMTP::Status.find(e['diagnosis'])
|
|
451
|
+
cr = e['replycode'] || Sisimai::SMTP::Reply.find(e['diagnosis'])
|
|
445
452
|
s1 = 0 # First character of Status as integer
|
|
446
453
|
r1 = 0 # First character of SMTP reply code as integer
|
|
447
454
|
|
|
448
455
|
while true
|
|
449
456
|
# "Status:" field did not exist in the bounce message
|
|
450
|
-
break if
|
|
451
|
-
break unless
|
|
457
|
+
break if cs
|
|
458
|
+
break unless cr
|
|
452
459
|
|
|
453
|
-
# Check SMTP reply code
|
|
454
|
-
|
|
455
|
-
r1 = rv[0, 1].to_i
|
|
460
|
+
# Check SMTP reply code, Generate pseudo DSN code from SMTP reply code
|
|
461
|
+
r1 = cr[0, 1].to_i
|
|
456
462
|
if r1 == 4
|
|
457
463
|
# Get the internal DSN(temporary error)
|
|
458
|
-
|
|
464
|
+
cs = Sisimai::SMTP::Status.code(e['reason'], true)
|
|
459
465
|
|
|
460
466
|
elsif r1 == 5
|
|
461
467
|
# Get the internal DSN(permanent error)
|
|
462
|
-
|
|
468
|
+
cs = Sisimai::SMTP::Status.code(e['reason'], false)
|
|
463
469
|
end
|
|
464
470
|
break
|
|
465
471
|
end
|
|
466
472
|
|
|
467
|
-
s1 =
|
|
473
|
+
s1 = cs[0, 1].to_i if cs
|
|
468
474
|
v1 = s1 + r1
|
|
469
475
|
v1 << e['status'][0, 1].to_i if e['status']
|
|
470
476
|
|
|
471
477
|
if v1 > 0
|
|
472
|
-
# Status or SMTP reply code exists
|
|
473
|
-
|
|
474
|
-
e['status'] = sv if r1 > 0
|
|
478
|
+
# Status or SMTP reply code exists, Set pseudo DSN into the value of "status" accessor
|
|
479
|
+
e['status'] = cs if r1 > 0
|
|
475
480
|
else
|
|
476
481
|
# Neither Status nor SMTP reply code exist
|
|
477
|
-
|
|
482
|
+
cs = if %w[expired mailboxfull].include?(e['reason'])
|
|
478
483
|
# Set pseudo DSN (temporary error)
|
|
479
484
|
Sisimai::SMTP::Status.code(e['reason'], true)
|
|
480
485
|
else
|
|
@@ -482,10 +487,10 @@ module Sisimai::Lhost
|
|
|
482
487
|
Sisimai::SMTP::Status.code(e['reason'], false)
|
|
483
488
|
end
|
|
484
489
|
end
|
|
485
|
-
e['status'] ||=
|
|
490
|
+
e['status'] ||= cs.to_s
|
|
486
491
|
end
|
|
487
492
|
|
|
488
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
|
493
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
489
494
|
end
|
|
490
495
|
def description; return 'Exim'; end
|
|
491
496
|
end
|