sisimai 5.4.1 → 5.5.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/.github/workflows/codecovio.yml +1 -1
- data/.github/workflows/rake-test.yml +1 -1
- data/ChangeLog.md +35 -0
- data/Makefile +2 -4
- data/README-JA.md +23 -20
- data/README.md +23 -20
- data/lib/sisimai/address.rb +92 -44
- data/lib/sisimai/arf.rb +7 -8
- data/lib/sisimai/datetime.rb +2 -2
- data/lib/sisimai/fact/json.rb +1 -2
- data/lib/sisimai/fact/yaml.rb +1 -2
- data/lib/sisimai/fact.rb +60 -35
- data/lib/sisimai/lda.rb +2 -2
- data/lib/sisimai/lhost/activehunter.rb +4 -5
- data/lib/sisimai/lhost/amazonses.rb +3 -4
- data/lib/sisimai/lhost/apachejames.rb +2 -2
- data/lib/sisimai/lhost/biglobe.rb +6 -6
- data/lib/sisimai/lhost/courier.rb +7 -7
- data/lib/sisimai/lhost/domino.rb +6 -6
- data/lib/sisimai/lhost/dragonfly.rb +5 -5
- data/lib/sisimai/lhost/einsundeins.rb +4 -4
- data/lib/sisimai/lhost/exchange2003.rb +7 -7
- data/lib/sisimai/lhost/exchange2007.rb +3 -3
- data/lib/sisimai/lhost/exim.rb +7 -7
- data/lib/sisimai/lhost/ezweb.rb +3 -2
- data/lib/sisimai/lhost/fml.rb +9 -9
- data/lib/sisimai/lhost/gmail.rb +9 -9
- data/lib/sisimai/lhost/gmx.rb +3 -3
- data/lib/sisimai/lhost/googlegroups.rb +6 -7
- data/lib/sisimai/lhost/googleworkspace.rb +5 -6
- data/lib/sisimai/lhost/imailserver.rb +4 -4
- data/lib/sisimai/lhost/kddi.rb +4 -4
- data/lib/sisimai/lhost/mailfoundry.rb +3 -3
- data/lib/sisimai/lhost/{mailmarshalsmtp.rb → mailmarshal.rb} +5 -5
- data/lib/sisimai/lhost/messagingserver.rb +8 -8
- data/lib/sisimai/lhost/mfilter.rb +8 -4
- data/lib/sisimai/lhost/mimecast.rb +105 -0
- data/lib/sisimai/lhost/notes.rb +5 -5
- data/lib/sisimai/lhost/opensmtpd.rb +5 -5
- data/lib/sisimai/lhost/postfix.rb +38 -32
- data/lib/sisimai/lhost/qmail.rb +6 -6
- data/lib/sisimai/lhost/sendmail.rb +13 -13
- data/lib/sisimai/lhost/{interscanmss.rb → trendmicro.rb} +8 -9
- data/lib/sisimai/lhost/v5sendmail.rb +7 -7
- data/lib/sisimai/lhost/verizon.rb +3 -3
- data/lib/sisimai/lhost/x1.rb +7 -4
- data/lib/sisimai/lhost/x2.rb +40 -12
- data/lib/sisimai/lhost/x3.rb +3 -3
- data/lib/sisimai/lhost/x6.rb +2 -2
- data/lib/sisimai/lhost/zoho.rb +5 -5
- data/lib/sisimai/lhost.rb +18 -17
- data/lib/sisimai/mail/maildir.rb +4 -4
- data/lib/sisimai/mail/mbox.rb +4 -4
- data/lib/sisimai/mail/memory.rb +1 -1
- data/lib/sisimai/mail/stdin.rb +2 -2
- data/lib/sisimai/message.rb +34 -34
- data/lib/sisimai/order.rb +5 -4
- data/lib/sisimai/reason/authfailure.rb +1 -1
- data/lib/sisimai/reason/badreputation.rb +1 -1
- data/lib/sisimai/reason/blocked.rb +2 -1
- data/lib/sisimai/reason/contenterror.rb +1 -2
- data/lib/sisimai/reason/exceedlimit.rb +1 -1
- data/lib/sisimai/reason/expired.rb +1 -1
- data/lib/sisimai/reason/failedstarttls.rb +1 -1
- data/lib/sisimai/reason/filtered.rb +1 -1
- data/lib/sisimai/reason/hasmoved.rb +1 -1
- data/lib/sisimai/reason/hostunknown.rb +2 -2
- data/lib/sisimai/reason/mailboxfull.rb +1 -1
- data/lib/sisimai/reason/mailererror.rb +1 -1
- data/lib/sisimai/reason/mesgtoobig.rb +1 -1
- data/lib/sisimai/reason/networkerror.rb +1 -1
- data/lib/sisimai/reason/norelaying.rb +2 -2
- data/lib/sisimai/reason/notaccept.rb +2 -3
- data/lib/sisimai/reason/notcompliantrfc.rb +1 -1
- data/lib/sisimai/reason/policyviolation.rb +2 -4
- data/lib/sisimai/reason/rejected.rb +5 -3
- data/lib/sisimai/reason/requireptr.rb +1 -1
- data/lib/sisimai/reason/securityerror.rb +1 -1
- data/lib/sisimai/reason/spamdetected.rb +1 -1
- data/lib/sisimai/reason/speeding.rb +1 -1
- data/lib/sisimai/reason/suspend.rb +2 -1
- data/lib/sisimai/reason/systemerror.rb +1 -1
- data/lib/sisimai/reason/systemfull.rb +1 -1
- data/lib/sisimai/reason/toomanyconn.rb +1 -1
- data/lib/sisimai/reason/userunknown.rb +4 -3
- data/lib/sisimai/reason/vacation.rb +1 -1
- data/lib/sisimai/reason/virusdetected.rb +1 -1
- data/lib/sisimai/reason.rb +12 -12
- data/lib/sisimai/rfc1123.rb +58 -18
- data/lib/sisimai/rfc1894.rb +6 -8
- data/lib/sisimai/rfc2045.rb +25 -13
- data/lib/sisimai/rfc3464/thirdparty.rb +2 -3
- data/lib/sisimai/rfc3464.rb +6 -6
- data/lib/sisimai/rfc3834.rb +18 -8
- data/lib/sisimai/rfc5322.rb +9 -9
- data/lib/sisimai/rfc791.rb +2 -2
- data/lib/sisimai/rhost/aol.rb +4 -1
- data/lib/sisimai/rhost/apple.rb +11 -7
- data/lib/sisimai/rhost/cox.rb +9 -5
- data/lib/sisimai/rhost/facebook.rb +9 -3
- data/lib/sisimai/rhost/franceptt.rb +86 -37
- data/lib/sisimai/rhost/godaddy.rb +10 -1
- data/lib/sisimai/rhost/google.rb +6 -6
- data/lib/sisimai/rhost/gsuite.rb +1 -1
- data/lib/sisimai/rhost/kddi.rb +1 -1
- data/lib/sisimai/rhost/messagelabs.rb +160 -2
- data/lib/sisimai/rhost/microsoft.rb +77 -26
- data/lib/sisimai/rhost/mimecast.rb +30 -21
- data/lib/sisimai/rhost/nttdocomo.rb +69 -89
- data/lib/sisimai/rhost/outlook.rb +1 -1
- data/lib/sisimai/rhost/spectrum.rb +1 -1
- data/lib/sisimai/rhost/tencent.rb +5 -4
- data/lib/sisimai/rhost/yahooinc.rb +2 -2
- data/lib/sisimai/rhost/zoho.rb +72 -0
- data/lib/sisimai/rhost.rb +4 -3
- data/lib/sisimai/smtp/command.rb +2 -2
- data/lib/sisimai/smtp/reply.rb +11 -4
- data/lib/sisimai/smtp/status.rb +17 -8
- data/lib/sisimai/smtp/transcript.rb +3 -3
- data/lib/sisimai/string.rb +6 -10
- data/lib/sisimai/version.rb +1 -1
- data/lib/sisimai.rb +1 -1
- data/set-of-emails/maildir/bsd/lhost-exim-56.eml +40 -40
- data/set-of-emails/maildir/bsd/lhost-mfilter-05.eml +41 -0
- data/set-of-emails/maildir/bsd/lhost-mimecast-01.eml +46 -0
- data/set-of-emails/maildir/bsd/lhost-mimecast-02.eml +59 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-79.eml +81 -0
- data/set-of-emails/maildir/bsd/lhost-postfix-80.eml +84 -0
- data/set-of-emails/maildir/bsd/lhost-x1-03.eml +26 -0
- data/set-of-emails/maildir/bsd/lhost-x1-04.eml +45 -0
- data/set-of-emails/maildir/bsd/lhost-x2-07.eml +30 -0
- data/set-of-emails/maildir/bsd/rfc3464-66.eml +170 -0
- data/set-of-emails/maildir/bsd/rfc3834-06.eml +59 -0
- data/set-of-emails/maildir/bsd/rhost-zoho-01.eml +88 -0
- data/set-of-emails/maildir/bsd/rhost-zoho-02.eml +86 -0
- data/set-of-emails/maildir/bsd/rhost-zoho-03.eml +87 -0
- data/set-of-emails/maildir/bsd/rhost-zoho-04.eml +86 -0
- data/set-of-emails/maildir/not/rb-issue-368-bug.eml +39 -0
- data/sisimai-java.gemspec +1 -1
- data/sisimai.gemspec +1 -1
- metadata +26 -9
- /data/set-of-emails/maildir/bsd/{lhost-mailmarshalsmtp-02.eml → lhost-mailmarshal-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-interscanmss-01.eml → lhost-trendmicro-01.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-interscanmss-02.eml → lhost-trendmicro-02.eml} +0 -0
- /data/set-of-emails/maildir/bsd/{lhost-interscanmss-03.eml → lhost-trendmicro-03.eml} +0 -0
data/lib/sisimai/lhost/zoho.rb
CHANGED
|
@@ -19,7 +19,7 @@ module Sisimai::Lhost
|
|
|
19
19
|
# X-ZohoMail: Si CHF_MF_NL SS_10 UW48 UB48 FMWL UW48 UB48 SGR3_1_09124_42
|
|
20
20
|
# X-Zoho-Virus-Status: 2
|
|
21
21
|
# X-Mailer: Zoho Mail
|
|
22
|
-
return nil
|
|
22
|
+
return nil if mhead['x-zohomail'].nil?
|
|
23
23
|
|
|
24
24
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
|
|
25
25
|
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
|
@@ -68,7 +68,7 @@ module Sisimai::Lhost
|
|
|
68
68
|
end
|
|
69
69
|
recipients += 1
|
|
70
70
|
|
|
71
|
-
elsif e.start_with?('[Status: ')
|
|
71
|
+
elsif e.start_with?('[Status: ') && e.include?('<') && e.include?('>')
|
|
72
72
|
# Expired
|
|
73
73
|
# [Status: Error, Address: <kijitora@6kaku.example.co.jp>, ResponseCode 421, , Host not reachable.]
|
|
74
74
|
if v["recipient"] != ""
|
|
@@ -83,17 +83,17 @@ module Sisimai::Lhost
|
|
|
83
83
|
recipients += 1
|
|
84
84
|
else
|
|
85
85
|
# Continued line
|
|
86
|
-
next
|
|
86
|
+
next if qprintable == false
|
|
87
87
|
v['diagnosis'] += e
|
|
88
88
|
end
|
|
89
89
|
end
|
|
90
|
-
return nil
|
|
90
|
+
return nil if recipients == 0
|
|
91
91
|
|
|
92
92
|
dscontents.each do |e|
|
|
93
93
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'].tr("\n", ' '))
|
|
94
94
|
MessagesOf.each_key do |r|
|
|
95
95
|
# Verify each regular expression of session errors
|
|
96
|
-
next
|
|
96
|
+
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
97
97
|
e['reason'] = r
|
|
98
98
|
break
|
|
99
99
|
end
|
data/lib/sisimai/lhost.rb
CHANGED
|
@@ -9,20 +9,21 @@ module Sisimai
|
|
|
9
9
|
# @private
|
|
10
10
|
def DELIVERYSTATUS
|
|
11
11
|
return {
|
|
12
|
-
'spec' => "",
|
|
13
|
-
'date' => "",
|
|
14
|
-
'rhost' => "",
|
|
15
|
-
'lhost' => "",
|
|
16
|
-
'alias' => "",
|
|
17
|
-
'agent' => "",
|
|
18
|
-
'action' => "",
|
|
19
|
-
'status' => "",
|
|
20
|
-
'reason' => "",
|
|
21
|
-
'command' => "",
|
|
22
|
-
'replycode' => "",
|
|
23
|
-
'diagnosis' => "",
|
|
24
|
-
'recipient' => "",
|
|
25
|
-
'feedbacktype' => "",
|
|
12
|
+
'spec' => "", # Protocl specification
|
|
13
|
+
'date' => "", # The value of Last-Attempt-Date header
|
|
14
|
+
'rhost' => "", # The value of Remote-MTA header
|
|
15
|
+
'lhost' => "", # The value of Received-From-MTA header
|
|
16
|
+
'alias' => "", # The value of alias entry(RHS)
|
|
17
|
+
'agent' => "", # MTA module name
|
|
18
|
+
'action' => "", # The value of Action header
|
|
19
|
+
'status' => "", # The value of Status header
|
|
20
|
+
'reason' => "", # Temporary reason of bounce
|
|
21
|
+
'command' => "", # SMTP command in the message body
|
|
22
|
+
'replycode' => "", # SMTP Reply code
|
|
23
|
+
'diagnosis' => "", # The value of Diagnostic-Code header
|
|
24
|
+
'recipient' => "", # The value of Final-Recipient header
|
|
25
|
+
'feedbacktype' => "", # Feedback Type
|
|
26
|
+
'toxic' => false, # EXPERIMENTAL
|
|
26
27
|
}
|
|
27
28
|
end
|
|
28
29
|
|
|
@@ -41,9 +42,9 @@ module Sisimai
|
|
|
41
42
|
def index
|
|
42
43
|
return %w[
|
|
43
44
|
Activehunter AmazonSES ApacheJames Biglobe Courier Domino DragonFly EZweb EinsUndEins Exchange2003
|
|
44
|
-
Exchange2007 Exim FML GMX GoogleWorkspace GoogleGroups Gmail IMailServer
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
Exchange2007 Exim FML GMX GoogleWorkspace GoogleGroups Gmail IMailServer KDDI MailFoundry Mimecast
|
|
46
|
+
MailMarshal MessagingServer Notes OpenSMTPD Postfix Sendmail TrendMicro V5sendmail Verizon
|
|
47
|
+
X1 X2 X3 X6 Zoho MFILTER Qmail
|
|
47
48
|
]
|
|
48
49
|
end
|
|
49
50
|
|
data/lib/sisimai/mail/maildir.rb
CHANGED
|
@@ -16,8 +16,8 @@ module Sisimai
|
|
|
16
16
|
# @return [Sisimai::Mail::Maildir] Object
|
|
17
17
|
# [Nil] is not a directory or does not exist
|
|
18
18
|
def initialize(argv1)
|
|
19
|
-
raise Errno::ENOENT
|
|
20
|
-
raise Errno::ENOTDIR
|
|
19
|
+
raise Errno::ENOENT if File.exist?(argv1) == false
|
|
20
|
+
raise Errno::ENOTDIR if File.ftype(argv1) != 'directory'
|
|
21
21
|
|
|
22
22
|
@path = nil
|
|
23
23
|
@size = Dir.entries(argv1).size
|
|
@@ -30,7 +30,7 @@ module Sisimai
|
|
|
30
30
|
# Maildir reader, works as an iterator.
|
|
31
31
|
# @return [String] Contents of file in Maildir/
|
|
32
32
|
def read
|
|
33
|
-
return nil
|
|
33
|
+
return nil if self.offset >= self.size
|
|
34
34
|
seekhandle = self.handle
|
|
35
35
|
readbuffer = ''
|
|
36
36
|
|
|
@@ -61,7 +61,7 @@ module Sisimai
|
|
|
61
61
|
self.file = r
|
|
62
62
|
break
|
|
63
63
|
end
|
|
64
|
-
seekhandle.close
|
|
64
|
+
seekhandle.close if self.offset >= self.size
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
return readbuffer
|
data/lib/sisimai/mail/mbox.rb
CHANGED
|
@@ -16,8 +16,8 @@ module Sisimai
|
|
|
16
16
|
# @return [Sisimai::Mail::Mbox] Object
|
|
17
17
|
# [Nil] is not specified or does not exist
|
|
18
18
|
def initialize(argv1)
|
|
19
|
-
raise Errno::ENOENT
|
|
20
|
-
raise 'is not a file'
|
|
19
|
+
raise Errno::ENOENT if File.exist?(argv1) == false
|
|
20
|
+
raise 'is not a file' if File.ftype(argv1) != 'file'
|
|
21
21
|
|
|
22
22
|
@path = argv1
|
|
23
23
|
@dir = File.dirname(argv1)
|
|
@@ -30,7 +30,7 @@ module Sisimai
|
|
|
30
30
|
# Mbox reader, works as an iterator.
|
|
31
31
|
# @return [String] Contents of mbox
|
|
32
32
|
def read
|
|
33
|
-
return nil
|
|
33
|
+
return nil if self.offset >= self.size
|
|
34
34
|
|
|
35
35
|
seekoffset = self.offset || 0
|
|
36
36
|
filehandle = self.handle
|
|
@@ -53,7 +53,7 @@ module Sisimai
|
|
|
53
53
|
seekoffset = filehandle.pos - frombuffer.bytesize
|
|
54
54
|
frombuffer = ''
|
|
55
55
|
self.offset = seekoffset
|
|
56
|
-
filehandle.close
|
|
56
|
+
filehandle.close if self.offset >= self.size
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
return readbuffer.to_s
|
data/lib/sisimai/mail/memory.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Sisimai
|
|
|
14
14
|
# @return [Sisimai::Mail::Memory] Object
|
|
15
15
|
# [Nil] is not specified or does not exist
|
|
16
16
|
def initialize(argv1)
|
|
17
|
-
raise 'is not a String'
|
|
17
|
+
raise 'is not a String' if argv1.is_a?(::String) == false
|
|
18
18
|
raise 'is empty' if argv1.empty?
|
|
19
19
|
|
|
20
20
|
@path = '<MEMORY>'
|
data/lib/sisimai/mail/stdin.rb
CHANGED
|
@@ -13,7 +13,7 @@ module Sisimai
|
|
|
13
13
|
# @param [IO::STDIN] stdin Standard-In
|
|
14
14
|
# @return [Sisimai::Mail::STDIN] Object
|
|
15
15
|
def initialize(stdin = $stdin)
|
|
16
|
-
raise 'is not an IO object'
|
|
16
|
+
raise 'is not an IO object' if stdin.is_a?(IO) == false
|
|
17
17
|
|
|
18
18
|
@path = '<STDIN>'
|
|
19
19
|
@size = nil
|
|
@@ -32,7 +32,7 @@ module Sisimai
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
begin
|
|
35
|
-
readhandle = STDIN
|
|
35
|
+
readhandle = STDIN if readhandle.nil?
|
|
36
36
|
while r = readhandle.gets
|
|
37
37
|
break if readbuffer.size > 0 && r.start_with?('From ')
|
|
38
38
|
readbuffer << r
|
data/lib/sisimai/message.rb
CHANGED
|
@@ -21,12 +21,15 @@ module Sisimai
|
|
|
21
21
|
FieldIndex = [Fields1894.flatten, Fields5322.flatten, Fields5965.flatten].flatten.freeze
|
|
22
22
|
FieldTable = FieldIndex.map { |e| [e.downcase, e] }.to_h.freeze
|
|
23
23
|
Boundaries = ['Content-Type: message/rfc822', 'Content-Type: text/rfc822-headers'].freeze
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
]
|
|
29
|
-
|
|
24
|
+
MediaTypes = [
|
|
25
|
+
%w[message/xdelivery-status message/delivery-status],
|
|
26
|
+
%w[message/disposition-notification message/delivery-status],
|
|
27
|
+
%w[message/global-delivery-status message/delivery-status],
|
|
28
|
+
%w[message/global-disposition-notification message/delivery-status],
|
|
29
|
+
%w[message/global-delivery-status message/delivery-status],
|
|
30
|
+
%w[message/global-headers text/rfc822-headers],
|
|
31
|
+
%w[message/global message/rfc822],
|
|
32
|
+
].freeze
|
|
30
33
|
|
|
31
34
|
# Read an email message and convert to structured format
|
|
32
35
|
# @param [Hash] argvs Module to be loaded
|
|
@@ -35,7 +38,7 @@ module Sisimai
|
|
|
35
38
|
# @return [Sisimai::Message] Structured email data or nil if each
|
|
36
39
|
# value of the arguments are missing
|
|
37
40
|
def rise(**argvs)
|
|
38
|
-
return nil
|
|
41
|
+
return nil if argvs.nil?
|
|
39
42
|
email = argvs[:data].scrub('?').gsub("\r\n", "\n")
|
|
40
43
|
thing = {'from' => '','header' => {}, 'rfc822' => '', 'ds' => [], 'catch' => nil}
|
|
41
44
|
param = {}
|
|
@@ -53,12 +56,12 @@ module Sisimai
|
|
|
53
56
|
thing['header'] = Sisimai::Message.makemap(aftersplit[1])
|
|
54
57
|
|
|
55
58
|
# 3. Decode and rewrite the "Subject:" header
|
|
56
|
-
|
|
59
|
+
if thing['header']['subject'].empty? == false
|
|
57
60
|
# Decode MIME-Encoded "Subject:" header
|
|
58
61
|
cv = thing['header']['subject']
|
|
59
62
|
cq = Sisimai::RFC2045.is_encoded(cv) ? Sisimai::RFC2045.decodeH(cv.split(/[ ]/)) : cv
|
|
60
63
|
cl = cq.downcase
|
|
61
|
-
p1 = cl.index('fwd:'); p1 = cl.index('fw:')
|
|
64
|
+
p1 = cl.index('fwd:'); p1 = cl.index('fw:') if p1.nil?
|
|
62
65
|
|
|
63
66
|
# Remove "Fwd:" string from the Subject: header
|
|
64
67
|
if p1
|
|
@@ -77,17 +80,16 @@ module Sisimai
|
|
|
77
80
|
'tryonfirst' => Sisimai::Order.make(thing['header']['subject'])
|
|
78
81
|
}
|
|
79
82
|
break if beforefact = Sisimai::Message.sift(param)
|
|
80
|
-
break
|
|
83
|
+
break if Boundaries.none? { |a| aftersplit[2].include?(a) }
|
|
81
84
|
|
|
82
85
|
# 5. Try to sift again
|
|
83
86
|
# There is a bounce message inside of mutipart/*, try to sift the first message/rfc822
|
|
84
87
|
# part as a entire message body again.
|
|
85
88
|
parseagain += 1
|
|
86
89
|
email = Sisimai::RFC5322.part(aftersplit[2], Boundaries, true).pop.sub(/\A\s+/, '')
|
|
87
|
-
break
|
|
90
|
+
break if email.size < 128
|
|
88
91
|
end
|
|
89
|
-
return nil
|
|
90
|
-
return nil if beforefact.empty?
|
|
92
|
+
return nil if beforefact.nil? || beforefact.empty?
|
|
91
93
|
|
|
92
94
|
# 6. Rewrite headers of the original message in the body part
|
|
93
95
|
%w|ds catch rfc822|.each { |e| thing[e] = beforefact[e] }
|
|
@@ -109,8 +111,7 @@ module Sisimai
|
|
|
109
111
|
email.gsub!(/\r\n/, "\n") if email.include?("\r\n")
|
|
110
112
|
|
|
111
113
|
(parts[1], parts[2]) = email.split(/\n\n/, 2)
|
|
112
|
-
return nil
|
|
113
|
-
return nil unless parts[2]
|
|
114
|
+
return nil if parts[1].nil? || parts[2].nil?
|
|
114
115
|
|
|
115
116
|
if parts[1].start_with?('From ')
|
|
116
117
|
# From MAILER-DAEMON Tue Feb 11 00:00:00 2014
|
|
@@ -119,7 +120,7 @@ module Sisimai
|
|
|
119
120
|
# Set pseudo UNIX From line
|
|
120
121
|
parts[0] = 'MAILER-DAEMON Tue Feb 11 00:00:00 2014'
|
|
121
122
|
end
|
|
122
|
-
parts[1] += "\n"
|
|
123
|
+
parts[1] += "\n" if parts[1].end_with?("\n") == false
|
|
123
124
|
|
|
124
125
|
%w[image/ application/ text/html].each do |e|
|
|
125
126
|
# https://github.com/sisimai/p5-sisimai/issues/492, Reduce email size
|
|
@@ -128,8 +129,8 @@ module Sisimai
|
|
|
128
129
|
ep = e == 'text/html' ? '</html>' : "--\n"
|
|
129
130
|
while true
|
|
130
131
|
# Remove each part from "Content-Type: image/..." to "--\n" (the end of each boundary)
|
|
131
|
-
p0 = parts[2].index("Content-Type: #{e}", p0); break
|
|
132
|
-
p1 = parts[2].index(ep, p0 + 32); break
|
|
132
|
+
p0 = parts[2].index("Content-Type: #{e}", p0); break if p0.nil?
|
|
133
|
+
p1 = parts[2].index(ep, p0 + 32); break if p1.nil?
|
|
133
134
|
parts[2][p0, p1 - p0] = ''
|
|
134
135
|
end
|
|
135
136
|
end
|
|
@@ -170,8 +171,7 @@ module Sisimai
|
|
|
170
171
|
end
|
|
171
172
|
headermaps['received'] = receivedby
|
|
172
173
|
|
|
173
|
-
return headermaps
|
|
174
|
-
return headermaps if headermaps['subject'].empty?
|
|
174
|
+
return headermaps if argv1.nil? || headermaps['subject'].empty?
|
|
175
175
|
|
|
176
176
|
# Convert MIME-Encoded subject
|
|
177
177
|
if Sisimai::String.is_8bit(headermaps['subject'])
|
|
@@ -209,7 +209,7 @@ module Sisimai
|
|
|
209
209
|
# Find and tidy up fields defined in RFC5322, RFC1894, and RFC5965
|
|
210
210
|
# 1. Find a field label defined in RFC5322, RFC1894, or RFC5965 from this line
|
|
211
211
|
p0 = e.index(':') || -1
|
|
212
|
-
cf = e.downcase[0, p0]
|
|
212
|
+
cf = e.downcase[0, p0].to_s.rstrip
|
|
213
213
|
fn = FieldTable[cf] || ''
|
|
214
214
|
|
|
215
215
|
index += 1
|
|
@@ -227,7 +227,7 @@ module Sisimai
|
|
|
227
227
|
# Such as Diagnostic-Code, Remote-MTA, and so on
|
|
228
228
|
# - Before: Diagnostic-Code: SMTP;550 User unknown
|
|
229
229
|
# - After: Diagnostic-Code: smtp; 550 User unknown
|
|
230
|
-
break
|
|
230
|
+
break if ['Content-Type'].concat(Fields1894).none? { |a| a == fn }
|
|
231
231
|
|
|
232
232
|
if p1
|
|
233
233
|
# The field including one or more ";"
|
|
@@ -251,7 +251,8 @@ module Sisimai
|
|
|
251
251
|
ps = f[0, p2].downcase
|
|
252
252
|
f[0, p2] = ps
|
|
253
253
|
end
|
|
254
|
-
f.downcase!
|
|
254
|
+
f.downcase! if ps != 'boundary'
|
|
255
|
+
f = 'rfc822' if f == 'rfc/822'
|
|
255
256
|
break
|
|
256
257
|
end
|
|
257
258
|
ab << f
|
|
@@ -261,9 +262,9 @@ module Sisimai
|
|
|
261
262
|
# Diagnostic-Code: x-unix;
|
|
262
263
|
# /var/email/kijitora/Maildir/tmp/1000000000.A000000B00000.neko22:
|
|
263
264
|
# Disk quota exceeded
|
|
264
|
-
break
|
|
265
|
-
break
|
|
266
|
-
break
|
|
265
|
+
break if fn != 'Diagnostic-Code'
|
|
266
|
+
break if ab.size != 1
|
|
267
|
+
break if lines[index + 1].start_with?(' ') == false
|
|
267
268
|
|
|
268
269
|
ab << ''
|
|
269
270
|
break
|
|
@@ -281,9 +282,9 @@ module Sisimai
|
|
|
281
282
|
end
|
|
282
283
|
|
|
283
284
|
# 3. Tidy up a value, and a parameter of Content-Type: field
|
|
284
|
-
if
|
|
285
|
+
if fn == "Content-Type"
|
|
285
286
|
# Replace the value of "Content-Type" field
|
|
286
|
-
|
|
287
|
+
MediaTypes.each do |f|
|
|
287
288
|
# - Before: Content-Type: message/xdelivery-status; ...
|
|
288
289
|
# - After: Content-Type: message/delivery-status; ...
|
|
289
290
|
p1 = bf.index(f[0]) || next
|
|
@@ -296,7 +297,7 @@ module Sisimai
|
|
|
296
297
|
email += sprintf("%s: %s\n", fn, bf)
|
|
297
298
|
end
|
|
298
299
|
|
|
299
|
-
email += "\n"
|
|
300
|
+
email += "\n" if email.end_with?("\n\n") == false
|
|
300
301
|
return email
|
|
301
302
|
end
|
|
302
303
|
|
|
@@ -311,14 +312,13 @@ module Sisimai
|
|
|
311
312
|
# @param options argvs [Array] tryonfirst MTA module list to load on first
|
|
312
313
|
# @return [Hash] Decoded and structured bounce mails
|
|
313
314
|
def sift(argvs)
|
|
314
|
-
return nil
|
|
315
|
-
return nil unless argvs['body']
|
|
315
|
+
return nil if argvs['mail'].nil? || argvs['body'].nil?
|
|
316
316
|
|
|
317
317
|
mailheader = argvs['mail']['header']
|
|
318
318
|
bodystring = argvs['body']
|
|
319
319
|
hookmethod = argvs['hook'] || nil
|
|
320
320
|
havecaught = nil
|
|
321
|
-
return nil
|
|
321
|
+
return nil if mailheader.nil?
|
|
322
322
|
|
|
323
323
|
# PRECHECK_EACH_HEADER:
|
|
324
324
|
# Set empty string if the value is nil
|
|
@@ -351,7 +351,7 @@ module Sisimai
|
|
|
351
351
|
# NOT text/plain
|
|
352
352
|
# In case of Content-Type: multipart/*
|
|
353
353
|
p = Sisimai::RFC2045.makeflat(mailheader['content-type'], bodystring)
|
|
354
|
-
bodystring = p
|
|
354
|
+
bodystring = p if p.empty? == false
|
|
355
355
|
end
|
|
356
356
|
bodystring = bodystring.scrub('?').delete("\r").gsub("\t", " ")
|
|
357
357
|
|
|
@@ -412,7 +412,7 @@ module Sisimai
|
|
|
412
412
|
break # as of now, we have no sample email for coding this block
|
|
413
413
|
end
|
|
414
414
|
end
|
|
415
|
-
return nil
|
|
415
|
+
return nil if havesifted.nil?
|
|
416
416
|
|
|
417
417
|
havesifted['catch'] = havecaught
|
|
418
418
|
modulename = modulename.sub(/\A.+::/, '')
|
data/lib/sisimai/order.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Sisimai
|
|
|
11
11
|
'Sisimai::Lhost::Sendmail',
|
|
12
12
|
'Sisimai::Lhost::Exchange2007',
|
|
13
13
|
'Sisimai::Lhost::Exchange2003',
|
|
14
|
-
'Sisimai::Lhost::
|
|
14
|
+
'Sisimai::Lhost::TrendMicro',
|
|
15
15
|
'Sisimai::Lhost::KDDI',
|
|
16
16
|
'Sisimai::Lhost::FML',
|
|
17
17
|
'Sisimai::Lhost::Verizon',
|
|
@@ -38,7 +38,7 @@ module Sisimai
|
|
|
38
38
|
'Sisimai::Lhost::MFILTER',
|
|
39
39
|
'Sisimai::Lhost::MailFoundry',
|
|
40
40
|
'Sisimai::Lhost::GoogleGroups',
|
|
41
|
-
'Sisimai::Lhost::
|
|
41
|
+
'Sisimai::Lhost::MailMarshal',
|
|
42
42
|
'Sisimai::Lhost::V5sendmail',
|
|
43
43
|
'Sisimai::Lhost::EZweb',
|
|
44
44
|
'Sisimai::Lhost::Biglobe',
|
|
@@ -84,7 +84,7 @@ module Sisimai
|
|
|
84
84
|
'Sisimai::Lhost::Zoho',
|
|
85
85
|
'Sisimai::Lhost::EinsUndEins',
|
|
86
86
|
],
|
|
87
|
-
'mail-could' => ['Sisimai::Lhost::
|
|
87
|
+
'mail-could' => ['Sisimai::Lhost::TrendMicro'],
|
|
88
88
|
'mail-failure' => ['Sisimai::Lhost::Exim'],
|
|
89
89
|
'mail-system' => ['Sisimai::Lhost::EZweb'],
|
|
90
90
|
'message-delivery' => ['Sisimai::Lhost::MailFoundry'],
|
|
@@ -92,6 +92,7 @@ module Sisimai
|
|
|
92
92
|
'non-recapitabile' => ['Sisimai::Lhost::Exchange2007'],
|
|
93
93
|
'non-remis' => ['Sisimai::Lhost::Exchange2007'],
|
|
94
94
|
'notice' => ['Sisimai::Lhost::Courier'],
|
|
95
|
+
'postmaster-email' => ['Sisimai::Lhost::Mimecast'],
|
|
95
96
|
'postmaster-notify' => ['Sisimai::Lhost::Sendmail'],
|
|
96
97
|
'returned-mail' => [
|
|
97
98
|
'Sisimai::Lhost::Sendmail',
|
|
@@ -101,7 +102,7 @@ module Sisimai
|
|
|
101
102
|
],
|
|
102
103
|
'there-was' => ['Sisimai::Lhost::X6'],
|
|
103
104
|
'undeliverable' => ['Sisimai::Lhost::Exchange2007', 'Sisimai::Lhost::Exchange2003'],
|
|
104
|
-
'undeliverable-mail' => ['Sisimai::Lhost::
|
|
105
|
+
'undeliverable-mail' => ['Sisimai::Lhost::MailMarshal', 'Sisimai::Lhost::IMailServer'],
|
|
105
106
|
'undeliverable-message' => ['Sisimai::Lhost::Notes', 'Sisimai::Lhost::Verizon'],
|
|
106
107
|
'undelivered-mail' => ['Sisimai::Lhost::Postfix', 'Sisimai::Lhost::Zoho'],
|
|
107
108
|
'warning' => ['Sisimai::Lhost::Sendmail', 'Sisimai::Lhost::Exim'],
|
|
@@ -38,7 +38,7 @@ module Sisimai
|
|
|
38
38
|
# @param [String] argv1 String to be matched with regular expressions
|
|
39
39
|
# @return [Boolean] false: Did not match, true: Matched
|
|
40
40
|
def match(argv1)
|
|
41
|
-
return false
|
|
41
|
+
return false if argv1.nil? || argv1.empty?
|
|
42
42
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
43
43
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
44
44
|
return false
|
|
@@ -30,7 +30,7 @@ module Sisimai
|
|
|
30
30
|
# @param [String] argv1 String to be matched with regular expressions
|
|
31
31
|
# @return [Boolean] false: Did not match, true: Matched
|
|
32
32
|
def match(argv1)
|
|
33
|
-
return false
|
|
33
|
+
return false if argv1.nil? || argv1.empty?
|
|
34
34
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
35
35
|
return false
|
|
36
36
|
end
|
|
@@ -41,6 +41,7 @@ module Sisimai
|
|
|
41
41
|
'invalid ip for sending mail of domain',
|
|
42
42
|
'is in a black list',
|
|
43
43
|
'is not allowed to send mail from',
|
|
44
|
+
'mailfrom domain is listed in spamhaus',
|
|
44
45
|
'no access from mail server',
|
|
45
46
|
'no matches to nameserver query',
|
|
46
47
|
'not currently accepting mail from your ip', # Microsoft
|
|
@@ -102,7 +103,7 @@ module Sisimai
|
|
|
102
103
|
# @param [String] argv1 String to be matched with regular expressions
|
|
103
104
|
# @return [Boolean] false: Did not match, true: Matched
|
|
104
105
|
def match(argv1)
|
|
105
|
-
return false
|
|
106
|
+
return false if argv1.nil? || argv1.empty?
|
|
106
107
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
107
108
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
108
109
|
return false
|
|
@@ -9,7 +9,6 @@ module Sisimai
|
|
|
9
9
|
module ContentError
|
|
10
10
|
class << self
|
|
11
11
|
Index = [
|
|
12
|
-
'duplicate header',
|
|
13
12
|
'header size exceeds maximum permitted',
|
|
14
13
|
'improper use of 8-bit data in message header',
|
|
15
14
|
'message header size, or recipient list, exceeds policy limit',
|
|
@@ -27,7 +26,7 @@ module Sisimai
|
|
|
27
26
|
# @param [String] argv1 String to be matched with regular expressions
|
|
28
27
|
# @return [Boolean] false: Did not match, true: Matched
|
|
29
28
|
def match(argv1)
|
|
30
|
-
return false
|
|
29
|
+
return false if argv1.nil? || argv1.empty?
|
|
31
30
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
32
31
|
return false
|
|
33
32
|
end
|
|
@@ -19,7 +19,7 @@ module Sisimai
|
|
|
19
19
|
# @param [String] argv1 String to be matched with regular expressions
|
|
20
20
|
# @return [Boolean] false: Did not match, true: Matched
|
|
21
21
|
def match(argv1)
|
|
22
|
-
return false
|
|
22
|
+
return false if argv1.nil? || argv1.empty?
|
|
23
23
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
24
24
|
return false
|
|
25
25
|
end
|
|
@@ -42,7 +42,7 @@ module Sisimai
|
|
|
42
42
|
# @param [String] argv1 String to be matched with regular expressions
|
|
43
43
|
# @return [Boolean] false: Did not match, true: Matched
|
|
44
44
|
def match(argv1)
|
|
45
|
-
return false
|
|
45
|
+
return false if argv1.nil? || argv1.empty?
|
|
46
46
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
47
47
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
48
48
|
return false
|
|
@@ -17,7 +17,7 @@ module Sisimai
|
|
|
17
17
|
# @param [String] argv1 String to be matched with regular expressions
|
|
18
18
|
# @return [Boolean] false: Did not match, true: Matched
|
|
19
19
|
def match(argv1)
|
|
20
|
-
return false
|
|
20
|
+
return false if argv1.nil? || argv1.empty?
|
|
21
21
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
22
22
|
return false
|
|
23
23
|
end
|
|
@@ -35,7 +35,7 @@ module Sisimai
|
|
|
35
35
|
# @param [String] argv1 String to be matched with regular expressions
|
|
36
36
|
# @return [Boolean] false: Did not match, true: Matched
|
|
37
37
|
def match(argv1)
|
|
38
|
-
return false
|
|
38
|
+
return false if argv1.nil? || argv1.empty?
|
|
39
39
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
40
40
|
return false
|
|
41
41
|
end
|
|
@@ -17,7 +17,7 @@ module Sisimai
|
|
|
17
17
|
# @param [String] argv1 String to be matched with regular expressions
|
|
18
18
|
# @return [Boolean] false: Did not match, true: Matched
|
|
19
19
|
def match(argv1)
|
|
20
|
-
return false
|
|
20
|
+
return false if argv1.nil? || argv1.empty?
|
|
21
21
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
22
22
|
return false
|
|
23
23
|
end
|
|
@@ -35,7 +35,7 @@ module Sisimai
|
|
|
35
35
|
# @return [Boolean] false: Did not match, true: Matched
|
|
36
36
|
# @since v4.0.0
|
|
37
37
|
def match(argv1)
|
|
38
|
-
return false
|
|
38
|
+
return false if argv1.nil? || argv1.empty?
|
|
39
39
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
40
40
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
41
41
|
return false
|
|
@@ -55,7 +55,7 @@ module Sisimai
|
|
|
55
55
|
if Sisimai::SMTP::Status.name(statuscode) == 'hostunknown'
|
|
56
56
|
# To prevent classifying DNS errors as "HostUnknown"
|
|
57
57
|
require 'sisimai/reason/networkerror'
|
|
58
|
-
return true
|
|
58
|
+
return true if Sisimai::Reason::NetworkError.match(issuedcode) == false
|
|
59
59
|
else
|
|
60
60
|
# Status: 5.1.2
|
|
61
61
|
# Diagnostic-Code: SMTP; 550 Host unknown
|
|
@@ -66,7 +66,7 @@ module Sisimai
|
|
|
66
66
|
# @param [String] argv1 String to be matched with regular expressions
|
|
67
67
|
# @return [Boolean] false: Did not match, true: Matched
|
|
68
68
|
def match(argv1)
|
|
69
|
-
return false
|
|
69
|
+
return false if argv1.nil? || argv1.empty?
|
|
70
70
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
71
71
|
return false
|
|
72
72
|
end
|
|
@@ -30,7 +30,7 @@ module Sisimai
|
|
|
30
30
|
# @param [String] argv1 String to be matched with regular expressions
|
|
31
31
|
# @return [Boolean] false: Did not match, true: Matched
|
|
32
32
|
def match(argv1)
|
|
33
|
-
return false
|
|
33
|
+
return false if argv1.nil? || argv1.empty?
|
|
34
34
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
35
35
|
return false
|
|
36
36
|
end
|
|
@@ -29,7 +29,7 @@ module Sisimai
|
|
|
29
29
|
# @param [String] argv1 String to be matched with regular expressions
|
|
30
30
|
# @return [Boolean] false: Did not match, true: Matched
|
|
31
31
|
def match(argv1)
|
|
32
|
-
return false
|
|
32
|
+
return false if argv1.nil? || argv1.empty?
|
|
33
33
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
34
34
|
return false
|
|
35
35
|
end
|
|
@@ -36,7 +36,7 @@ module Sisimai
|
|
|
36
36
|
# @param [String] argv1 String to be matched with regular expressions
|
|
37
37
|
# @return [Boolean] false: Did not match, true: Matched
|
|
38
38
|
def match(argv1)
|
|
39
|
-
return false
|
|
39
|
+
return false if argv1.nil? || argv1.empty?
|
|
40
40
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
41
41
|
return false
|
|
42
42
|
end
|
|
@@ -28,7 +28,7 @@ module Sisimai
|
|
|
28
28
|
'specified domain is not allowed',
|
|
29
29
|
"that domain isn't in my list of allowed rcpthost",
|
|
30
30
|
'this system is not configured to relay mail',
|
|
31
|
-
'unable to relay
|
|
31
|
+
'unable to relay ',
|
|
32
32
|
"we don't handle mail for",
|
|
33
33
|
].freeze
|
|
34
34
|
|
|
@@ -39,7 +39,7 @@ module Sisimai
|
|
|
39
39
|
# @param [String] argv1 String to be matched with regular expressions
|
|
40
40
|
# @return [Boolean] false: Did not match, true: Matched
|
|
41
41
|
def match(argv1)
|
|
42
|
-
return false
|
|
42
|
+
return false if argv1.nil? || argv1.empty?
|
|
43
43
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
44
44
|
return false
|
|
45
45
|
end
|
|
@@ -11,9 +11,8 @@ module Sisimai
|
|
|
11
11
|
class << self
|
|
12
12
|
# Destination mail server does not accept any message
|
|
13
13
|
Index = [
|
|
14
|
-
'does not accept mail
|
|
14
|
+
'does not accept mail', # Sendmail
|
|
15
15
|
'host/domain does not accept mail', # iCloud
|
|
16
|
-
'host does not accept mail', # Sendmail
|
|
17
16
|
'mail receiving disabled',
|
|
18
17
|
'name server: .: host not found', # Sendmail
|
|
19
18
|
'no mx record found for domain=', # Oath(Yahoo!)
|
|
@@ -28,7 +27,7 @@ module Sisimai
|
|
|
28
27
|
# @param [String] argv1 String to be matched with regular expressions
|
|
29
28
|
# @return [Boolean] false: Did not match, true: Matched
|
|
30
29
|
def match(argv1)
|
|
31
|
-
return false
|
|
30
|
+
return false if argv1.nil? || argv1.empty?
|
|
32
31
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
33
32
|
return false
|
|
34
33
|
end
|
|
@@ -25,7 +25,7 @@ module Sisimai
|
|
|
25
25
|
# @param [String] argv1 String to be matched with regular expressions
|
|
26
26
|
# @return [Boolean] false: Did not match, true: Matched
|
|
27
27
|
def match(argv1)
|
|
28
|
-
return false
|
|
28
|
+
return false if argv1.nil? || argv1.empty?
|
|
29
29
|
return true if Index.any? { |a| argv1.include?(a) }
|
|
30
30
|
return true if Pairs.any? { |a| Sisimai::String.aligned(argv1, a) }
|
|
31
31
|
return false
|