sisimai 5.4.0-java → 5.5.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 +4 -4
- data/.github/workflows/codecovio.yml +1 -1
- data/.github/workflows/rake-test.yml +1 -1
- data/ChangeLog.md +45 -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 +26 -22
- 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 +80 -29
- 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 +5 -4
- 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-apple-05.eml +96 -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 +27 -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
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
module Sisimai::Lhost
|
|
2
|
+
# Sisimai::Lhost::Mimecast decodes a bounce email which created by Mimecast https://www.mimecast.com/.
|
|
3
|
+
# Methods in the module are called from only Sisimai::Message.
|
|
4
|
+
module Mimecast
|
|
5
|
+
class << self
|
|
6
|
+
require 'sisimai/lhost'
|
|
7
|
+
|
|
8
|
+
Indicators = Sisimai::Lhost.INDICATORS
|
|
9
|
+
Boundaries = ['Content-Type: message/rfc822'].freeze # No such line in lhost-mimecast-*
|
|
10
|
+
StartingOf = {message: ['-- ']}.freeze
|
|
11
|
+
|
|
12
|
+
# @abstract Decodes the bounce message from Mimecast
|
|
13
|
+
# @param [Hash] mhead Message headers of a bounce email
|
|
14
|
+
# @param [String] mbody Message body of a bounce email
|
|
15
|
+
# @return [Hash] Bounce data list and message/rfc822 part
|
|
16
|
+
# @return [Nil] it failed to decode or the arguments are missing
|
|
17
|
+
def inquire(mhead, mbody)
|
|
18
|
+
match = 0
|
|
19
|
+
match += 1 if mhead['subject'].include?('Email Delivery Failure')
|
|
20
|
+
if mhead['message-id']
|
|
21
|
+
# Message-Id: <0123456789-1102117314000@us-mta-25.us.mimecast.lan>
|
|
22
|
+
match += 1 if mhead['message-id'].include?('.mimecast.lan>')
|
|
23
|
+
end
|
|
24
|
+
return nil if match == 0
|
|
25
|
+
|
|
26
|
+
require 'sisimai/rfc1123'
|
|
27
|
+
require 'sisimai/rfc1894'
|
|
28
|
+
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
|
29
|
+
permessage = {} # (Hash) Store values of each Per-Message field
|
|
30
|
+
|
|
31
|
+
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
|
|
32
|
+
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
|
33
|
+
bodyslices = emailparts[0].split("\n")
|
|
34
|
+
readcursor = 0 # (Integer) Points the current cursor position
|
|
35
|
+
recipients = 0 # (Integer) The number of 'Final-Recipient' header
|
|
36
|
+
|
|
37
|
+
while e = bodyslices.shift do
|
|
38
|
+
# Read error messages and delivery status lines from the head of the email to the previous
|
|
39
|
+
# line of the beginning of the original message.
|
|
40
|
+
if readcursor == 0
|
|
41
|
+
# Beginning of the bounce message or message/delivery-status part
|
|
42
|
+
readcursor |= Indicators[:deliverystatus] if e.include?(StartingOf[:message][0])
|
|
43
|
+
end
|
|
44
|
+
next if (readcursor & Indicators[:deliverystatus]) == 0 || e.empty?
|
|
45
|
+
|
|
46
|
+
v = dscontents[-1]
|
|
47
|
+
if e.start_with?('-- ')
|
|
48
|
+
# An email that you attempted to send to the following address could not be delivered:
|
|
49
|
+
# -- sabineko@neko.ef.example.org
|
|
50
|
+
cv = e[3, 256]
|
|
51
|
+
if cv.include?(' ') == false
|
|
52
|
+
# -- sotoneko@cat.example.com
|
|
53
|
+
if v["recipient"] != ""
|
|
54
|
+
# There are multiple recipient addresses in the message body.
|
|
55
|
+
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
|
56
|
+
v = dscontents[-1]
|
|
57
|
+
end
|
|
58
|
+
v['recipient'] = Sisimai::Address.s3s4(cv)
|
|
59
|
+
recipients += 1
|
|
60
|
+
else
|
|
61
|
+
# Deal each line begins with "-- " as an error message.
|
|
62
|
+
# The problem appears to be :
|
|
63
|
+
# -- Recipient email address is possibly incorrect
|
|
64
|
+
# Additional information follows :
|
|
65
|
+
# -- 5.4.1 Recipient address rejected: Access denied.
|
|
66
|
+
v["diagnosis"] += cv + " "
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
# Lines after Content-Type: message/delivery-status
|
|
70
|
+
f = Sisimai::RFC1894.match(e)
|
|
71
|
+
if f > 0
|
|
72
|
+
# "e" matched with any field defined in RFC3464
|
|
73
|
+
next unless o = Sisimai::RFC1894.field(e)
|
|
74
|
+
|
|
75
|
+
if o[3] == 'code'
|
|
76
|
+
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
|
77
|
+
v['spec'] = o[1]
|
|
78
|
+
v['diagnosis'] = o[2]
|
|
79
|
+
else
|
|
80
|
+
# Other DSN fields defined in RFC3464
|
|
81
|
+
next if fieldtable[o[0]].nil?
|
|
82
|
+
next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
|
|
83
|
+
v[fieldtable[o[0]]] = o[2]
|
|
84
|
+
|
|
85
|
+
next if f != 1
|
|
86
|
+
permessage[fieldtable[o[0]]] = o[2]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
return nil if recipients == 0
|
|
92
|
+
|
|
93
|
+
dscontents.each do |e|
|
|
94
|
+
# Set default values if each value is empty.
|
|
95
|
+
permessage.each_key { |a| e[a] ||= permessage[a] || '' }
|
|
96
|
+
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis']) || ''
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
100
|
+
end
|
|
101
|
+
def description; return 'Mimecast'; end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
data/lib/sisimai/lhost/notes.rb
CHANGED
|
@@ -22,7 +22,7 @@ module Sisimai::Lhost
|
|
|
22
22
|
# @return [Hash] Bounce data list and message/rfc822 part
|
|
23
23
|
# @return [Nil] it failed to decode or the arguments are missing
|
|
24
24
|
def inquire(mhead, mbody)
|
|
25
|
-
return nil
|
|
25
|
+
return nil if mhead['subject'].start_with?('Undeliverable message') == false
|
|
26
26
|
|
|
27
27
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
|
|
28
28
|
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
|
@@ -89,16 +89,16 @@ module Sisimai::Lhost
|
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
if recipients == 0
|
|
93
93
|
# Fallback: Get the recpient address from RFC822 part
|
|
94
94
|
p1 = emailparts[1].index("\nTo: ") || -1
|
|
95
95
|
p2 = emailparts[1].index("\n", p1 + 6) || -1
|
|
96
96
|
if p1 > 0
|
|
97
97
|
v['recipient'] = Sisimai::Address.s3s4(emailparts[1][p1 + 5, p2 - p1 - 5])
|
|
98
|
-
recipients += 1
|
|
98
|
+
recipients += 1 if v['recipient'].empty? == false
|
|
99
99
|
end
|
|
100
100
|
end
|
|
101
|
-
return nil
|
|
101
|
+
return nil if recipients == 0
|
|
102
102
|
|
|
103
103
|
dscontents.each do |e|
|
|
104
104
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
@@ -106,7 +106,7 @@ module Sisimai::Lhost
|
|
|
106
106
|
|
|
107
107
|
MessagesOf.each_key do |r|
|
|
108
108
|
# Check each regular expression of Notes error messages
|
|
109
|
-
next
|
|
109
|
+
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
110
110
|
e['reason'] = r
|
|
111
111
|
e['status'] = Sisimai::SMTP::Status.code(r.to_s) || ''
|
|
112
112
|
break
|
|
@@ -72,9 +72,9 @@ module Sisimai::Lhost
|
|
|
72
72
|
# @return [Hash] Bounce data list and message/rfc822 part
|
|
73
73
|
# @return [Nil] it failed to decode or the arguments are missing
|
|
74
74
|
def inquire(mhead, mbody)
|
|
75
|
-
return nil
|
|
76
|
-
return nil
|
|
77
|
-
return nil
|
|
75
|
+
return nil if mhead['subject'].start_with?('Delivery status notification') == false
|
|
76
|
+
return nil if mhead['from'].start_with?('Mailer Daemon <') == false
|
|
77
|
+
return nil if mhead['received'].none? { |a| a.include?(' (OpenSMTPD) with ') }
|
|
78
78
|
|
|
79
79
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
|
|
80
80
|
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
|
@@ -116,13 +116,13 @@ module Sisimai::Lhost
|
|
|
116
116
|
recipients += 1
|
|
117
117
|
end
|
|
118
118
|
end
|
|
119
|
-
return nil
|
|
119
|
+
return nil if recipients == 0
|
|
120
120
|
|
|
121
121
|
dscontents.each do |e|
|
|
122
122
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
123
123
|
MessagesOf.each_key do |r|
|
|
124
124
|
# Verify each regular expression of session errors
|
|
125
|
-
next
|
|
125
|
+
next if MessagesOf[r].none? { |a| e['diagnosis'].include?(a) }
|
|
126
126
|
e['reason'] = r
|
|
127
127
|
break
|
|
128
128
|
end
|
|
@@ -6,6 +6,7 @@ module Sisimai::Lhost
|
|
|
6
6
|
require 'sisimai/lhost'
|
|
7
7
|
require 'sisimai/rfc1123'
|
|
8
8
|
require 'sisimai/smtp/reply'
|
|
9
|
+
require 'sisimai/smtp/status'
|
|
9
10
|
require 'sisimai/smtp/command'
|
|
10
11
|
|
|
11
12
|
# Postfix manual - bounce(5) - http://www.postfix.org/bounce.5.html
|
|
@@ -55,8 +56,7 @@ module Sisimai::Lhost
|
|
|
55
56
|
require 'sisimai/smtp/transcript'
|
|
56
57
|
transcript = Sisimai::SMTP::Transcript.rise(emailparts[0], 'In:', 'Out:')
|
|
57
58
|
|
|
58
|
-
return nil
|
|
59
|
-
return nil if transcript.size == 0
|
|
59
|
+
return nil if transcript.nil? || transcript.size == 0
|
|
60
60
|
|
|
61
61
|
transcript.each do |e|
|
|
62
62
|
# Pick email addresses, error messages, and the last SMTP command.
|
|
@@ -113,18 +113,22 @@ module Sisimai::Lhost
|
|
|
113
113
|
if o[3] == 'addr'
|
|
114
114
|
# Final-Recipient: rfc822; kijitora@example.jp
|
|
115
115
|
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
116
|
-
if o[
|
|
117
|
-
#
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
v
|
|
116
|
+
if Sisimai::Address.is_emailaddress(o[2])
|
|
117
|
+
# The email address is a valid email address, avoid an email address
|
|
118
|
+
# without a valid domain part such as "neko@mailhost".
|
|
119
|
+
if o[0] == 'final-recipient'
|
|
120
|
+
# Final-Recipient: rfc822; kijitora@example.jp
|
|
121
|
+
if v["recipient"] != ""
|
|
122
|
+
# There are multiple recipient addresses in the message body.
|
|
123
|
+
dscontents << Sisimai::Lhost.DELIVERYSTATUS
|
|
124
|
+
v = dscontents[-1]
|
|
125
|
+
end
|
|
126
|
+
v['recipient'] = o[2]
|
|
127
|
+
recipients += 1
|
|
128
|
+
else
|
|
129
|
+
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
130
|
+
v['alias'] = o[2]
|
|
122
131
|
end
|
|
123
|
-
v['recipient'] = o[2]
|
|
124
|
-
recipients += 1
|
|
125
|
-
else
|
|
126
|
-
# X-Actual-Recipient: rfc822; kijitora@example.co.jp
|
|
127
|
-
v['alias'] = o[2]
|
|
128
132
|
end
|
|
129
133
|
elsif o[3] == 'code'
|
|
130
134
|
# Diagnostic-Code: SMTP; 550 5.1.1 <userunknown@example.jp>... User Unknown
|
|
@@ -133,11 +137,11 @@ module Sisimai::Lhost
|
|
|
133
137
|
v['diagnosis'] = o[2]
|
|
134
138
|
else
|
|
135
139
|
# Other DSN fields defined in RFC3464
|
|
136
|
-
next
|
|
140
|
+
next if fieldtable[o[0]].nil?
|
|
137
141
|
next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
|
|
138
142
|
v[fieldtable[o[0]]] = o[2]
|
|
139
143
|
|
|
140
|
-
next
|
|
144
|
+
next if f != 1
|
|
141
145
|
permessage[fieldtable[o[0]]] = o[2]
|
|
142
146
|
end
|
|
143
147
|
else
|
|
@@ -161,15 +165,15 @@ module Sisimai::Lhost
|
|
|
161
165
|
# Alternative error message and recipient
|
|
162
166
|
if e.include?(' (in reply to ') || e.include?('command)')
|
|
163
167
|
# 5.1.1 <userunknown@example.co.jp>... User Unknown (in reply to RCPT TO
|
|
164
|
-
cv = Sisimai::SMTP::Command.find(e) || ""; commandset << cv
|
|
168
|
+
cv = Sisimai::SMTP::Command.find(e) || ""; commandset << cv if cv.empty? == false
|
|
165
169
|
anotherset['diagnosis'] ||= ''
|
|
166
170
|
anotherset['diagnosis'] += " #{e}"
|
|
167
171
|
|
|
168
|
-
elsif Sisimai::String.aligned(e, ['<', '@', '>', '(expanded from
|
|
172
|
+
elsif Sisimai::String.aligned(e, ['<', '@', '>', '(expanded from ', '):'])
|
|
169
173
|
# <r@example.ne.jp> (expanded from <kijitora@example.org>): user ...
|
|
170
|
-
p1 = e.index('> ')
|
|
171
|
-
p2 = e.index('(expanded from ', p1)
|
|
172
|
-
p3 = e.index('>): ', p2 + 14)
|
|
174
|
+
p1 = e.index('> '); next unless p1
|
|
175
|
+
p2 = e.index('(expanded from ', p1); next unless p2
|
|
176
|
+
p3 = e.index('>): ', p2 + 14); next unless p3
|
|
173
177
|
anotherset['recipient'] = Sisimai::Address.s3s4(e[0, p1])
|
|
174
178
|
anotherset['alias'] = Sisimai::Address.s3s4(e[p2 + 15, p3 - p2 - 15])
|
|
175
179
|
anotherset['diagnosis'] = e[p3 + 3, e.size]
|
|
@@ -192,7 +196,7 @@ module Sisimai::Lhost
|
|
|
192
196
|
nomessages = true
|
|
193
197
|
else
|
|
194
198
|
# Get an error message continued from the previous line
|
|
195
|
-
next
|
|
199
|
+
next if anotherset['diagnosis'].nil?
|
|
196
200
|
if e.start_with?(' ')
|
|
197
201
|
# host mx.example.jp said:...
|
|
198
202
|
anotherset['diagnosis'] += " #{e[4, e.size]}"
|
|
@@ -201,16 +205,20 @@ module Sisimai::Lhost
|
|
|
201
205
|
end
|
|
202
206
|
end
|
|
203
207
|
end # end of while()
|
|
204
|
-
|
|
205
208
|
end
|
|
206
209
|
|
|
207
210
|
if recipients == 0
|
|
208
211
|
# Fallback: get a recipient address from error messages
|
|
209
|
-
|
|
210
|
-
# Set a recipient address
|
|
211
|
-
|
|
212
|
+
%w[recipient alias].each do |e|
|
|
213
|
+
# Set a valid recipient address picked from the anotherset
|
|
214
|
+
next if anotherset[e].nil? || Sisimai::Address.is_emailaddress(anotherset[e]) == false
|
|
215
|
+
break if dscontents[-1]['recipient'].empty? == false
|
|
216
|
+
dscontents[-1]['recipient'] = anotherset[e]
|
|
212
217
|
recipients += 1
|
|
213
|
-
|
|
218
|
+
break
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
if recipients == 0
|
|
214
222
|
# Get a recipient address from message/rfc822 part if the delivery report was unavailable:
|
|
215
223
|
# '--- Delivery report unavailable ---'
|
|
216
224
|
p1 = emailparts[1].index("\nTo: ") || -1
|
|
@@ -222,7 +230,7 @@ module Sisimai::Lhost
|
|
|
222
230
|
end
|
|
223
231
|
end
|
|
224
232
|
end
|
|
225
|
-
return nil
|
|
233
|
+
return nil if recipients == 0
|
|
226
234
|
|
|
227
235
|
dscontents.each do |e|
|
|
228
236
|
# Set default values if each value is empty.
|
|
@@ -240,13 +248,11 @@ module Sisimai::Lhost
|
|
|
240
248
|
# More detailed error message is in "anotherset"
|
|
241
249
|
as = '' # status
|
|
242
250
|
ar = '' # replycode
|
|
243
|
-
if
|
|
251
|
+
if Sisimai::SMTP::Status.is_ambiguous(e['status'])
|
|
244
252
|
# Check the value of D.S.N. in anotherset
|
|
253
|
+
# The D.S.N. is neither an empty nor *.0.0
|
|
245
254
|
as = Sisimai::SMTP::Status.find(anotherset['diagnosis'])
|
|
246
|
-
|
|
247
|
-
# The D.S.N. is neither an empty nor *.0.0
|
|
248
|
-
e['status'] = as
|
|
249
|
-
end
|
|
255
|
+
e['status'] = as if Sisimai::SMTP::Status.is_ambiguous(as) == false
|
|
250
256
|
end
|
|
251
257
|
|
|
252
258
|
if e['replycode'].empty? || e['replycode'].end_with?('00')
|
data/lib/sisimai/lhost/qmail.rb
CHANGED
|
@@ -182,7 +182,7 @@ module Sisimai::Lhost
|
|
|
182
182
|
next if v["rhost"] != ""
|
|
183
183
|
StartingOf["rhost"].each do |r|
|
|
184
184
|
# Find a remote host name
|
|
185
|
-
p1 = e.index(r); next
|
|
185
|
+
p1 = e.index(r); next if p1.nil?
|
|
186
186
|
cm = r.size
|
|
187
187
|
p2 = e.index(" ", p1 + cm + 1) || p2 = e.rindex(".")
|
|
188
188
|
|
|
@@ -191,7 +191,7 @@ module Sisimai::Lhost
|
|
|
191
191
|
end
|
|
192
192
|
end
|
|
193
193
|
end
|
|
194
|
-
return nil
|
|
194
|
+
return nil if recipients == 0
|
|
195
195
|
|
|
196
196
|
dscontents.each do |e|
|
|
197
197
|
# Tidy up the error message in e['diagnosis'], Try to detect the bounce reason.
|
|
@@ -200,7 +200,7 @@ module Sisimai::Lhost
|
|
|
200
200
|
# Get the SMTP command name for the session
|
|
201
201
|
CommandSet.each_key do |r|
|
|
202
202
|
# Get the last SMTP command
|
|
203
|
-
next
|
|
203
|
+
next if CommandSet[r].none? { |a| e["diagnosis"].include?(a) }
|
|
204
204
|
e["command"] = r
|
|
205
205
|
break
|
|
206
206
|
end
|
|
@@ -224,10 +224,10 @@ module Sisimai::Lhost
|
|
|
224
224
|
[e["alterrors"], e["diagnosis"]].each do |f|
|
|
225
225
|
# Try to detect an error reason
|
|
226
226
|
break if e["reason"] != ""
|
|
227
|
-
next
|
|
227
|
+
next if f.nil?
|
|
228
228
|
MessagesOf.each_key do |r|
|
|
229
229
|
# The key is a bounce reason name
|
|
230
|
-
next
|
|
230
|
+
next if MessagesOf[r].none? { |a| f.include?(a) }
|
|
231
231
|
e["reason"] = r
|
|
232
232
|
break
|
|
233
233
|
end
|
|
@@ -235,7 +235,7 @@ module Sisimai::Lhost
|
|
|
235
235
|
|
|
236
236
|
FailOnLDAP.each_key do |r|
|
|
237
237
|
# The key is a bounce reason name
|
|
238
|
-
next
|
|
238
|
+
next if FailOnLDAP[r].none? { |a| f.include?(a) }
|
|
239
239
|
e["reason"] = r
|
|
240
240
|
break
|
|
241
241
|
end
|
|
@@ -31,10 +31,10 @@ module Sisimai::Lhost
|
|
|
31
31
|
# @return [Nil] it failed to decode or the arguments are missing
|
|
32
32
|
def inquire(mhead, mbody)
|
|
33
33
|
return nil if mhead['x-aol-ip']
|
|
34
|
-
match =
|
|
34
|
+
match = false
|
|
35
35
|
match ||= true if mhead['subject'].end_with?('see transcript for details')
|
|
36
36
|
match ||= true if mhead['subject'].start_with?('Warning: ')
|
|
37
|
-
return nil
|
|
37
|
+
return nil if match == false
|
|
38
38
|
|
|
39
39
|
fieldtable = Sisimai::RFC1894.FIELDTABLE
|
|
40
40
|
permessage = {} # (Hash) Store values of each Per-Message field
|
|
@@ -89,11 +89,11 @@ module Sisimai::Lhost
|
|
|
89
89
|
v['diagnosis'] = o[2]
|
|
90
90
|
else
|
|
91
91
|
# Other DSN fields defined in RFC3464
|
|
92
|
-
next
|
|
92
|
+
next if fieldtable[o[0]].nil?
|
|
93
93
|
next if o[3] == "host" && Sisimai::RFC1123.is_internethost(o[2]) == false
|
|
94
94
|
v[fieldtable[o[0]]] = o[2]
|
|
95
95
|
|
|
96
|
-
next
|
|
96
|
+
next if f != 1
|
|
97
97
|
permessage[fieldtable[o[0]]] = o[2]
|
|
98
98
|
end
|
|
99
99
|
else
|
|
@@ -108,7 +108,7 @@ module Sisimai::Lhost
|
|
|
108
108
|
# Reporting-MTA: dns; mx.example.jp
|
|
109
109
|
# Received-From-MTA: DNS; x1x2x3x4.dhcp.example.ne.jp
|
|
110
110
|
# Arrival-Date: Wed, 29 Apr 2009 16:03:18 +0900
|
|
111
|
-
|
|
111
|
+
if e.start_with?(' ') == false
|
|
112
112
|
if e.start_with?('>>> ')
|
|
113
113
|
# >>> DATA (Client Command)
|
|
114
114
|
thecommand = Sisimai::SMTP::Command.find(e) if thecommand.empty?
|
|
@@ -116,7 +116,7 @@ module Sisimai::Lhost
|
|
|
116
116
|
elsif e.start_with?('<<< ')
|
|
117
117
|
# <<< Response from the SMTP server
|
|
118
118
|
cv = e[4, e.size - 4]
|
|
119
|
-
esmtpreply << cv
|
|
119
|
+
esmtpreply << cv if esmtpreply.index(cv).nil?
|
|
120
120
|
else
|
|
121
121
|
# Detect an SMTP session error or a connection error
|
|
122
122
|
next if sessionerr
|
|
@@ -157,14 +157,14 @@ module Sisimai::Lhost
|
|
|
157
157
|
end
|
|
158
158
|
else
|
|
159
159
|
# Continued line of the value of Diagnostic-Code field
|
|
160
|
-
next
|
|
161
|
-
next
|
|
160
|
+
next if readslices[-2].start_with?('Diagnostic-Code:') == false
|
|
161
|
+
next if e.start_with?(' ') == false
|
|
162
162
|
v['diagnosis'] += " #{Sisimai::String.sweep(e)}"
|
|
163
163
|
readslices[-1] = "Diagnostic-Code: #{e}"
|
|
164
164
|
end
|
|
165
165
|
end
|
|
166
166
|
end # End of message/delivery-status
|
|
167
|
-
return nil
|
|
167
|
+
return nil if recipients == 0
|
|
168
168
|
|
|
169
169
|
dscontents.each do |e|
|
|
170
170
|
# Set default values if each value is empty.
|
|
@@ -193,9 +193,9 @@ module Sisimai::Lhost
|
|
|
193
193
|
|
|
194
194
|
while true
|
|
195
195
|
# Check alternative status code and override it
|
|
196
|
-
break
|
|
197
|
-
break
|
|
198
|
-
break if
|
|
196
|
+
break if anotherset.has_key?('status') == false
|
|
197
|
+
break if anotherset['status'].size == 0
|
|
198
|
+
break if Sisimai::SMTP::Status.test(e['status'])
|
|
199
199
|
|
|
200
200
|
e['status'] = anotherset['status']
|
|
201
201
|
break
|
|
@@ -203,7 +203,7 @@ module Sisimai::Lhost
|
|
|
203
203
|
|
|
204
204
|
# @example.jp, no local part
|
|
205
205
|
# # Get email address from the value of Diagnostic-Code field
|
|
206
|
-
next
|
|
206
|
+
next if e['recipient'].start_with?('@') == false
|
|
207
207
|
cv = Sisimai::Address.find(e['diagnosis'], true) || []
|
|
208
208
|
e['recipient'] = cv[0][:address] if cv.size > 0
|
|
209
209
|
end
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
module Sisimai::Lhost
|
|
2
|
-
# Sisimai::Lhost::
|
|
3
|
-
#
|
|
2
|
+
# Sisimai::Lhost::TrendMicro decodes a bounce email which created by TREND VISION ONE: Email and
|
|
3
|
+
# Collaboration Security: https://www.trendmicro.com/en_us/business/products/email-and-collaboration.html
|
|
4
4
|
# Methods in the module are called from only Sisimai::Message.
|
|
5
|
-
module
|
|
5
|
+
module TrendMicro
|
|
6
6
|
class << self
|
|
7
7
|
require 'sisimai/lhost'
|
|
8
8
|
Boundaries = ['Content-Type: message/rfc822'].freeze
|
|
9
9
|
|
|
10
|
-
# @abstract Decodes the bounce message from Trend Micro
|
|
10
|
+
# @abstract Decodes the bounce message from Trend Micro TREND VISION ONE
|
|
11
11
|
# @param [Hash] mhead Message headers of a bounce email
|
|
12
12
|
# @param [String] mbody Message body of a bounce email
|
|
13
13
|
# @return [Hash] Bounce data list and message/rfc822 part
|
|
@@ -23,7 +23,7 @@ module Sisimai::Lhost
|
|
|
23
23
|
match += 1 if mhead['from'].start_with?('"InterScan MSS"')
|
|
24
24
|
match += 1 if mhead['from'].start_with?('"InterScan Notification"')
|
|
25
25
|
match += 1 if tryto.any? { |a| mhead['subject'] == a }
|
|
26
|
-
return nil
|
|
26
|
+
return nil if match == 0
|
|
27
27
|
|
|
28
28
|
require 'sisimai/smtp/command'
|
|
29
29
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
|
|
@@ -65,12 +65,11 @@ module Sisimai::Lhost
|
|
|
65
65
|
else
|
|
66
66
|
# Error message in non-English
|
|
67
67
|
v['command'] = Sisimai::SMTP::Command.find(e) if e.include?(' >>> ')
|
|
68
|
-
p3 = e.index(' <<< ')
|
|
69
|
-
next unless p3
|
|
68
|
+
p3 = e.index(' <<< '); next if p3.nil?
|
|
70
69
|
v['diagnosis'] = e[p3 + 4, e.size]
|
|
71
70
|
end
|
|
72
71
|
end
|
|
73
|
-
return nil
|
|
72
|
+
return nil if recipients == 0
|
|
74
73
|
|
|
75
74
|
dscontents.each do |e|
|
|
76
75
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
@@ -78,7 +77,7 @@ module Sisimai::Lhost
|
|
|
78
77
|
end
|
|
79
78
|
return { 'ds' => dscontents, 'rfc822' => emailparts[1] }
|
|
80
79
|
end
|
|
81
|
-
def description; return '
|
|
80
|
+
def description; return 'TREND VISION ONE(Email and Collaboration Security)'; end
|
|
82
81
|
end
|
|
83
82
|
end
|
|
84
83
|
end
|
|
@@ -36,10 +36,10 @@ module Sisimai::Lhost
|
|
|
36
36
|
# @return [Nil] it failed to decode or the arguments are missing
|
|
37
37
|
def inquire(mhead, mbody)
|
|
38
38
|
# :from => %r/\AMail Delivery Subsystem/,
|
|
39
|
-
return nil
|
|
39
|
+
return nil if mhead['subject'].start_with?('Returned mail: ') == false
|
|
40
40
|
|
|
41
41
|
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
|
42
|
-
return nil
|
|
42
|
+
return nil if emailparts[1].size == 0
|
|
43
43
|
|
|
44
44
|
require 'sisimai/rfc1123'
|
|
45
45
|
require 'sisimai/smtp/command'
|
|
@@ -133,7 +133,7 @@ module Sisimai::Lhost
|
|
|
133
133
|
# There is no recipient address in the error message
|
|
134
134
|
anotherone.each_key do |e|
|
|
135
135
|
# Try to pick an recipient address, a reply code, and error messages
|
|
136
|
-
cv = Sisimai::Address.s3s4(anotherone[e]); next
|
|
136
|
+
cv = Sisimai::Address.s3s4(anotherone[e]); next if Sisimai::Address.is_emailaddress(cv) == false
|
|
137
137
|
cr = Sisimai::SMTP::Reply.find(anotherone[e])
|
|
138
138
|
|
|
139
139
|
dscontents[e]["recipient"] = cv
|
|
@@ -150,13 +150,13 @@ module Sisimai::Lhost
|
|
|
150
150
|
if p1 > 0
|
|
151
151
|
# Get the recipient address from "To:" header at the original message
|
|
152
152
|
cv = Sisimai::Address.s3s4(emailparts[1][p1, p2 - p1 - 5])
|
|
153
|
-
return nil
|
|
153
|
+
return nil if Sisimai::Address.is_emailaddress(cv) == false
|
|
154
154
|
dscontents[0]["recipient"] = cv
|
|
155
155
|
recipients += 1
|
|
156
156
|
end
|
|
157
157
|
end
|
|
158
158
|
end
|
|
159
|
-
return nil
|
|
159
|
+
return nil if recipients == 0
|
|
160
160
|
|
|
161
161
|
j = 0; dscontents.each do |e|
|
|
162
162
|
# Tidy up the error message in e.Diagnosis
|
|
@@ -169,8 +169,8 @@ module Sisimai::Lhost
|
|
|
169
169
|
# @example.jp, no local part
|
|
170
170
|
# Get email address from the value of Diagnostic-Code header
|
|
171
171
|
next if e['recipient'].include?('@')
|
|
172
|
-
p1 = e['diagnosis'].index('<'); next
|
|
173
|
-
p2 = e['diagnosis'].index('>'); next
|
|
172
|
+
p1 = e['diagnosis'].index('<'); next if p1.nil?
|
|
173
|
+
p2 = e['diagnosis'].index('>'); next if p2.nil?
|
|
174
174
|
e['recipient'] = Sisimai::Address.s3s4(e[p1, p2 - p1])
|
|
175
175
|
end
|
|
176
176
|
|
|
@@ -16,7 +16,7 @@ module Sisimai::Lhost
|
|
|
16
16
|
while true
|
|
17
17
|
# Check the value of "From" header
|
|
18
18
|
# :'subject' => %r/Undeliverable Message/,
|
|
19
|
-
break
|
|
19
|
+
break if mhead['received'].none? { |a| a.include?('.vtext.com (') }
|
|
20
20
|
match = 1 if mhead['from'] == 'post_master@vtext.com'
|
|
21
21
|
match = 0 if Sisimai::String.aligned(mhead['from'], ['sysadmin@', '.vzwpix.com'])
|
|
22
22
|
break
|
|
@@ -130,7 +130,7 @@ module Sisimai::Lhost
|
|
|
130
130
|
end
|
|
131
131
|
end
|
|
132
132
|
end
|
|
133
|
-
return nil
|
|
133
|
+
return nil if recipients == 0
|
|
134
134
|
|
|
135
135
|
# Set the value of "MAIL FROM:" and "From:"
|
|
136
136
|
emailparts[1] += "From: #{senderaddr}\n" if emailparts[1].include?("\nFrom: ") == false
|
|
@@ -140,7 +140,7 @@ module Sisimai::Lhost
|
|
|
140
140
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|
|
141
141
|
messagesof.each_key do |r|
|
|
142
142
|
# Verify each regular expression of session errors
|
|
143
|
-
next
|
|
143
|
+
next if messagesof[r].none? { |a| e['diagnosis'].include?(a) }
|
|
144
144
|
e['reason'] = r
|
|
145
145
|
break
|
|
146
146
|
end
|
data/lib/sisimai/lhost/x1.rb
CHANGED
|
@@ -6,7 +6,7 @@ module Sisimai::Lhost
|
|
|
6
6
|
require 'sisimai/lhost'
|
|
7
7
|
|
|
8
8
|
Indicators = Sisimai::Lhost.INDICATORS
|
|
9
|
-
Boundaries = ['Received: from '].freeze
|
|
9
|
+
Boundaries = ['Content-Type: message/rfc822', 'Received: from '].freeze
|
|
10
10
|
MarkingsOf = {message: ['The original message was received at ']}.freeze
|
|
11
11
|
|
|
12
12
|
# @abstract Decodes the bounce message from Unknown MTA #1
|
|
@@ -15,8 +15,11 @@ module Sisimai::Lhost
|
|
|
15
15
|
# @return [Hash] Bounce data list and message/rfc822 part
|
|
16
16
|
# @return [Nil] it failed to decode or the arguments are missing
|
|
17
17
|
def inquire(mhead, mbody)
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
proceedsto = false
|
|
19
|
+
proceedsto = true if mhead['subject'].start_with?('Returned Mail: ')
|
|
20
|
+
proceedsto = true if mhead['subject'].start_with?('Mail Delivery Failure')
|
|
21
|
+
proceedsto = true if Sisimai::String.aligned(mhead['from'], ['"Mail Deliver', 'System" '])
|
|
22
|
+
return nil if proceedsto == false
|
|
20
23
|
|
|
21
24
|
dscontents = [Sisimai::Lhost.DELIVERYSTATUS]; v = nil
|
|
22
25
|
emailparts = Sisimai::RFC5322.part(mbody, Boundaries)
|
|
@@ -61,7 +64,7 @@ module Sisimai::Lhost
|
|
|
61
64
|
datestring = e[MarkingsOf[:message][0].size, e.size]
|
|
62
65
|
end
|
|
63
66
|
end
|
|
64
|
-
return nil
|
|
67
|
+
return nil if recipients == 0
|
|
65
68
|
|
|
66
69
|
dscontents.each do |e|
|
|
67
70
|
e['diagnosis'] = Sisimai::String.sweep(e['diagnosis'])
|