sisimai 4.25.17 → 5.0.0
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 +4 -4
- 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 +41 -21
- 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
@@ -1,13 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Barracuda parses a bounce email which created by Barracuda.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Barracuda parses a bounce email which created by Barracuda. Methods in the module
|
3
|
+
# are called from only Sisimai::Message.
|
4
4
|
module Barracuda
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Barracuda.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['Content-Type: text/rfc822-headers'].freeze
|
11
10
|
StartingOf = { message: ['Your message to:'] }.freeze
|
12
11
|
|
13
12
|
# Parse bounce messages from Barracuda
|
@@ -16,24 +15,23 @@ module Sisimai::Lhost
|
|
16
15
|
# @return [Hash] Bounce data list and message/rfc822 part
|
17
16
|
# @return [Nil] it failed to parse or the arguments are missing
|
18
17
|
# @since v4.25.6
|
19
|
-
def
|
18
|
+
def inquire(mhead, mbody)
|
20
19
|
# Subject: **Message you sent blocked by our bulk email filter**
|
21
20
|
return nil unless mhead['subject'].to_s.end_with?('our bulk email filter**')
|
22
21
|
|
23
|
-
require 'sisimai/rfc1894'
|
24
22
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
25
23
|
permessage = {} # (Hash) Store values of each Per-Message field
|
26
24
|
|
27
25
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
28
|
-
|
29
|
-
bodyslices =
|
26
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
27
|
+
bodyslices = emailparts[0].split("\n")
|
30
28
|
readcursor = 0 # (Integer) Points the current cursor position
|
31
29
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
32
30
|
v = nil
|
33
31
|
|
34
32
|
while e = bodyslices.shift do
|
35
|
-
# Read error messages and delivery status lines from the head of the email
|
36
|
-
#
|
33
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
34
|
+
# line of the beginning of the original message.
|
37
35
|
if readcursor == 0
|
38
36
|
# Beginning of the bounce message or message/delivery-status part
|
39
37
|
readcursor |= Indicators[:deliverystatus] if e.start_with?(StartingOf[:message][0])
|
@@ -72,7 +70,7 @@ module Sisimai::Lhost
|
|
72
70
|
next unless fieldtable[o[0]]
|
73
71
|
v[fieldtable[o[0]]] = o[2]
|
74
72
|
|
75
|
-
next unless f
|
73
|
+
next unless f
|
76
74
|
permessage[fieldtable[o[0]]] = o[2]
|
77
75
|
end
|
78
76
|
end
|
@@ -85,7 +83,7 @@ module Sisimai::Lhost
|
|
85
83
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].to_s.tr("\n", ' '))
|
86
84
|
end
|
87
85
|
|
88
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
86
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
89
87
|
end
|
90
88
|
def description; return 'Barracuda: https://www.barracuda.com'; end
|
91
89
|
end
|
@@ -1,49 +1,49 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Bigfoot parses a bounce email which created by Bigfoot.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Bigfoot parses a bounce email which created by Bigfoot. Methods in the module
|
3
|
+
# are called from only Sisimai::Message.
|
4
4
|
module Bigfoot
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Bigfoot.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
11
|
-
MarkingsOf = { message:
|
9
|
+
Boundaries = ['Content-Type: message/partial'].freeze
|
10
|
+
MarkingsOf = { message: ' ----- Transcript of session follows -----' }.freeze
|
12
11
|
|
13
12
|
# Parse bounce messages from Bigfoot
|
14
13
|
# @param [Hash] mhead Message headers of a bounce email
|
15
14
|
# @param [String] mbody Message body of a bounce email
|
16
15
|
# @return [Hash] Bounce data list and message/rfc822 part
|
17
16
|
# @return [Nil] it failed to parse or the arguments are missing
|
18
|
-
def
|
17
|
+
def inquire(mhead, mbody)
|
19
18
|
# :subject => %r/\AReturned mail: /,
|
20
19
|
match = 0
|
21
20
|
match += 1 if mhead['from'].include?('@bigfoot.com>')
|
22
21
|
match += 1 if mhead['received'].any? { |a| a.include?('.bigfoot.com') }
|
23
22
|
return nil unless match > 0
|
24
23
|
|
24
|
+
require 'sisimai/smtp/command'
|
25
25
|
require 'sisimai/rfc1894'
|
26
26
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
27
27
|
permessage = {} # (Hash) Store values of each Per-Message field
|
28
28
|
|
29
29
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
30
|
-
|
31
|
-
bodyslices =
|
30
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
31
|
+
bodyslices = emailparts[0].split("\n")
|
32
32
|
readslices = ['']
|
33
33
|
readcursor = 0 # (Integer) Points the current cursor position
|
34
34
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
35
|
-
|
35
|
+
thecommand = '' # (String) SMTP Command name begin with the string '>>>'
|
36
36
|
esmtpreply = '' # (String) Reply from remote server on SMTP session
|
37
37
|
v = nil
|
38
38
|
|
39
39
|
while e = bodyslices.shift do
|
40
|
-
# Read error messages and delivery status lines from the head of the email
|
41
|
-
#
|
40
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
41
|
+
# line of the beginning of the original message.
|
42
42
|
readslices << e # Save the current line for the next loop
|
43
43
|
|
44
44
|
if readcursor == 0
|
45
45
|
# Beginning of the bounce message or message/delivery-status part
|
46
|
-
readcursor |= Indicators[:deliverystatus] if e
|
46
|
+
readcursor |= Indicators[:deliverystatus] if e.start_with?(MarkingsOf[:message])
|
47
47
|
next
|
48
48
|
end
|
49
49
|
next if (readcursor & Indicators[:deliverystatus]) == 0
|
@@ -79,7 +79,7 @@ module Sisimai::Lhost
|
|
79
79
|
next unless fieldtable[o[0]]
|
80
80
|
v[fieldtable[o[0]]] = o[2]
|
81
81
|
|
82
|
-
next unless f
|
82
|
+
next unless f
|
83
83
|
permessage[fieldtable[o[0]]] = o[2]
|
84
84
|
end
|
85
85
|
else
|
@@ -88,18 +88,18 @@ module Sisimai::Lhost
|
|
88
88
|
# ----- Transcript of session follows -----
|
89
89
|
# >>> RCPT TO:<destinaion@example.net>
|
90
90
|
# <<< 553 Invalid recipient destinaion@example.net (Mode: normal)
|
91
|
-
if
|
91
|
+
if e.start_with?('>>> ')
|
92
92
|
# >>> DATA
|
93
|
-
|
94
|
-
elsif
|
93
|
+
thecommand = Sisimai::SMTP::Command.find(e)
|
94
|
+
elsif e.start_with?('<<< ')
|
95
95
|
# <<< Response
|
96
|
-
esmtpreply =
|
96
|
+
esmtpreply = e[4, e.size - 4]
|
97
97
|
end
|
98
98
|
else
|
99
99
|
# Continued line of the value of Diagnostic-Code field
|
100
100
|
next unless readslices[-2].start_with?('Diagnostic-Code:')
|
101
|
-
next unless
|
102
|
-
v['diagnosis'] << ' ' <<
|
101
|
+
next unless e.start_with?(' ')
|
102
|
+
v['diagnosis'] << ' ' << Sisimai::String.sweep(e[1, e.size])
|
103
103
|
readslices[-1] = 'Diagnostic-Code: ' << e
|
104
104
|
end
|
105
105
|
end
|
@@ -111,13 +111,13 @@ module Sisimai::Lhost
|
|
111
111
|
e['lhost'] ||= permessage['rhost']
|
112
112
|
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
113
113
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
114
|
-
e['command'] =
|
114
|
+
e['command'] = thecommand || ''
|
115
115
|
if e['command'].empty?
|
116
116
|
e['command'] = 'EHLO' unless esmtpreply.empty?
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
120
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
121
121
|
end
|
122
122
|
def description; return 'Bigfoot: http://www.bigfoot.com'; end
|
123
123
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Biglobe parses a bounce email which created by BIGLOBE.
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Biglobe parses a bounce email which created by BIGLOBE. Methods in the module
|
3
|
+
# are called from only Sisimai::Message.
|
4
4
|
module Biglobe
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Biglobe.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['Content-Type: message/rfc822'].freeze
|
11
10
|
StartingOf = {
|
12
11
|
message: [' ----- The following addresses had delivery problems -----'],
|
13
12
|
error: [' ----- Non-delivered information -----'],
|
@@ -22,20 +21,21 @@ module Sisimai::Lhost
|
|
22
21
|
# @param [String] mbody Message body of a bounce email
|
23
22
|
# @return [Hash] Bounce data list and message/rfc822 part
|
24
23
|
# @return [Nil] it failed to parse or the arguments are missing
|
25
|
-
def
|
26
|
-
return nil unless mhead['from']
|
24
|
+
def inquire(mhead, mbody)
|
25
|
+
return nil unless mhead['from'].include?('postmaster@')
|
26
|
+
return nil unless %w[biglobe inacatv tmtv ttv].any? { |a| mhead['from'].include?('@' + a + '.ne.jp') }
|
27
27
|
return nil unless mhead['subject'].start_with?('Returned mail:')
|
28
28
|
|
29
29
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
30
|
-
|
31
|
-
bodyslices =
|
30
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
31
|
+
bodyslices = emailparts[0].split("\n")
|
32
32
|
readcursor = 0 # (Integer) Points the current cursor position
|
33
33
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
34
34
|
v = nil
|
35
35
|
|
36
36
|
while e = bodyslices.shift do
|
37
|
-
# Read error messages and delivery status lines from the head of the email
|
38
|
-
#
|
37
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
38
|
+
# line of the beginning of the original message.
|
39
39
|
if readcursor == 0
|
40
40
|
# Beginning of the bounce message or delivery status part
|
41
41
|
readcursor |= Indicators[:deliverystatus] if e == StartingOf[:message][0]
|
@@ -60,7 +60,7 @@ module Sisimai::Lhost
|
|
60
60
|
#
|
61
61
|
v = dscontents[-1]
|
62
62
|
|
63
|
-
if
|
63
|
+
if e.include?('@') && e.include?(' ') == false
|
64
64
|
# ----- The following addresses had delivery problems -----
|
65
65
|
# ********@***.biglobe.ne.jp
|
66
66
|
if v['recipient']
|
@@ -69,12 +69,11 @@ module Sisimai::Lhost
|
|
69
69
|
v = dscontents[-1]
|
70
70
|
end
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
v['recipient'] = r
|
72
|
+
next unless Sisimai::Address.is_emailaddress(e)
|
73
|
+
v['recipient'] = e
|
75
74
|
recipients += 1
|
76
75
|
else
|
77
|
-
next if e
|
76
|
+
next if e.include?('--')
|
78
77
|
v['diagnosis'] ||= ''
|
79
78
|
v['diagnosis'] << e + ' '
|
80
79
|
end
|
@@ -92,7 +91,7 @@ module Sisimai::Lhost
|
|
92
91
|
end
|
93
92
|
end
|
94
93
|
|
95
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
94
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
96
95
|
end
|
97
96
|
def description; return 'BIGLOBE: https://www.biglobe.ne.jp'; end
|
98
97
|
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Courier parses a bounce email which created by Courier
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Courier parses a bounce email which created by Courier MTA. Methods in the module
|
3
|
+
# are called from only Sisimai::Message.
|
4
4
|
module Courier
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Courier.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
# https://www.courier-mta.org/courierdsn.html
|
10
9
|
Indicators = Sisimai::Lhost.INDICATORS
|
11
|
-
|
10
|
+
Boundaries = ['Content-Type: message/rfc822', 'Content-Type: text/rfc822-headers'].freeze
|
12
11
|
StartingOf = {
|
13
12
|
# courier/module.dsn/dsn*.txt
|
14
13
|
message: ['DELAYS IN DELIVERING YOUR MESSAGE', 'UNDELIVERABLE MAIL'],
|
@@ -29,32 +28,34 @@ module Sisimai::Lhost
|
|
29
28
|
# @param [String] mbody Message body of a bounce email
|
30
29
|
# @return [Hash] Bounce data list and message/rfc822 part
|
31
30
|
# @return [Nil] it failed to parse or the arguments are missing
|
32
|
-
def
|
31
|
+
def inquire(mhead, mbody)
|
33
32
|
match = 0
|
34
33
|
match += 1 if mhead['from'].include?('Courier mail server at ')
|
35
|
-
match += 1 if mhead['subject']
|
34
|
+
match += 1 if mhead['subject'].include?('NOTICE: mail delivery status.')
|
35
|
+
match += 1 if mhead['subject'].include?('WARNING: delayed mail.')
|
36
36
|
if mhead['message-id']
|
37
37
|
# Message-ID: <courier.4D025E3A.00001792@5jo.example.org>
|
38
|
-
match += 1 if mhead['message-id']
|
38
|
+
match += 1 if mhead['message-id'].start_with?('<courier.')
|
39
39
|
end
|
40
40
|
return nil unless match > 0
|
41
41
|
|
42
|
+
require 'sisimai/smtp/command'
|
42
43
|
require 'sisimai/rfc1894'
|
43
44
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
44
45
|
permessage = {} # (Hash) Store values of each Per-Message field
|
45
46
|
|
46
47
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
47
|
-
|
48
|
-
bodyslices =
|
48
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
49
|
+
bodyslices = emailparts[0].split("\n")
|
49
50
|
readslices = ['']
|
50
51
|
readcursor = 0 # (Integer) Points the current cursor position
|
51
52
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
52
|
-
|
53
|
+
thecommand = '' # (String) SMTP Command name begin with the string '>>>'
|
53
54
|
v = nil
|
54
55
|
|
55
56
|
while e = bodyslices.shift do
|
56
|
-
# Read error messages and delivery status lines from the head of the email
|
57
|
-
#
|
57
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
58
|
+
# line of the beginning of the original message.
|
58
59
|
readslices << e # Save the current line for the next loop
|
59
60
|
|
60
61
|
if readcursor == 0
|
@@ -97,12 +98,12 @@ module Sisimai::Lhost
|
|
97
98
|
next unless fieldtable[o[0]]
|
98
99
|
v[fieldtable[o[0]]] = o[2]
|
99
100
|
|
100
|
-
next unless f
|
101
|
+
next unless f
|
101
102
|
permessage[fieldtable[o[0]]] = o[2]
|
102
103
|
end
|
103
104
|
else
|
104
105
|
# The line does not begin with a DSN field defined in RFC3464
|
105
|
-
if
|
106
|
+
if e.start_with?('>>> ')
|
106
107
|
# Your message to the following recipients cannot be delivered:
|
107
108
|
#
|
108
109
|
# <kijitora@example.co.jp>:
|
@@ -110,13 +111,12 @@ module Sisimai::Lhost
|
|
110
111
|
# >>> RCPT TO:<kijitora@example.co.jp>
|
111
112
|
# <<< 550 5.1.1 <kijitora@example.co.jp>... User Unknown
|
112
113
|
#
|
113
|
-
|
114
|
-
commandtxt = cv[1]
|
114
|
+
thecommand = Sisimai::SMTP::Command.find(e)
|
115
115
|
else
|
116
116
|
# Continued line of the value of Diagnostic-Code field
|
117
117
|
next unless readslices[-2].start_with?('Diagnostic-Code:')
|
118
|
-
next unless
|
119
|
-
v['diagnosis'] << ' ' <<
|
118
|
+
next unless e.start_with?(' ')
|
119
|
+
v['diagnosis'] << ' ' << Sisimai::String.sweep(e)
|
120
120
|
readslices[-1] = 'Diagnostic-Code: ' << e
|
121
121
|
end
|
122
122
|
end
|
@@ -126,7 +126,7 @@ module Sisimai::Lhost
|
|
126
126
|
dscontents.each do |e|
|
127
127
|
# Set default values if each value is empty.
|
128
128
|
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
129
|
-
e['command'] ||=
|
129
|
+
e['command'] ||= thecommand || ''
|
130
130
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
131
131
|
|
132
132
|
MessagesOf.each_key do |r|
|
@@ -137,7 +137,7 @@ module Sisimai::Lhost
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
140
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
141
141
|
end
|
142
142
|
def description; return 'Courier MTA'; end
|
143
143
|
end
|
data/lib/sisimai/lhost/domino.rb
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::Domino parses a bounce email which created by IBM
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::Domino parses a bounce email which created by IBM Domino Server. Methods in the
|
3
|
+
# module are called from only Sisimai::Message.
|
4
4
|
module Domino
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/Domino.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['Content-Type: message/rfc822'].freeze
|
11
10
|
StartingOf = { message: ['Your message'] }.freeze
|
12
11
|
MessagesOf = {
|
13
12
|
'userunknown' => [
|
14
13
|
'not listed in Domino Directory',
|
15
14
|
'not listed in public Name & Address Book',
|
16
|
-
"
|
15
|
+
"non répertorié dans l'annuaire Domino",
|
16
|
+
'no se encuentra en el Directorio de Domino',
|
17
17
|
'Domino ディレクトリには見つかりません',
|
18
18
|
],
|
19
19
|
'filtered' => ['Cannot route mail to user'],
|
@@ -25,7 +25,7 @@ module Sisimai::Lhost
|
|
25
25
|
# @param [String] mbody Message body of a bounce email
|
26
26
|
# @return [Hash] Bounce data list and message/rfc822 part
|
27
27
|
# @return [Nil] it failed to parse or the arguments are missing
|
28
|
-
def
|
28
|
+
def inquire(mhead, mbody)
|
29
29
|
return nil unless mhead['subject'].start_with?('DELIVERY FAILURE:', 'DELIVERY_FAILURE:')
|
30
30
|
|
31
31
|
require 'sisimai/rfc1894'
|
@@ -33,16 +33,16 @@ module Sisimai::Lhost
|
|
33
33
|
permessage = {} # (Hash) Store values of each Per-Message field
|
34
34
|
|
35
35
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
36
|
-
|
37
|
-
bodyslices =
|
36
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
37
|
+
bodyslices = emailparts[0].split("\n")
|
38
38
|
readcursor = 0 # (Integer) Points the current cursor position
|
39
39
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
40
40
|
subjecttxt = '' # (String) The value of Subject:
|
41
41
|
v = nil
|
42
42
|
|
43
43
|
while e = bodyslices.shift do
|
44
|
-
# Read error messages and delivery status lines from the head of the email
|
45
|
-
#
|
44
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
45
|
+
# line of the beginning of the original message.
|
46
46
|
next if e.empty?
|
47
47
|
|
48
48
|
if readcursor == 0
|
@@ -76,10 +76,10 @@ module Sisimai::Lhost
|
|
76
76
|
v['recipient'] ||= e
|
77
77
|
recipients += 1
|
78
78
|
|
79
|
-
elsif
|
79
|
+
elsif e.start_with?(' ') && e.include?('@') && e.index(' ', 3).nil?
|
80
80
|
# Continued from the line "was not delivered to:"
|
81
81
|
# kijitora@example.net
|
82
|
-
v['recipient'] = Sisimai::Address.s3s4(
|
82
|
+
v['recipient'] = Sisimai::Address.s3s4(e[2, e.size])
|
83
83
|
|
84
84
|
elsif e.start_with?('because:')
|
85
85
|
# because:
|
@@ -89,9 +89,9 @@ module Sisimai::Lhost
|
|
89
89
|
# Error message, continued from the line "because:"
|
90
90
|
v['diagnosis'] = e
|
91
91
|
|
92
|
-
elsif
|
92
|
+
elsif e.start_with?(' Subject: ')
|
93
93
|
# Subject: Nyaa
|
94
|
-
subjecttxt =
|
94
|
+
subjecttxt = e[11, e.size]
|
95
95
|
|
96
96
|
elsif f = Sisimai::RFC1894.match(e)
|
97
97
|
# There are some fields defined in RFC3464, try to match
|
@@ -107,9 +107,14 @@ module Sisimai::Lhost
|
|
107
107
|
next unless fieldtable[o[0]]
|
108
108
|
v[fieldtable[o[0]]] = o[2]
|
109
109
|
|
110
|
-
next unless f
|
110
|
+
next unless f
|
111
111
|
permessage[fieldtable[o[0]]] = o[2]
|
112
112
|
end
|
113
|
+
else
|
114
|
+
if v['diagnosis'] && e.start_with?("\s", "\t")
|
115
|
+
# The line is a continued line of "Diagnostic-Code:" field
|
116
|
+
v['diagnosis'] += e.sub(/\A[\s\t]+/, '')
|
117
|
+
end
|
113
118
|
end
|
114
119
|
end
|
115
120
|
end
|
@@ -130,11 +135,10 @@ module Sisimai::Lhost
|
|
130
135
|
end
|
131
136
|
end
|
132
137
|
|
133
|
-
# Set the value of subjecttxt as a Subject if there is no original
|
134
|
-
|
135
|
-
emailsteak[1] << ('Subject: ' << subjecttxt << "\n") unless emailsteak[1] =~ /^Subject: /
|
138
|
+
# Set the value of subjecttxt as a Subject if there is no original message in the bounce mail.
|
139
|
+
emailparts[1] << ('Subject: ' << subjecttxt << "\n") unless emailparts[1].include?("\nSubject:")
|
136
140
|
|
137
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
141
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
138
142
|
end
|
139
143
|
def description; return 'IBM Domino Server'; end
|
140
144
|
end
|
@@ -1,13 +1,12 @@
|
|
1
1
|
module Sisimai::Lhost
|
2
|
-
# Sisimai::Lhost::EinsUndEins parses a bounce email which created by
|
3
|
-
#
|
2
|
+
# Sisimai::Lhost::EinsUndEins parses a bounce email which created by 1&1. Methods in the module are
|
3
|
+
# called from only Sisimai::Message.
|
4
4
|
module EinsUndEins
|
5
5
|
class << self
|
6
|
-
# Imported from p5-Sisimail/lib/Sisimai/Lhost/EinsUndEins.pm
|
7
6
|
require 'sisimai/lhost'
|
8
7
|
|
9
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
10
|
-
|
9
|
+
Boundaries = ['--- The header of the original message is following. ---'].freeze
|
11
10
|
StartingOf = {
|
12
11
|
message: ['This message was created automatically by mail delivery software'],
|
13
12
|
error: ['For the following reason:'],
|
@@ -19,20 +18,20 @@ module Sisimai::Lhost
|
|
19
18
|
# @param [String] mbody Message body of a bounce email
|
20
19
|
# @return [Hash] Bounce data list and message/rfc822 part
|
21
20
|
# @return [Nil] it failed to parse or the arguments are missing
|
22
|
-
def
|
21
|
+
def inquire(mhead, mbody)
|
23
22
|
return nil unless mhead['from'].start_with?('"Mail Delivery System"')
|
24
23
|
return nil unless mhead['subject'] == 'Mail delivery failed: returning message to sender'
|
25
24
|
|
26
25
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]
|
27
|
-
|
28
|
-
bodyslices =
|
26
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
27
|
+
bodyslices = emailparts[0].split("\n")
|
29
28
|
readcursor = 0 # (Integer) Points the current cursor position
|
30
29
|
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
31
30
|
v = nil
|
32
31
|
|
33
32
|
while e = bodyslices.shift do
|
34
|
-
# Read error messages and delivery status lines from the head of the email
|
35
|
-
#
|
33
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
34
|
+
# line of the beginning of the original message.
|
36
35
|
|
37
36
|
if readcursor == 0
|
38
37
|
# Beginning of the bounce message or delivery status part
|
@@ -60,7 +59,7 @@ module Sisimai::Lhost
|
|
60
59
|
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
61
60
|
v = dscontents[-1]
|
62
61
|
end
|
63
|
-
v['recipient'] =
|
62
|
+
v['recipient'] = Sisimai::Address.s3s4(e)
|
64
63
|
recipients += 1
|
65
64
|
|
66
65
|
elsif e.start_with?(StartingOf[:error][0])
|
@@ -81,21 +80,26 @@ module Sisimai::Lhost
|
|
81
80
|
end
|
82
81
|
return nil unless recipients > 0
|
83
82
|
|
83
|
+
require 'sisimai/smtp/command'
|
84
84
|
dscontents.each do |e|
|
85
85
|
e['diagnosis'] ||= ''
|
86
86
|
e['diagnosis'] = e['alterrors'] if e['diagnosis'].empty?
|
87
|
+
e['command'] = Sisimai::SMTP::Command.find(e['diagnosis'])
|
87
88
|
|
88
|
-
if
|
89
|
+
if Sisimai::String.aligned(e['diagnosis'], ['host: ', ' reason:'])
|
89
90
|
# SMTP error from remote server for TEXT command,
|
90
91
|
# host: smtp-in.orange.fr (193.252.22.65)
|
91
92
|
# reason: 550 5.2.0 Mail rejete. Mail rejected. ofr_506 [506]
|
92
|
-
e['
|
93
|
-
|
94
|
-
|
93
|
+
p1 = e['diagnosis'].index('host: ')
|
94
|
+
p2 = e['diagnosis'].index(' reason:')
|
95
|
+
|
96
|
+
e['rhost'] = Sisimai::String.sweep(e['diagnosis'][p1 + 6, p2 - p1 - 6])
|
97
|
+
e['command'] = 'DATA' if e['diagnosis'].include?('for TEXT command')
|
98
|
+
e['spec'] = 'SMTP' if e['diagnosis'].include?('SMTP error')
|
95
99
|
e['status'] = Sisimai::SMTP::Status.find(e['diagnosis'])
|
96
100
|
else
|
97
101
|
# For the following reason:
|
98
|
-
e['diagnosis']
|
102
|
+
e['diagnosis'][0, StartingOf[:error][0].size] = ''
|
99
103
|
end
|
100
104
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
101
105
|
|
@@ -107,7 +111,7 @@ module Sisimai::Lhost
|
|
107
111
|
end
|
108
112
|
end
|
109
113
|
|
110
|
-
return { 'ds' => dscontents, 'rfc822' =>
|
114
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
111
115
|
end
|
112
116
|
def description; return '1&1: https://www.1und1.de'; end
|
113
117
|
end
|