sisimai 4.22.3-java → 4.22.4-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 +1 -1
- data/Benchmarks.mk +54 -0
- data/ChangeLog.md +23 -2
- data/Developers.mk +42 -35
- data/Makefile +10 -0
- data/README-JA.md +13 -13
- data/README.md +14 -14
- data/lib/sisimai.rb +12 -18
- data/lib/sisimai/address.rb +64 -82
- data/lib/sisimai/arf.rb +27 -42
- data/lib/sisimai/bite/email.rb +2 -4
- data/lib/sisimai/bite/email/activehunter.rb +12 -17
- data/lib/sisimai/bite/email/amazonses.rb +30 -48
- data/lib/sisimai/bite/email/amazonworkmail.rb +20 -27
- data/lib/sisimai/bite/email/aol.rb +27 -35
- data/lib/sisimai/bite/email/apachejames.rb +17 -28
- data/lib/sisimai/bite/email/bigfoot.rb +20 -33
- data/lib/sisimai/bite/email/biglobe.rb +15 -24
- data/lib/sisimai/bite/email/courier.rb +37 -61
- data/lib/sisimai/bite/email/domino.rb +19 -28
- data/lib/sisimai/bite/email/einsundeins.rb +20 -34
- data/lib/sisimai/bite/email/exchange2003.rb +25 -43
- data/lib/sisimai/bite/email/exchange2007.rb +15 -23
- data/lib/sisimai/bite/email/exim.rb +101 -120
- data/lib/sisimai/bite/email/ezweb.rb +28 -44
- data/lib/sisimai/bite/email/facebook.rb +26 -37
- data/lib/sisimai/bite/email/fml.rb +11 -20
- data/lib/sisimai/bite/email/gmx.rb +17 -27
- data/lib/sisimai/bite/email/google.rb +19 -29
- data/lib/sisimai/bite/email/gsuite.rb +39 -48
- data/lib/sisimai/bite/email/imailserver.rb +25 -39
- data/lib/sisimai/bite/email/interscanmss.rb +19 -26
- data/lib/sisimai/bite/email/kddi.rb +20 -33
- data/lib/sisimai/bite/email/mailfoundry.rb +14 -24
- data/lib/sisimai/bite/email/mailmarshalsmtp.rb +15 -24
- data/lib/sisimai/bite/email/mailru.rb +40 -59
- data/lib/sisimai/bite/email/mcafee.rb +21 -35
- data/lib/sisimai/bite/email/messagelabs.rb +23 -38
- data/lib/sisimai/bite/email/messagingserver.rb +15 -27
- data/lib/sisimai/bite/email/mfilter.rb +19 -28
- data/lib/sisimai/bite/email/mxlogic.rb +31 -49
- data/lib/sisimai/bite/email/notes.rb +16 -24
- data/lib/sisimai/bite/email/office365.rb +29 -38
- data/lib/sisimai/bite/email/opensmtpd.rb +50 -67
- data/lib/sisimai/bite/email/outlook.rb +24 -36
- data/lib/sisimai/bite/email/postfix.rb +33 -42
- data/lib/sisimai/bite/email/qmail.rb +44 -59
- data/lib/sisimai/bite/email/receivingses.rb +28 -36
- data/lib/sisimai/bite/email/sendgrid.rb +28 -37
- data/lib/sisimai/bite/email/sendmail.rb +35 -51
- data/lib/sisimai/bite/email/surfcontrol.rb +17 -25
- data/lib/sisimai/bite/email/userdefined.rb +17 -28
- data/lib/sisimai/bite/email/v5sendmail.rb +32 -41
- data/lib/sisimai/bite/email/verizon.rb +31 -56
- data/lib/sisimai/bite/email/x1.rb +11 -18
- data/lib/sisimai/bite/email/x2.rb +11 -23
- data/lib/sisimai/bite/email/x3.rb +10 -19
- data/lib/sisimai/bite/email/x4.rb +46 -65
- data/lib/sisimai/bite/email/x5.rb +26 -37
- data/lib/sisimai/bite/email/yahoo.rb +11 -19
- data/lib/sisimai/bite/email/yandex.rb +19 -30
- data/lib/sisimai/bite/email/zoho.rb +21 -30
- data/lib/sisimai/bite/json.rb +1 -2
- data/lib/sisimai/bite/json/amazonses.rb +20 -25
- data/lib/sisimai/bite/json/sendgrid.rb +1 -1
- data/lib/sisimai/data.rb +36 -55
- data/lib/sisimai/data/json.rb +3 -3
- data/lib/sisimai/data/yaml.rb +1 -1
- data/lib/sisimai/datetime.rb +5 -21
- data/lib/sisimai/mail.rb +4 -6
- data/lib/sisimai/mail/maildir.rb +1 -1
- data/lib/sisimai/mda.rb +41 -44
- data/lib/sisimai/message.rb +2 -3
- data/lib/sisimai/message/email.rb +42 -52
- data/lib/sisimai/message/json.rb +7 -7
- data/lib/sisimai/mime.rb +25 -23
- data/lib/sisimai/order/email.rb +2 -2
- data/lib/sisimai/order/json.rb +2 -7
- data/lib/sisimai/reason.rb +41 -46
- data/lib/sisimai/reason/blocked.rb +60 -71
- data/lib/sisimai/reason/contenterror.rb +4 -8
- data/lib/sisimai/reason/delivered.rb +1 -3
- data/lib/sisimai/reason/exceedlimit.rb +10 -20
- data/lib/sisimai/reason/expired.rb +5 -9
- data/lib/sisimai/reason/feedback.rb +1 -3
- data/lib/sisimai/reason/filtered.rb +19 -38
- data/lib/sisimai/reason/hasmoved.rb +5 -8
- data/lib/sisimai/reason/hostunknown.rb +11 -18
- data/lib/sisimai/reason/mailboxfull.rb +14 -24
- data/lib/sisimai/reason/mailererror.rb +3 -5
- data/lib/sisimai/reason/mesgtoobig.rb +15 -25
- data/lib/sisimai/reason/networkerror.rb +8 -10
- data/lib/sisimai/reason/norelaying.rb +9 -14
- data/lib/sisimai/reason/notaccept.rb +9 -21
- data/lib/sisimai/reason/onhold.rb +3 -8
- data/lib/sisimai/reason/policyviolation.rb +8 -10
- data/lib/sisimai/reason/rejected.rb +36 -49
- data/lib/sisimai/reason/securityerror.rb +11 -13
- data/lib/sisimai/reason/spamdetected.rb +23 -37
- data/lib/sisimai/reason/suspend.rb +9 -10
- data/lib/sisimai/reason/syntaxerror.rb +3 -4
- data/lib/sisimai/reason/systemerror.rb +7 -9
- data/lib/sisimai/reason/systemfull.rb +2 -4
- data/lib/sisimai/reason/toomanyconn.rb +17 -30
- data/lib/sisimai/reason/undefined.rb +1 -3
- data/lib/sisimai/reason/userunknown.rb +28 -38
- data/lib/sisimai/reason/vacation.rb +4 -6
- data/lib/sisimai/reason/virusdetected.rb +4 -6
- data/lib/sisimai/rfc2606.rb +1 -2
- data/lib/sisimai/rfc3464.rb +87 -101
- data/lib/sisimai/rfc3834.rb +29 -39
- data/lib/sisimai/rfc5322.rb +17 -24
- data/lib/sisimai/rhost.rb +10 -7
- data/lib/sisimai/rhost/exchangeonline.rb +124 -255
- data/lib/sisimai/rhost/franceptt.rb +2 -2
- data/lib/sisimai/rhost/godaddy.rb +12 -25
- data/lib/sisimai/rhost/googleapps.rb +82 -183
- data/lib/sisimai/smtp.rb +4 -4
- data/lib/sisimai/smtp/error.rb +8 -8
- data/lib/sisimai/smtp/reply.rb +1 -1
- data/lib/sisimai/smtp/status.rb +1 -0
- data/lib/sisimai/string.rb +5 -7
- data/lib/sisimai/version.rb +1 -1
- data/set-of-emails/README.md +1 -1
- data/set-of-emails/maildir/bsd/README.md +50 -50
- data/sisimai-java.gemspec +1 -1
- data/sisimai.gemspec +1 -1
- metadata +4 -4
- data/lib/sisimai/skeleton.rb +0 -43
@@ -6,59 +6,46 @@ module Sisimai::Bite::Email
|
|
6
6
|
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/OpenSMTPD.pm
|
7
7
|
require 'sisimai/bite/email'
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
# bounce.c/339:
|
39
|
-
Re1 = {
|
40
|
-
:begin => %r/\A[ \t]*This is the MAILER-DAEMON, please DO NOT REPLY to this e[-]?mail[.]\z/,
|
41
|
-
:rfc822 => %r/\A[ \t]*Below is a copy of the original message:\z/,
|
42
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
9
|
+
Indicators = Sisimai::Bite::Email.INDICATORS
|
10
|
+
StartingOf = {
|
11
|
+
# http://www.openbsd.org/cgi-bin/man.cgi?query=smtpd&sektion=8
|
12
|
+
# opensmtpd-5.4.2p1/smtpd/
|
13
|
+
# bounce.c/317:#define NOTICE_INTRO \
|
14
|
+
# bounce.c/318: " Hi!\n\n" \
|
15
|
+
# bounce.c/319: " This is the MAILER-DAEMON, please DO NOT REPLY to this e-mail.\n"
|
16
|
+
# bounce.c/320:
|
17
|
+
# bounce.c/321:const char *notice_error =
|
18
|
+
# bounce.c/322: " An error has occurred while attempting to deliver a message for\n"
|
19
|
+
# bounce.c/323: " the following list of recipients:\n\n";
|
20
|
+
# bounce.c/324:
|
21
|
+
# bounce.c/325:const char *notice_warning =
|
22
|
+
# bounce.c/326: " A message is delayed for more than %s for the following\n"
|
23
|
+
# bounce.c/327: " list of recipients:\n\n";
|
24
|
+
# bounce.c/328:
|
25
|
+
# bounce.c/329:const char *notice_warning2 =
|
26
|
+
# bounce.c/330: " Please note that this is only a temporary failure report.\n"
|
27
|
+
# bounce.c/331: " The message is kept in the queue for up to %s.\n"
|
28
|
+
# bounce.c/332: " You DO NOT NEED to re-send the message to these recipients.\n\n";
|
29
|
+
# bounce.c/333:
|
30
|
+
# bounce.c/334:const char *notice_success =
|
31
|
+
# bounce.c/335: " Your message was successfully delivered to these recipients.\n\n";
|
32
|
+
# bounce.c/336:
|
33
|
+
# bounce.c/337:const char *notice_relay =
|
34
|
+
# bounce.c/338: " Your message was relayed to these recipients.\n\n";
|
35
|
+
# bounce.c/339:
|
36
|
+
message: [' This is the MAILER-DAEMON, please DO NOT REPLY to this '],
|
37
|
+
rfc822: [' Below is a copy of the original message:'],
|
43
38
|
}.freeze
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
hostunknown: %r
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|Domain[ ]does[ ]not[ ]exist
|
54
|
-
)
|
55
|
-
}x,
|
56
|
-
notaccept: %r{
|
57
|
-
# smtp/mta.c:1085| relay->failstr = "Destination seem to reject all mails";
|
58
|
-
Destination[ ]seem[ ]to[ ]reject[ ]all[ ]mails
|
59
|
-
}x,
|
39
|
+
ReFailures = {
|
40
|
+
# smtpd/queue.c:221| envelope_set_errormsg(&evp, "Envelope expired");
|
41
|
+
expired: %r/Envelope expired/,
|
42
|
+
# smtpd/mta.c:976| relay->failstr = "Invalid domain name";
|
43
|
+
# smtpd/mta.c:980| relay->failstr = "Domain does not exist";
|
44
|
+
hostunknown: %r/(?:Invalid domain name|Domain does not exist)/,
|
45
|
+
# smtp/mta.c:1085| relay->failstr = "Destination seem to reject all mails";
|
46
|
+
notaccept: %r/Destination seem to reject all mails/,
|
47
|
+
# smtpd/mta.c:972| relay->failstr = "Temporary failure in MX lookup";
|
60
48
|
networkerror: %r{(?>
|
61
|
-
# smtpd/mta.c:972| relay->failstr = "Temporary failure in MX lookup";
|
62
49
|
Address[ ]family[ ]mismatch[ ]on[ ]destination[ ]MXs
|
63
50
|
|All[ ]routes[ ]to[ ]destination[ ]blocked
|
64
51
|
|bad[ ]DNS[ ]lookup[ ]error[ ]code
|
@@ -72,17 +59,13 @@ module Sisimai::Bite::Email
|
|
72
59
|
|Temporary[ ]failure[ ]in[ ]MX[ ]lookup
|
73
60
|
)
|
74
61
|
}x,
|
75
|
-
|
76
|
-
|
77
|
-
Could[ ]not[ ]retrieve[ ]credentials
|
78
|
-
}x,
|
62
|
+
# smtpd/mta.c:1013| relay->failstr = "Could not retrieve credentials";
|
63
|
+
securityerror: %r/Could not retrieve credentials/,
|
79
64
|
}.freeze
|
80
|
-
Indicators = Sisimai::Bite::Email.INDICATORS
|
81
65
|
|
82
66
|
def description; return 'OpenSMTPD'; end
|
83
67
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
84
68
|
def headerlist; return []; end
|
85
|
-
def pattern; return Re0; end
|
86
69
|
|
87
70
|
# Parse bounce messages from OpenSMTPD
|
88
71
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -98,9 +81,10 @@ module Sisimai::Bite::Email
|
|
98
81
|
def scan(mhead, mbody)
|
99
82
|
return nil unless mhead
|
100
83
|
return nil unless mbody
|
101
|
-
|
102
|
-
return nil unless mhead['
|
103
|
-
return nil unless mhead['
|
84
|
+
|
85
|
+
return nil unless mhead['subject'].start_with?('Delivery status notification')
|
86
|
+
return nil unless mhead['from'].start_with?('Mailer Daemon <')
|
87
|
+
return nil unless mhead['received'].find { |a| a.include?(' (OpenSMTPD) with ') }
|
104
88
|
|
105
89
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
106
90
|
hasdivided = mbody.split("\n")
|
@@ -110,10 +94,10 @@ module Sisimai::Bite::Email
|
|
110
94
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
111
95
|
v = nil
|
112
96
|
|
113
|
-
hasdivided.
|
97
|
+
while e = hasdivided.shift do
|
114
98
|
if readcursor.zero?
|
115
99
|
# Beginning of the bounce message or delivery status part
|
116
|
-
if e
|
100
|
+
if e.include?(StartingOf[:message][0])
|
117
101
|
readcursor |= Indicators[:deliverystatus]
|
118
102
|
next
|
119
103
|
end
|
@@ -121,7 +105,7 @@ module Sisimai::Bite::Email
|
|
121
105
|
|
122
106
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
123
107
|
# Beginning of the original message part
|
124
|
-
if e
|
108
|
+
if e.include?(StartingOf[:rfc822][0])
|
125
109
|
readcursor |= Indicators[:'message-rfc822']
|
126
110
|
next
|
127
111
|
end
|
@@ -135,7 +119,6 @@ module Sisimai::Bite::Email
|
|
135
119
|
next
|
136
120
|
end
|
137
121
|
rfc822list << e
|
138
|
-
|
139
122
|
else
|
140
123
|
# Before "message/rfc822"
|
141
124
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
@@ -167,15 +150,15 @@ module Sisimai::Bite::Email
|
|
167
150
|
end
|
168
151
|
end
|
169
152
|
return nil if recipients.zero?
|
170
|
-
require 'sisimai/string'
|
171
153
|
|
154
|
+
require 'sisimai/string'
|
172
155
|
dscontents.map do |e|
|
173
156
|
e['agent'] = self.smtpagent
|
174
157
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
175
158
|
|
176
|
-
|
159
|
+
ReFailures.each_key do |r|
|
177
160
|
# Verify each regular expression of session errors
|
178
|
-
next unless e['diagnosis'] =~
|
161
|
+
next unless e['diagnosis'] =~ ReFailures[r]
|
179
162
|
e['reason'] = r.to_s
|
180
163
|
break
|
181
164
|
end
|
@@ -7,22 +7,15 @@ module Sisimai::Bite::Email
|
|
7
7
|
# Imported from p5-Sisimail/lib/Sisimai/Bite/Email/US/Outlook.pm
|
8
8
|
require 'sisimai/bite/email'
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
:
|
13
|
-
:
|
14
|
-
}.freeze
|
15
|
-
Re1 = {
|
16
|
-
:begin => %r/\AThis is an automatically generated Delivery Status Notification/,
|
17
|
-
:error => %r/\A[.]+ while talking to .+[:]\z/,
|
18
|
-
:rfc822 => %r|\AContent-Type: message/rfc822\z|,
|
19
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
10
|
+
Indicators = Sisimai::Bite::Email.INDICATORS
|
11
|
+
StartingOf = {
|
12
|
+
message: ['This is an automatically generated Delivery Status Notification'],
|
13
|
+
rfc822: ['Content-Type: message/rfc822'],
|
20
14
|
}.freeze
|
21
|
-
|
15
|
+
ReFailures = {
|
22
16
|
hostunknown: %r/The mail could not be delivered to the recipient because the domain is not reachable/,
|
23
17
|
userunknown: %r/Requested action not taken: mailbox unavailable/,
|
24
18
|
}.freeze
|
25
|
-
Indicators = Sisimai::Bite::Email.INDICATORS
|
26
19
|
|
27
20
|
def description; return 'Microsoft Outlook.com: https://www.outlook.com/'; end
|
28
21
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
@@ -30,7 +23,6 @@ module Sisimai::Bite::Email
|
|
30
23
|
# X-Message-Delivery: Vj0xLjE7RD0wO0dEPTA7U0NMPTk7bD0xO3VzPTE=
|
31
24
|
# X-Message-Info: AuEzbeVr9u5fkDpn2vR5iCu5wb6HBeY4iruBjnutBzpStnUabbM...
|
32
25
|
def headerlist; return ['X-Message-Delivery', 'X-Message-Info']; end
|
33
|
-
def pattern; return Re0; end
|
34
26
|
|
35
27
|
# Parse bounce messages from Microsoft Outlook.com
|
36
28
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -47,11 +39,12 @@ module Sisimai::Bite::Email
|
|
47
39
|
return nil unless mhead
|
48
40
|
return nil unless mbody
|
49
41
|
|
42
|
+
# :from => %r/postmaster[@]/,
|
50
43
|
match = 0
|
51
|
-
match += 1 if mhead['subject']
|
44
|
+
match += 1 if mhead['subject'].include?('Delivery Status Notification')
|
52
45
|
match += 1 if mhead['x-message-delivery']
|
53
46
|
match += 1 if mhead['x-message-info']
|
54
|
-
match += 1 if mhead['received'].find { |a| a
|
47
|
+
match += 1 if mhead['received'].find { |a| a.include?('.hotmail.com') }
|
55
48
|
return nil if match < 2
|
56
49
|
|
57
50
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
@@ -68,14 +61,14 @@ module Sisimai::Bite::Email
|
|
68
61
|
}
|
69
62
|
v = nil
|
70
63
|
|
71
|
-
hasdivided.
|
64
|
+
while e = hasdivided.shift do
|
72
65
|
# Save the current line for the next loop
|
73
66
|
havepassed << e
|
74
67
|
p = havepassed[-2]
|
75
68
|
|
76
69
|
if readcursor.zero?
|
77
70
|
# Beginning of the bounce message or delivery status part
|
78
|
-
if e
|
71
|
+
if e.start_with?(StartingOf[:message][0])
|
79
72
|
readcursor |= Indicators[:deliverystatus]
|
80
73
|
next
|
81
74
|
end
|
@@ -83,7 +76,7 @@ module Sisimai::Bite::Email
|
|
83
76
|
|
84
77
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
85
78
|
# Beginning of the original message part
|
86
|
-
if e
|
79
|
+
if e == StartingOf[:rfc822][0]
|
87
80
|
readcursor |= Indicators[:'message-rfc822']
|
88
81
|
next
|
89
82
|
end
|
@@ -97,7 +90,6 @@ module Sisimai::Bite::Email
|
|
97
90
|
next
|
98
91
|
end
|
99
92
|
rfc822list << e
|
100
|
-
|
101
93
|
else
|
102
94
|
# Before "message/rfc822"
|
103
95
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
@@ -116,7 +108,7 @@ module Sisimai::Bite::Email
|
|
116
108
|
# Diagnostic-Code: smtp;550 5.2.2 <kijitora@example.jp>... Mailbox Full
|
117
109
|
v = dscontents[-1]
|
118
110
|
|
119
|
-
if cv = e.match(/\
|
111
|
+
if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
|
120
112
|
# Final-Recipient: rfc822;kijitora@example.jp
|
121
113
|
if v['recipient']
|
122
114
|
# There are multiple recipient addresses in the message body.
|
@@ -126,39 +118,36 @@ module Sisimai::Bite::Email
|
|
126
118
|
v['recipient'] = cv[1]
|
127
119
|
recipients += 1
|
128
120
|
|
129
|
-
elsif cv = e.match(/\
|
121
|
+
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
130
122
|
# Action: failed
|
131
123
|
v['action'] = cv[1].downcase
|
132
124
|
|
133
|
-
elsif cv = e.match(/\
|
125
|
+
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
134
126
|
# Status:5.2.0
|
135
127
|
v['status'] = cv[1]
|
136
|
-
|
137
128
|
else
|
138
|
-
if cv = e.match(/\
|
129
|
+
if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
|
139
130
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
140
131
|
v['spec'] = cv[1].upcase
|
141
132
|
v['diagnosis'] = cv[2]
|
142
133
|
|
143
|
-
elsif p
|
134
|
+
elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
144
135
|
# Continued line of the value of Diagnostic-Code header
|
145
|
-
v['diagnosis']
|
146
|
-
|
147
|
-
havepassed[-1] = 'Diagnostic-Code: ' + e
|
136
|
+
v['diagnosis'] << ' ' << cv[1]
|
137
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
148
138
|
end
|
149
|
-
|
150
139
|
end
|
151
140
|
else
|
152
141
|
# Reporting-MTA: dns;BLU004-OMC3S13.hotmail.example.com
|
153
142
|
# Received-From-MTA: dns;BLU436-SMTP66
|
154
143
|
# Arrival-Date: Fri, 21 Nov 2014 14:17:34 -0800
|
155
|
-
if cv = e.match(/\
|
144
|
+
if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
156
145
|
# Reporting-MTA: dns;BLU004-OMC3S13.hotmail.example.com
|
157
146
|
next if connheader['lhost'].size > 0
|
158
147
|
connheader['lhost'] = cv[1].downcase
|
159
148
|
connvalues += 1
|
160
149
|
|
161
|
-
elsif cv = e.match(/\
|
150
|
+
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
162
151
|
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
163
152
|
next if connheader['date'].size > 0
|
164
153
|
connheader['date'] = cv[1]
|
@@ -168,8 +157,8 @@ module Sisimai::Bite::Email
|
|
168
157
|
end
|
169
158
|
end
|
170
159
|
return nil if recipients.zero?
|
171
|
-
require 'sisimai/string'
|
172
160
|
|
161
|
+
require 'sisimai/string'
|
173
162
|
dscontents.map do |e|
|
174
163
|
# Set default values if each value is empty.
|
175
164
|
connheader.each_key { |a| e[a] ||= connheader[a] || '' }
|
@@ -181,17 +170,16 @@ module Sisimai::Bite::Email
|
|
181
170
|
if e['action'] == 'delayed'
|
182
171
|
# Set pseudo diagnostic code message for delaying
|
183
172
|
e['diagnosis'] = 'Delivery to the following recipients has been delayed.'
|
184
|
-
|
185
173
|
else
|
186
174
|
# Set pseudo diagnostic code message
|
187
175
|
e['diagnosis'] = 'Unable to deliver message to the following recipients, '
|
188
|
-
e['diagnosis']
|
176
|
+
e['diagnosis'] << 'due to being unable to connect successfully to the destination mail server.'
|
189
177
|
end
|
190
178
|
end
|
191
179
|
|
192
|
-
|
180
|
+
ReFailures.each_key do |r|
|
193
181
|
# Verify each regular expression of session errors
|
194
|
-
next unless e['diagnosis'] =~
|
182
|
+
next unless e['diagnosis'] =~ ReFailures[r]
|
195
183
|
e['reason'] = r.to_s
|
196
184
|
break
|
197
185
|
end
|
@@ -7,12 +7,10 @@ module Sisimai::Bite::Email
|
|
7
7
|
require 'sisimai/bite/email'
|
8
8
|
|
9
9
|
# Postfix manual - bounce(5) - http://www.postfix.org/bounce.5.html
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
Re1 = {
|
15
|
-
:begin => %r{\A(?>
|
10
|
+
Indicators = Sisimai::Bite::Email.INDICATORS
|
11
|
+
StartingOf = { rfc822: ['Content-Type: message/rfc822', 'Content-Type: text/rfc822-headers'] }.freeze
|
12
|
+
MarkingsOf = {
|
13
|
+
message: %r{\A(?>
|
16
14
|
[ ]+The[ ](?:
|
17
15
|
Postfix[ ](?:
|
18
16
|
program\z # The Postfix program
|
@@ -30,15 +28,11 @@ module Sisimai::Bite::Email
|
|
30
28
|
)
|
31
29
|
)
|
32
30
|
}x,
|
33
|
-
:rfc822 => %r!\AContent-Type:[ \t]*(?:message/rfc822|text/rfc822-headers)\z!x,
|
34
|
-
:endof => %r/\A__END_OF_EMAIL_MESSAGE__\z/,
|
35
31
|
}.freeze
|
36
|
-
Indicators = Sisimai::Bite::Email.INDICATORS
|
37
32
|
|
38
33
|
def description; return 'Postfix'; end
|
39
34
|
def smtpagent; return Sisimai::Bite.smtpagent(self); end
|
40
35
|
def headerlist; return []; end
|
41
|
-
def pattern; return Re0; end
|
42
36
|
|
43
37
|
# Parse bounce messages from Postfix
|
44
38
|
# @param [Hash] mhead Message headers of a bounce email
|
@@ -54,7 +48,9 @@ module Sisimai::Bite::Email
|
|
54
48
|
def scan(mhead, mbody)
|
55
49
|
return nil unless mhead
|
56
50
|
return nil unless mbody
|
57
|
-
|
51
|
+
|
52
|
+
# :from => %r/ [(]Mail Delivery System[)]\z/,
|
53
|
+
return nil unless mhead['subject'] == 'Undelivered Mail Returned to Sender'
|
58
54
|
|
59
55
|
dscontents = [Sisimai::Bite.DELIVERYSTATUS]
|
60
56
|
hasdivided = mbody.split("\n")
|
@@ -72,14 +68,14 @@ module Sisimai::Bite::Email
|
|
72
68
|
anotherset = {} # Another error information
|
73
69
|
v = nil
|
74
70
|
|
75
|
-
hasdivided.
|
71
|
+
while e = hasdivided.shift do
|
76
72
|
# Save the current line for the next loop
|
77
73
|
havepassed << e
|
78
74
|
p = havepassed[-2]
|
79
75
|
|
80
76
|
if readcursor.zero?
|
81
77
|
# Beginning of the bounce message or delivery status part
|
82
|
-
if e =~
|
78
|
+
if e =~ MarkingsOf[:message]
|
83
79
|
readcursor |= Indicators[:deliverystatus]
|
84
80
|
next
|
85
81
|
end
|
@@ -87,7 +83,7 @@ module Sisimai::Bite::Email
|
|
87
83
|
|
88
84
|
if (readcursor & Indicators[:'message-rfc822']).zero?
|
89
85
|
# Beginning of the original message part
|
90
|
-
if e
|
86
|
+
if e.start_with?(StartingOf[:rfc822][0], StartingOf[:rfc822][1])
|
91
87
|
readcursor |= Indicators[:'message-rfc822']
|
92
88
|
next
|
93
89
|
end
|
@@ -101,7 +97,6 @@ module Sisimai::Bite::Email
|
|
101
97
|
next
|
102
98
|
end
|
103
99
|
rfc822list << e
|
104
|
-
|
105
100
|
else
|
106
101
|
# Before "message/rfc822"
|
107
102
|
next if (readcursor & Indicators[:deliverystatus]).zero?
|
@@ -116,7 +111,7 @@ module Sisimai::Bite::Email
|
|
116
111
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
117
112
|
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
118
113
|
v = dscontents[-1]
|
119
|
-
if cv = e.match(/\
|
114
|
+
if cv = e.match(/\AFinal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*(.+)\z/)
|
120
115
|
# Final-Recipient: RFC822; userunknown@example.jp
|
121
116
|
if v['recipient']
|
122
117
|
# There are multiple recipient addresses in the message body.
|
@@ -126,27 +121,27 @@ module Sisimai::Bite::Email
|
|
126
121
|
v['recipient'] = cv[1]
|
127
122
|
recipients += 1
|
128
123
|
|
129
|
-
elsif cv = e.match(/\
|
130
|
-
e.match(/\
|
124
|
+
elsif cv = e.match(/\AX-Actual-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/) ||
|
125
|
+
e.match(/\AOriginal-Recipient:[ ]*(?:RFC|rfc)822;[ ]*([^ ]+)\z/)
|
131
126
|
# X-Actual-Recipient: RFC822; kijitora@example.co.jp
|
132
127
|
# Original-Recipient: rfc822;kijitora@example.co.jp
|
133
128
|
v['alias'] = cv[1]
|
134
129
|
|
135
|
-
elsif cv = e.match(/\
|
130
|
+
elsif cv = e.match(/\AAction:[ ]*(.+)\z/)
|
136
131
|
# Action: failed
|
137
132
|
v['action'] = cv[1].downcase
|
138
133
|
|
139
|
-
elsif cv = e.match(/\
|
134
|
+
elsif cv = e.match(/\AStatus:[ ]*(\d[.]\d+[.]\d+)/)
|
140
135
|
# Status: 5.1.1
|
141
136
|
# Status:5.2.0
|
142
137
|
# Status: 5.1.0 (permanent failure)
|
143
138
|
v['status'] = cv[1]
|
144
139
|
|
145
|
-
elsif cv = e.match(/\
|
140
|
+
elsif cv = e.match(/\ARemote-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
146
141
|
# Remote-MTA: DNS; mx.example.jp
|
147
142
|
v['rhost'] = cv[1].downcase
|
148
143
|
|
149
|
-
elsif cv = e.match(/\
|
144
|
+
elsif cv = e.match(/\ALast-Attempt-Date:[ ]*(.+)\z/)
|
150
145
|
# Last-Attempt-Date: Fri, 14 Feb 2014 12:30:08 -0500
|
151
146
|
#
|
152
147
|
# src/bounce/bounce_notify_util.c:
|
@@ -156,22 +151,19 @@ module Sisimai::Bite::Email
|
|
156
151
|
# 684 mail_date(dsn->time));
|
157
152
|
# 685 #endif
|
158
153
|
v['date'] = cv[1]
|
159
|
-
|
160
154
|
else
|
161
|
-
if cv = e.match(/\
|
155
|
+
if cv = e.match(/\ADiagnostic-Code:[ ]*(.+?);[ ]*(.+)\z/)
|
162
156
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
163
157
|
v['spec'] = cv[1].upcase
|
164
158
|
v['diagnosis'] = cv[2]
|
165
159
|
v['spec'] = 'SMTP' if v['spec'] == 'X-POSTFIX'
|
166
160
|
|
167
|
-
elsif p
|
161
|
+
elsif p.start_with?('Diagnostic-Code:') && cv = e.match(/\A[ \t]+(.+)\z/)
|
168
162
|
# Continued line of the value of Diagnostic-Code header
|
169
|
-
v['diagnosis']
|
170
|
-
|
171
|
-
havepassed[-1] = 'Diagnostic-Code: ' + e
|
163
|
+
v['diagnosis'] << ' ' << cv[1]
|
164
|
+
havepassed[-1] = 'Diagnostic-Code: ' << e
|
172
165
|
end
|
173
166
|
end
|
174
|
-
|
175
167
|
else
|
176
168
|
# If you do so, please include this problem report. You can
|
177
169
|
# delete your own text from the attached returned message.
|
@@ -185,22 +177,22 @@ module Sisimai::Bite::Email
|
|
185
177
|
# 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
|
186
178
|
commandset << cv[1]
|
187
179
|
anotherset['diagnosis'] ||= ''
|
188
|
-
anotherset['diagnosis']
|
180
|
+
anotherset['diagnosis'] << ' ' << e
|
189
181
|
|
190
182
|
elsif cv = e.match(/([A-Z]{4})[ \t]*.*command[)]\z/)
|
191
183
|
# to MAIL command)
|
192
184
|
commandset << cv[1]
|
193
185
|
anotherset['diagnosis'] ||= ''
|
194
|
-
anotherset['diagnosis']
|
186
|
+
anotherset['diagnosis'] << ' ' << e
|
195
187
|
|
196
188
|
else
|
197
|
-
if cv = e.match(/\
|
189
|
+
if cv = e.match(/\AReporting-MTA:[ ]*(?:DNS|dns);[ ]*(.+)\z/)
|
198
190
|
# Reporting-MTA: dns; mx.example.jp
|
199
191
|
next if connheader['lhost'].size > 0
|
200
192
|
connheader['lhost'] = cv[1].downcase
|
201
193
|
connvalues += 1
|
202
194
|
|
203
|
-
elsif cv = e.match(/\
|
195
|
+
elsif cv = e.match(/\AArrival-Date:[ ]*(.+)\z/)
|
204
196
|
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
205
197
|
next if connheader['date'].size > 0
|
206
198
|
connheader['date'] = cv[1]
|
@@ -208,8 +200,7 @@ module Sisimai::Bite::Email
|
|
208
200
|
|
209
201
|
elsif cv = e.match(/\A(X-Postfix-Sender):[ ]*rfc822;[ ]*(.+)\z/)
|
210
202
|
# X-Postfix-Sender: rfc822; shironeko@example.org
|
211
|
-
rfc822list <<
|
212
|
-
|
203
|
+
rfc822list << (cv[1] << ': ' << cv[2])
|
213
204
|
else
|
214
205
|
# Alternative error message and recipient
|
215
206
|
if cv = e.match(/\A[<]([^ ]+[@][^ ]+)[>] [(]expanded from [<](.+)[>][)]:[ \t]*(.+)\z/)
|
@@ -222,16 +213,14 @@ module Sisimai::Bite::Email
|
|
222
213
|
# <kijitora@exmaple.jp>: ...
|
223
214
|
anotherset['recipient'] = cv[1]
|
224
215
|
anotherset['diagnosis'] = cv[2]
|
225
|
-
|
226
216
|
else
|
227
217
|
# Get error message continued from the previous line
|
228
218
|
next unless anotherset['diagnosis']
|
229
219
|
if e =~ /\A[ \t]{4}(.+)\z/
|
230
220
|
# host mx.example.jp said:...
|
231
|
-
anotherset['diagnosis']
|
221
|
+
anotherset['diagnosis'] << ' ' << e
|
232
222
|
end
|
233
223
|
end
|
234
|
-
|
235
224
|
end
|
236
225
|
end
|
237
226
|
end
|
@@ -240,7 +229,7 @@ module Sisimai::Bite::Email
|
|
240
229
|
|
241
230
|
if recipients.zero?
|
242
231
|
# Fallback: set recipient address from error message
|
243
|
-
if anotherset['recipient']
|
232
|
+
if anotherset['recipient'].to_s.size > 0
|
244
233
|
# Set recipient address
|
245
234
|
dscontents[-1]['recipient'] = anotherset['recipient']
|
246
235
|
recipients += 1
|
@@ -251,7 +240,6 @@ module Sisimai::Bite::Email
|
|
251
240
|
require 'sisimai/string'
|
252
241
|
require 'sisimai/smtp/status'
|
253
242
|
require 'sisimai/smtp/reply'
|
254
|
-
|
255
243
|
dscontents.map do |e|
|
256
244
|
# Set default values if each value is empty.
|
257
245
|
connheader.each_key { |a| e[a] ||= connheader[a] || '' }
|
@@ -270,7 +258,10 @@ module Sisimai::Bite::Email
|
|
270
258
|
as = nil # status
|
271
259
|
ar = nil # replycode
|
272
260
|
|
273
|
-
|
261
|
+
e['status'] ||= ''
|
262
|
+
e['replycode'] ||= ''
|
263
|
+
|
264
|
+
if e['status'] == '' || e['status'].start_with?('4.0.0', '5.0.0')
|
274
265
|
# Check the value of D.S.N. in anotherset
|
275
266
|
as = Sisimai::SMTP::Status.find(anotherset['diagnosis'])
|
276
267
|
if as.size > 0 && as[-3, 3] != '0.0'
|
@@ -279,7 +270,7 @@ module Sisimai::Bite::Email
|
|
279
270
|
end
|
280
271
|
end
|
281
272
|
|
282
|
-
if e['replycode'] == '' || e['replycode']
|
273
|
+
if e['replycode'] == '' || e['replycode'].start_with?('400', '500')
|
283
274
|
# Check the value of SMTP reply code in anotherset
|
284
275
|
ar = Sisimai::SMTP::Reply.find(anotherset['diagnosis'])
|
285
276
|
if ar.size > 0 && ar[-2, 2].to_i != 0
|