sisimai 4.25.17-java → 5.0.0-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/.travis.yml +3 -3
- data/ANALYTICAL-PRECISION +2 -2
- data/Benchmarks.mk +3 -3
- data/CONTRIBUTING +1 -1
- data/ChangeLog.md +406 -407
- data/Developers.mk +5 -6
- data/Gemfile +1 -1
- data/Makefile +12 -12
- data/README-JA.md +142 -94
- data/README.md +282 -150
- 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 +468 -0
- data/lib/sisimai/lhost/activehunter.rb +12 -14
- data/lib/sisimai/lhost/amavis.rb +11 -14
- data/lib/sisimai/lhost/amazonses.rb +37 -41
- data/lib/sisimai/lhost/amazonworkmail.rb +15 -18
- data/lib/sisimai/lhost/aol.rb +12 -14
- data/lib/sisimai/lhost/apachejames.rb +19 -21
- data/lib/sisimai/lhost/barracuda.rb +10 -12
- data/lib/sisimai/lhost/bigfoot.rb +21 -21
- data/lib/sisimai/lhost/biglobe.rb +15 -16
- data/lib/sisimai/lhost/courier.rb +20 -20
- data/lib/sisimai/lhost/domino.rb +23 -19
- data/lib/sisimai/lhost/einsundeins.rb +20 -16
- data/lib/sisimai/lhost/exchange2003.rb +30 -29
- data/lib/sisimai/lhost/exchange2007.rb +70 -58
- data/lib/sisimai/lhost/exim.rb +175 -161
- data/lib/sisimai/lhost/ezweb.rb +31 -56
- data/lib/sisimai/lhost/facebook.rb +21 -33
- 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 +9 -10
- data/lib/sisimai/lhost/gsuite.rb +21 -27
- 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 +33 -27
- data/lib/sisimai/lhost/mcafee.rb +21 -31
- data/lib/sisimai/lhost/messagelabs.rb +17 -20
- data/lib/sisimai/lhost/messagingserver.rb +40 -37
- data/lib/sisimai/lhost/mfilter.rb +15 -16
- data/lib/sisimai/lhost/mxlogic.rb +24 -23
- data/lib/sisimai/lhost/notes.rb +17 -17
- data/lib/sisimai/lhost/office365.rb +63 -27
- data/lib/sisimai/lhost/opensmtpd.rb +12 -13
- data/lib/sisimai/lhost/outlook.rb +12 -15
- data/lib/sisimai/lhost/postfix.rb +179 -129
- data/lib/sisimai/lhost/powermta.rb +12 -14
- data/lib/sisimai/lhost/qmail.rb +44 -47
- data/lib/sisimai/lhost/receivingses.rb +15 -20
- data/lib/sisimai/lhost/sendgrid.rb +34 -32
- data/lib/sisimai/lhost/sendmail.rb +66 -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 -20
- 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 +435 -325
- data/lib/sisimai/order.rb +5 -5
- data/lib/sisimai/reason/authfailure.rb +64 -0
- data/lib/sisimai/reason/badreputation.rb +53 -0
- data/lib/sisimai/reason/blocked.rb +94 -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 +6 -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 +10 -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 +33 -36
- data/lib/sisimai/reason/spamdetected.rb +114 -147
- data/lib/sisimai/reason/speeding.rb +49 -0
- data/lib/sisimai/reason/suspend.rb +11 -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 +75 -100
- 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/{googleapps.rb → google.rb} +80 -72
- 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 +42 -40
- data/lib/sisimai/rhost/nttdocomo.rb +13 -18
- 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 +504 -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 +35 -21
- 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/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 +42 -23
- 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/set-of-emails/maildir/mac/reported-from-nick4tech-san-01.eml +0 -6
- /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/ezweb.rb
CHANGED
@@ -1,41 +1,28 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::EZweb parses a bounce email which created by au EZweb.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::EZweb parses a bounce email which created by au EZweb. Methods in the module are
|
3
|
+
# called from only Sisimai::Message.
|
4
4
|
module EZweb
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/EZweb.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
11
|
-
MarkingsOf = {
|
12
|
-
message: %r{\A(?:
|
13
|
-
The[ ]user[(]s[)][ ]
|
14
|
-
|Your[ ]message[ ]
|
15
|
-
|Each[ ]of[ ]the[ ]following
|
16
|
-
|[<][^ ]+[@][^ ]+[>]\z
|
17
|
-
)
|
18
|
-
}x,
|
19
|
-
}.freeze
|
9
|
+
Boundaries = ['--------------------------------------------------', 'Content-Type: message/rfc822'].freeze
|
10
|
+
MarkingsOf = { message: ['The user(s) ', 'Your message ', 'Each of the following', '<'] }.freeze
|
20
11
|
ReFailures = {
|
21
|
-
# notaccept: [
|
22
|
-
'mailboxfull' => [
|
23
|
-
%r/The user[(]s[)] account is temporarily over quota/,
|
24
|
-
],
|
12
|
+
# notaccept: ['The following recipients did not receive this message:'],
|
13
|
+
'mailboxfull' => ['The user(s) account is temporarily over quota'],
|
25
14
|
'suspend' => [
|
26
15
|
# http://www.naruhodo-au.kddi.com/qa3429203.html
|
27
16
|
# The recipient may be unpaid user...?
|
28
|
-
|
29
|
-
|
17
|
+
'The user(s) account is disabled.',
|
18
|
+
'The user(s) account is temporarily limited.',
|
30
19
|
],
|
31
20
|
'expired' => [
|
32
21
|
# Your message was not delivered within 0 days and 1 hours.
|
33
22
|
# Remote host is not responding.
|
34
|
-
|
35
|
-
],
|
36
|
-
'onhold' => [
|
37
|
-
%r/Each of the following recipients was rejected by a remote mail server/,
|
23
|
+
'Your message was not delivered within ',
|
38
24
|
],
|
25
|
+
'onhold' => ['Each of the following recipients was rejected by a remote mail server'],
|
39
26
|
}.freeze
|
40
27
|
|
41
28
|
# Parse bounce messages from au EZweb
|
@@ -43,7 +30,7 @@ module Sisimai::Lhost
|
|
43
30
|
# @param [String] mbody Message body of a bounce email
|
44
31
|
# @return [Hash] Bounce data list and message/rfc822 part
|
45
32
|
# @return [Nil] it failed to parse or the arguments are missing
|
46
|
-
def
|
33
|
+
def inquire(mhead, mbody)
|
47
34
|
match = 0
|
48
35
|
match += 1 if mhead['from'].include?('Postmaster@ezweb.ne.jp')
|
49
36
|
match += 1 if mhead['from'].include?('Postmaster@au.com')
|
@@ -55,31 +42,21 @@ module Sisimai::Lhost
|
|
55
42
|
end
|
56
43
|
return nil if match < 2
|
57
44
|
|
58
|
-
require 'sisimai/rfc1894'
|
59
45
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
60
46
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
61
|
-
|
62
|
-
bodyslices =
|
47
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
48
|
+
bodyslices = emailparts[0].split("\n")
|
63
49
|
readcursor = 0 # (Integer) Points the current cursor position
|
64
50
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
65
|
-
|
51
|
+
rxmessages = []; ReFailures.each_value { |a| rxmessages << a }
|
66
52
|
v = nil
|
67
53
|
|
68
|
-
if mhead['content-type']
|
69
|
-
# Get the boundary string and set regular expression for matching with
|
70
|
-
# the boundary string.
|
71
|
-
b0 = Sisimai::MIME.boundary(mhead['content-type'], 1)
|
72
|
-
rxboundary = Regexp.new('\A' << Regexp.escape(b0) << '\z') unless b0.empty?
|
73
|
-
end
|
74
|
-
rxmessages = []
|
75
|
-
ReFailures.each_value { |a| rxmessages << a }
|
76
|
-
|
77
54
|
while e = bodyslices.shift do
|
78
|
-
# Read error messages and delivery status lines from the head of the email
|
79
|
-
#
|
55
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
56
|
+
# line of the beginning of the original message.
|
80
57
|
if readcursor == 0
|
81
58
|
# Beginning of the bounce message or delivery status part
|
82
|
-
readcursor |= Indicators[:deliverystatus] if
|
59
|
+
readcursor |= Indicators[:deliverystatus] if MarkingsOf[:message].any? { |a| e.include?(a) }
|
83
60
|
end
|
84
61
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
85
62
|
next if e.empty?
|
@@ -97,18 +74,17 @@ module Sisimai::Lhost
|
|
97
74
|
# <<< 550 <******@ezweb.ne.jp>: User unknown
|
98
75
|
v = dscontents[-1]
|
99
76
|
|
100
|
-
if
|
101
|
-
|
102
|
-
|
77
|
+
if Sisimai::String.aligned(e, ['<', '@', '>']) && (e.include?('Recipient: <') || e.start_with?('<'))
|
78
|
+
# Recipient: <******@ezweb.ne.jp> OR <***@ezweb.ne.jp>: 550 user unknown ...
|
79
|
+
p1 = e.index('<') || -1
|
80
|
+
p2 = e.index('>') || -1
|
103
81
|
|
104
82
|
if v['recipient']
|
105
83
|
# There are multiple recipient addresses in the message body.
|
106
84
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
107
85
|
v = dscontents[-1]
|
108
86
|
end
|
109
|
-
|
110
|
-
r = Sisimai::Address.s3s4(cv[1])
|
111
|
-
v['recipient'] = r
|
87
|
+
v['recipient'] = Sisimai::Address.s3s4(e[p1, p2 - p1])
|
112
88
|
recipients += 1
|
113
89
|
|
114
90
|
elsif f = Sisimai::RFC1894.match(e)
|
@@ -120,12 +96,12 @@ module Sisimai::Lhost
|
|
120
96
|
else
|
121
97
|
# The line does not begin with a DSN field defined in RFC3464
|
122
98
|
next if Sisimai::String.is_8bit(e)
|
123
|
-
if
|
99
|
+
if e.include?('>>> ')
|
124
100
|
# >>> RCPT TO:<******@ezweb.ne.jp>
|
125
|
-
v['command'] =
|
101
|
+
v['command'] = Sisimai::SMTP::Command.find(e) || ''
|
126
102
|
else
|
127
103
|
# Check error message
|
128
|
-
if rxmessages.any? { |messages| messages.any? { |message| e
|
104
|
+
if rxmessages.any? { |messages| messages.any? { |message| e.include?(message) } }
|
129
105
|
# Check with regular expressions of each error
|
130
106
|
v['diagnosis'] ||= ''
|
131
107
|
v['diagnosis'] << ' ' << e
|
@@ -149,7 +125,7 @@ module Sisimai::Lhost
|
|
149
125
|
end
|
150
126
|
e.delete('alterrors')
|
151
127
|
end
|
152
|
-
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
128
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
153
129
|
|
154
130
|
if mhead['x-spasign'].to_s == 'NG'
|
155
131
|
# Content-Type: text/plain; ..., X-SPASIGN: NG (spamghetti, au by EZweb)
|
@@ -157,17 +133,16 @@ module Sisimai::Lhost
|
|
157
133
|
e['reason'] = 'filtered'
|
158
134
|
else
|
159
135
|
if e['command'] == 'RCPT'
|
160
|
-
# set "userunknown" when the remote server rejected after RCPT
|
161
|
-
# command.
|
136
|
+
# set "userunknown" when the remote server rejected after RCPT command.
|
162
137
|
e['reason'] = 'userunknown'
|
163
138
|
else
|
164
139
|
# SMTP command is not RCPT
|
165
140
|
catch :SESSION do
|
166
141
|
ReFailures.each_key do |r|
|
167
|
-
#
|
142
|
+
# Try to match with each session error message
|
168
143
|
ReFailures[r].each do |rr|
|
169
|
-
# Check each
|
170
|
-
next unless e['diagnosis']
|
144
|
+
# Check each error message pattern
|
145
|
+
next unless e['diagnosis'].include?(rr)
|
171
146
|
e['reason'] = r
|
172
147
|
throw :SESSION
|
173
148
|
end
|
@@ -181,7 +156,7 @@ module Sisimai::Lhost
|
|
181
156
|
e['reason'] = 'userunknown'
|
182
157
|
end
|
183
158
|
|
184
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
159
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
185
160
|
end
|
186
161
|
def description; return 'au EZweb: http://www.au.kddi.com/mobile/'; end
|
187
162
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Facebook parses a bounce email which created by Facebook.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Facebook parses a bounce email which created by Facebook. Methods in the module
|
3
|
+
# are called from only Sisimai::Message.
|
4
4
|
module Facebook
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Facebook.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['Content-Disposition: inline'].freeze
|
11
10
|
StartingOf = { message: ['This message was created automatically by Facebook.'] }.freeze
|
12
11
|
ReFailures = {
|
13
12
|
# http://postmaster.facebook.com/response_codes
|
@@ -22,21 +21,20 @@ module Sisimai::Lhost
|
|
22
21
|
'RCP-P2', # The attempted recipient's preferences prevent messages from being delivered.
|
23
22
|
'RCP-P3', # The attempted recipient's privacy settings blocked the delivery.
|
24
23
|
],
|
25
|
-
'blocked' => [
|
26
|
-
'POL-P1', # Your mail server's IP Address is listed on the Spamhaus PBL.
|
27
|
-
'POL-P2', # Facebook will no longer accept mail from your mail server's IP Address.
|
28
|
-
],
|
29
24
|
'mesgtoobig' => [
|
30
25
|
'MSG-P1', # The message exceeds Facebook's maximum allowed size.
|
31
26
|
'INT-P2', # The message exceeds Facebook's maximum allowed size.
|
32
27
|
],
|
33
28
|
'contenterror' => [
|
34
29
|
'MSG-P2', # The message contains an attachment type that Facebook does not accept.
|
35
|
-
'MSG-P3', # The message contains multiple instances of a header field that can only be present once.
|
30
|
+
'MSG-P3', # The message contains multiple instances of a header field that can only be present once. Please see RFC 5322, section 3.6 for more information
|
36
31
|
'POL-P6', # The message contains a url that has been blocked by Facebook.
|
37
32
|
'POL-P7', # The message does not comply with Facebook's abuse policies and will not be accepted.
|
38
33
|
],
|
39
34
|
'securityerror' => [
|
35
|
+
'POL-P1', # Your mail server's IP Address is listed on the Spamhaus PBL.
|
36
|
+
'POL-P2', # Facebook will no longer accept mail from your mail server's IP Address.
|
37
|
+
'POL-P5', # The message contains a virus.
|
40
38
|
'POL-P7', # The message does not comply with Facebook's Domain Authentication requirements.
|
41
39
|
],
|
42
40
|
'notaccept' => [
|
@@ -55,20 +53,17 @@ module Sisimai::Lhost
|
|
55
53
|
],
|
56
54
|
'systemerror' => [
|
57
55
|
'CON-T1', # Facebook's mail server currently has too many connections open to allow another one.
|
58
|
-
'RCP-T1', # The attempted recipient address is not currently available due to an internal system issue. This is a temporary condition.
|
59
|
-
],
|
60
|
-
'virusdetected' => [
|
61
|
-
'POL-P5', # The message contains a virus.
|
62
56
|
],
|
63
57
|
'toomanyconn' => [
|
64
|
-
'CON-T2', # Your mail server currently has too many connections open to Facebook's mail servers.
|
65
58
|
'CON-T3', # Your mail server has opened too many new connections to Facebook's mail servers in a short period of time.
|
66
59
|
],
|
67
60
|
'suspend' => [
|
68
61
|
'RCP-T4', # The attempted recipient address is currently deactivated. The user may or may not reactivate it.
|
69
62
|
],
|
70
63
|
'undefined' => [
|
64
|
+
'RCP-T1', # The attempted recipient address is not currently available due to an internal system issue. This is a temporary condition.
|
71
65
|
'MSG-T1', # The number of recipients on the message exceeds Facebook's allowed maximum.
|
66
|
+
'CON-T2', # Your mail server currently has too many connections open to Facebook's mail servers.
|
72
67
|
'CON-T4', # Your mail server has exceeded the maximum number of recipients for its current connection.
|
73
68
|
],
|
74
69
|
}.freeze
|
@@ -78,17 +73,16 @@ module Sisimai::Lhost
|
|
78
73
|
# @param [String] mbody Message body of a bounce email
|
79
74
|
# @return [Hash] Bounce data list and message/rfc822 part
|
80
75
|
# @return [Nil] it failed to parse or the arguments are missing
|
81
|
-
def
|
76
|
+
def inquire(mhead, mbody)
|
82
77
|
return nil unless mhead['from'] == 'Facebook <mailer-daemon@mx.facebook.com>'
|
83
78
|
return nil unless mhead['subject'] == 'Sorry, your message could not be delivered'
|
84
79
|
|
85
|
-
require 'sisimai/rfc1894'
|
86
80
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
87
81
|
permessage = {} # (Hash) Store values of each Per-Message field
|
88
82
|
|
89
83
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
90
|
-
|
91
|
-
bodyslices =
|
84
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
85
|
+
bodyslices = emailparts[0].split("\n")
|
92
86
|
readslices = ['']
|
93
87
|
readcursor = 0 # (Integer) Points the current cursor position
|
94
88
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
@@ -96,8 +90,8 @@ module Sisimai::Lhost
|
|
96
90
|
v = nil
|
97
91
|
|
98
92
|
while e = bodyslices.shift do
|
99
|
-
# Read error messages and delivery status lines from the head of the email
|
100
|
-
#
|
93
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
94
|
+
# line of the beginning of the original message.
|
101
95
|
readslices << e # Save the current line for the next loop
|
102
96
|
|
103
97
|
if readcursor == 0
|
@@ -138,14 +132,14 @@ module Sisimai::Lhost
|
|
138
132
|
next unless fieldtable[o[0]]
|
139
133
|
v[fieldtable[o[0]]] = o[2]
|
140
134
|
|
141
|
-
next unless f
|
135
|
+
next unless f
|
142
136
|
permessage[fieldtable[o[0]]] = o[2]
|
143
137
|
end
|
144
138
|
else
|
145
139
|
# Continued line of the value of Diagnostic-Code field
|
146
140
|
next unless readslices[-2].start_with?('Diagnostic-Code:')
|
147
|
-
next unless
|
148
|
-
v['diagnosis'] << ' ' <<
|
141
|
+
next unless e.start_with?(' ')
|
142
|
+
v['diagnosis'] << ' ' << e[e.rindex(' ') + 1, e.size]
|
149
143
|
readslices[-1] = 'Diagnostic-Code: ' << e
|
150
144
|
end
|
151
145
|
end
|
@@ -155,14 +149,8 @@ module Sisimai::Lhost
|
|
155
149
|
e['lhost'] ||= permessage['lhost']
|
156
150
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
157
151
|
|
158
|
-
|
159
|
-
|
160
|
-
lhs = cv[1]
|
161
|
-
rhs = cv[2]
|
162
|
-
num = cv[3]
|
163
|
-
|
164
|
-
fbresponse = sprintf('%s-%s%d', lhs, rhs, num)
|
165
|
-
end
|
152
|
+
p0 = e['diagnosis'].index('-') || -1
|
153
|
+
fbresponse = e['diagnosis'][p0 - 3, 6] if p0 > 0
|
166
154
|
|
167
155
|
catch :SESSION do
|
168
156
|
ReFailures.each_key do |r|
|
@@ -188,11 +176,11 @@ module Sisimai::Lhost
|
|
188
176
|
# https://groups.google.com/forum/#!topic/cdmix/eXfi4ddgYLQ
|
189
177
|
# This block has not been tested because we have no email sample
|
190
178
|
# including "INT-T?" error code.
|
191
|
-
next unless fbresponse
|
179
|
+
next unless fbresponse.start_with?('INT-T')
|
192
180
|
e['reason'] = 'systemerror'
|
193
181
|
end
|
194
182
|
|
195
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
183
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
196
184
|
end
|
197
185
|
def description; return 'Facebook: https://www.facebook.com'; end
|
198
186
|
end
|
data/lib/sisimai/lhost/fml.rb
CHANGED
@@ -1,48 +1,41 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::FML parses a bounce email which created by fml.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::FML parses a bounce email which created by fml. Methods in the module are called
|
3
|
+
# from only Sisimai::Message.
|
4
4
|
module FML
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/FML.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['Original mail as follows:'].freeze
|
11
10
|
ErrorTitle = {
|
12
|
-
'rejected' =>
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
}x,
|
26
|
-
'securityerror' => %r/Security Alert/,
|
11
|
+
'rejected' => [
|
12
|
+
' are not member',
|
13
|
+
'NOT MEMBER article from ',
|
14
|
+
'reject mail ',
|
15
|
+
'Spam mail from a spammer is rejected',
|
16
|
+
],
|
17
|
+
'systemerror' => [
|
18
|
+
'fml system error message',
|
19
|
+
'Loop Alert: ',
|
20
|
+
'Loop Back Warning: ',
|
21
|
+
'WARNING: UNIX FROM Loop',
|
22
|
+
],
|
23
|
+
'securityerror' => ['Security Alert'],
|
27
24
|
}.freeze
|
28
25
|
ErrorTable = {
|
29
|
-
'rejected' =>
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|Loop[ ]Back[ ]Warning:
|
43
|
-
)
|
44
|
-
}x,
|
45
|
-
'securityerror' => %r/Security alert:/,
|
26
|
+
'rejected' => [
|
27
|
+
' header may cause mail loop',
|
28
|
+
'NOT MEMBER article from ',
|
29
|
+
'reject mail from ',
|
30
|
+
'reject spammers:',
|
31
|
+
'You are not a member of this mailing list',
|
32
|
+
],
|
33
|
+
'systemerror' => [
|
34
|
+
' has detected a loop condition so that',
|
35
|
+
'Duplicated Message-ID',
|
36
|
+
'Loop Back Warning:',
|
37
|
+
],
|
38
|
+
'securityerror' => ['Security alert:'],
|
46
39
|
}.freeze
|
47
40
|
|
48
41
|
# Parse bounce messages from fml mailling list server/manager
|
@@ -51,34 +44,36 @@ module Sisimai::Lhost
|
|
51
44
|
# @return [Hash] Bounce data list and message/rfc822 part
|
52
45
|
# @return [Nil] it failed to parse or the arguments are missing
|
53
46
|
# @since v4.22.3
|
54
|
-
def
|
47
|
+
def inquire(mhead, mbody)
|
55
48
|
return nil unless mhead['x-mlserver']
|
56
|
-
return nil unless mhead['from']
|
57
|
-
return nil unless mhead['message-id']
|
49
|
+
return nil unless mhead['from'].include?('-admin@')
|
50
|
+
return nil unless mhead['message-id'].index('.FML') > 1
|
58
51
|
|
59
52
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
60
|
-
|
61
|
-
bodyslices =
|
53
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
54
|
+
bodyslices = emailparts[0].split("\n")
|
62
55
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
63
56
|
v = nil
|
64
57
|
|
65
58
|
while e = bodyslices.shift do
|
66
|
-
# Read error messages and delivery status lines from the head of the email
|
67
|
-
#
|
59
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
60
|
+
# line of the beginning of the original message.
|
68
61
|
next if e.empty?
|
69
62
|
|
70
63
|
# Duplicated Message-ID in <2ndml@example.com>.
|
71
64
|
# Original mail as follows:
|
72
65
|
v = dscontents[-1]
|
73
66
|
|
74
|
-
|
75
|
-
|
67
|
+
p1 = e.index('<') || -1
|
68
|
+
p2 = e.rindex('>') || -1
|
69
|
+
if p1 > 0 && p2 > 0
|
70
|
+
# You are not a member of this mailing list <neko-nyaan@example.org>.
|
76
71
|
if v['recipient']
|
77
72
|
# There are multiple recipient addresses in the message body.
|
78
73
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
79
74
|
v = dscontents[-1]
|
80
75
|
end
|
81
|
-
v['recipient'] =
|
76
|
+
v['recipient'] = e[p1 + 1, p2 - p1 - 1]
|
82
77
|
v['diagnosis'] = e
|
83
78
|
recipients += 1
|
84
79
|
else
|
@@ -94,7 +89,7 @@ module Sisimai::Lhost
|
|
94
89
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
95
90
|
ErrorTable.each_key do |f|
|
96
91
|
# Try to match with error messages defined in ErrorTable
|
97
|
-
next unless e['diagnosis']
|
92
|
+
next unless ErrorTable[f].any? { |a| e['diagnosis'].include?(a) }
|
98
93
|
e['reason'] = f
|
99
94
|
break
|
100
95
|
end
|
@@ -110,7 +105,7 @@ module Sisimai::Lhost
|
|
110
105
|
end
|
111
106
|
end
|
112
107
|
|
113
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
108
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
114
109
|
end
|
115
110
|
def description; return 'fml mailing list server/manager'; end
|
116
111
|
end
|
data/lib/sisimai/lhost/gmail.rb
CHANGED
@@ -1,18 +1,16 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Gmail parses a bounce email which created by Gmail.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Gmail parses a bounce email which created by Gmail. Methods in the module are
|
3
|
+
# called from only Sisimai::Message.
|
4
4
|
module Gmail
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Gmail.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['----- Original message -----', '----- Message header follows -----'].freeze
|
11
10
|
StartingOf = {
|
12
11
|
message: ['Delivery to the following recipient'],
|
13
12
|
error: ['The error that the other server returned was:'],
|
14
13
|
}.freeze
|
15
|
-
MarkingsOf = { start: %r/Technical details of (?:permanent|temporary) failure:/ }.freeze
|
16
14
|
MessagesOf = {
|
17
15
|
'expired' => [
|
18
16
|
'DNS Error: Could not contact DNS servers',
|
@@ -103,7 +101,7 @@ module Sisimai::Lhost
|
|
103
101
|
# @param [String] mbody Message body of a bounce email
|
104
102
|
# @return [Hash] Bounce data list and message/rfc822 part
|
105
103
|
# @return [Nil] it failed to parse or the arguments are missing
|
106
|
-
def
|
104
|
+
def inquire(mhead, mbody)
|
107
105
|
# From: Mail Delivery Subsystem <mailer-daemon@googlemail.com>
|
108
106
|
# Received: from vw-in-f109.1e100.net [74.125.113.109] by ...
|
109
107
|
#
|
@@ -154,16 +152,15 @@ module Sisimai::Lhost
|
|
154
152
|
return nil unless mhead['subject'].start_with?('Delivery Status Notification')
|
155
153
|
|
156
154
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
157
|
-
|
158
|
-
bodyslices =
|
155
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
156
|
+
bodyslices = emailparts[0].split("\n")
|
159
157
|
readcursor = 0 # (Integer) Points the current cursor position
|
160
158
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
161
|
-
statecode0 = 0 # (Integer) The value of (state *) in the error message
|
162
159
|
v = nil
|
163
160
|
|
164
161
|
while e = bodyslices.shift do
|
165
|
-
# Read error messages and delivery status lines from the head of the email
|
166
|
-
#
|
162
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
163
|
+
# line of the beginning of the original message.
|
167
164
|
if readcursor == 0
|
168
165
|
# Beginning of the bounce message or delivery status part
|
169
166
|
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
@@ -188,7 +185,7 @@ module Sisimai::Lhost
|
|
188
185
|
#
|
189
186
|
v = dscontents[-1]
|
190
187
|
|
191
|
-
if
|
188
|
+
if e.start_with?(' ') && e.include?('@')
|
192
189
|
# kijitora@example.jp: 550 5.2.2 <kijitora@example>... Mailbox Full
|
193
190
|
if v['recipient']
|
194
191
|
# There are multiple recipient addresses in the message body.
|
@@ -196,8 +193,8 @@ module Sisimai::Lhost
|
|
196
193
|
v = dscontents[-1]
|
197
194
|
end
|
198
195
|
|
199
|
-
r = Sisimai::Address.s3s4(
|
200
|
-
next unless Sisimai::
|
196
|
+
r = Sisimai::Address.s3s4(e[e.rindex(' ') + 1, e.size])
|
197
|
+
next unless Sisimai::Address.is_emailaddress(r)
|
201
198
|
v['recipient'] = r
|
202
199
|
recipients += 1
|
203
200
|
else
|
@@ -212,22 +209,24 @@ module Sisimai::Lhost
|
|
212
209
|
|
213
210
|
unless e['rhost']
|
214
211
|
# Get the value of remote host
|
215
|
-
if
|
216
|
-
# Google tried to deliver your message, but it was rejected by
|
217
|
-
#
|
218
|
-
|
219
|
-
|
220
|
-
e['
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
end
|
212
|
+
if Sisimai::String.aligned(e['diagnosis'], [' by ', '. [', ']. '])
|
213
|
+
# Google tried to deliver your message, but it was rejected by the server for the recipient
|
214
|
+
# domain example.jp by mx.example.jp. [192.0.2.153].
|
215
|
+
p1 = e['diagnosis'].rindex(' by ') || -1
|
216
|
+
p2 = e['diagnosis'].rindex('. [' ) || -1
|
217
|
+
hostname = e['diagnosis'][p1 + 4, p2 - p1 - 4]
|
218
|
+
ipv4addr = e['diagnosis'][p2 + 3, e['diagnosis'].rindex(']. ') - p2 - 3]
|
219
|
+
lastchar = hostname[-1, 1].upcase.ord
|
220
|
+
|
221
|
+
e['rhost'] = hostname if lastchar > 64 && lastchar < 91
|
222
|
+
e['rhost'] ||= ipv4addr
|
227
223
|
end
|
228
224
|
end
|
229
225
|
|
230
|
-
|
226
|
+
p1 = e['diagnosis'].rindex(' ') || -1
|
227
|
+
p2 = e['diagnosis'].rindex(')') || -1
|
228
|
+
statecode0 = e['diagnosis'][p1 + 1, p2 - p1 - 1] || 0
|
229
|
+
|
231
230
|
if StateTable[statecode0]
|
232
231
|
# (state *)
|
233
232
|
e['reason'] = StateTable[statecode0]['reason']
|
@@ -245,10 +244,11 @@ module Sisimai::Lhost
|
|
245
244
|
|
246
245
|
# Set pseudo status code
|
247
246
|
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis']) || ''
|
248
|
-
|
247
|
+
next if e['status'].size == 0 || e['status'].include?('.0')
|
248
|
+
e['reason'] = Sisimai::SMTP::Status.name(e['status']).to_s || ''
|
249
249
|
end
|
250
250
|
|
251
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
251
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
252
252
|
end
|
253
253
|
def description; return 'Gmail: https://mail.google.com'; end
|
254
254
|
end
|