mailreport 0.1.1 → 0.1.2
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/CHANGELOG.md +5 -0
- data/README.md +2 -1
- data/lib/mailreport/archive.rb +9 -2
- data/lib/mailreport/dmarc/document.rb +15 -4
- data/lib/mailreport/version.rb +1 -1
- data/mailreport.gemspec +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f3d7ccde2b425bc6a1c990efde170016e4ec813c00d3c7ee69c289463f418052
|
|
4
|
+
data.tar.gz: b2e035153e75905c2d13ee5277dd64aac25a7f8bd328f83a7507ee074a457b24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 65e069ab2aaf56f78be9fcf0553ebefc53e4c68d5831cc6aaa79f609aa7c1e0e4a827c9b612ca8a43af0917954aa65320737021a68edf160e49c7bcf4220d87e
|
|
7
|
+
data.tar.gz: a976676695518993833d4b742907113fa2a57bea2a7c767e2dfff2f43c5073e731475f2e1c2685a7cdd77be65a95497653a99259aa20ee1526af9a312ede1469
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -124,12 +124,13 @@ This is deliberately different from a report carrying no records - that one is a
|
|
|
124
124
|
A `rua` address is published in DNS, so anyone can send anything to it, and the limits assume as much:
|
|
125
125
|
|
|
126
126
|
- **Entity declarations are refused.** A report has none of its own, so the expansion bomb is refused with them. Escapes a real document needs (`&`, `é`) still read.
|
|
127
|
-
- **Decompression stops at
|
|
127
|
+
- **Decompression stops at 2 MB** rather than running to completion.
|
|
128
128
|
|
|
129
129
|
```ruby
|
|
130
130
|
MailReport::Archive.open(bytes, max_size: 1024 * 1024)
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
+
- **A document of more than 25,000 tags is refused**, however few bytes it spends on them. Tags cost time and memory to read whatever their size, so the count is bounded to 500 records.
|
|
133
134
|
- **External references are never resolved** - no document reads a file, a URL, or a DNS name.
|
|
134
135
|
- **A zip entry is bounded as it inflates**, not on the size it claims.
|
|
135
136
|
|
data/lib/mailreport/archive.rb
CHANGED
|
@@ -9,7 +9,9 @@ module MailReport
|
|
|
9
9
|
GZIP = "\x1f\x8b".b
|
|
10
10
|
ZIP = "PK".b
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
# Real reports run to KBs; this is headroom, not an expectation - and
|
|
13
|
+
# every byte of it is parse cost a caller may pay before refusing.
|
|
14
|
+
MAX_SIZE = 2 * 1024 * 1024
|
|
13
15
|
CHUNK_SIZE = 64 * 1024
|
|
14
16
|
STORED = 0
|
|
15
17
|
|
|
@@ -23,13 +25,18 @@ module MailReport
|
|
|
23
25
|
def open(bytes, max_size: MAX_SIZE, name: nil)
|
|
24
26
|
bytes = bytes.to_s.b
|
|
25
27
|
|
|
28
|
+
# A real report's container never exceeds what it holds; refuse before
|
|
29
|
+
# reading a zip's central directory, whose entry count (not its bytes)
|
|
30
|
+
# is what costs time to walk.
|
|
26
31
|
if bytes.empty?
|
|
27
32
|
nil
|
|
33
|
+
elsif bytes.bytesize > max_size
|
|
34
|
+
nil
|
|
28
35
|
elsif gzipped?(bytes)
|
|
29
36
|
inflated(bytes, max_size)
|
|
30
37
|
elsif zipped?(bytes)
|
|
31
38
|
unzipped(bytes, max_size, name)
|
|
32
|
-
|
|
39
|
+
else
|
|
33
40
|
bytes
|
|
34
41
|
end
|
|
35
42
|
rescue *UNREADABLE
|
|
@@ -10,8 +10,11 @@ module MailReport
|
|
|
10
10
|
|
|
11
11
|
PREDEFINED_ENTITIES = %w[ lt gt amp quot apos ].freeze
|
|
12
12
|
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# A tag costs time and memory to build however few bytes it spends, so
|
|
14
|
+
# the count is bounded as well as the size. Room for some 500 records
|
|
15
|
+
MAX_TAGS = 25_000
|
|
16
|
+
|
|
17
|
+
# REXML raises a bare RuntimeError when expansion limits trip
|
|
15
18
|
EXPANSION_ABANDONED = /entity expansions exceeded|entity expansion has grown too large/
|
|
16
19
|
|
|
17
20
|
def initialize(xml)
|
|
@@ -34,9 +37,17 @@ module MailReport
|
|
|
34
37
|
|
|
35
38
|
private
|
|
36
39
|
def feedback
|
|
37
|
-
|
|
40
|
+
if countable?
|
|
41
|
+
document = REXML::Document.new(@xml)
|
|
42
|
+
|
|
43
|
+
document.root if readable?(document) && document.root&.name == ROOT
|
|
44
|
+
end
|
|
45
|
+
end
|
|
38
46
|
|
|
39
|
-
|
|
47
|
+
# Every tag opens with one, so this over-counts where text or a comment
|
|
48
|
+
# holds a `<` — which refuses in the direction we want.
|
|
49
|
+
def countable?
|
|
50
|
+
@xml.to_s.count("<") <= MAX_TAGS
|
|
40
51
|
end
|
|
41
52
|
|
|
42
53
|
# Refuse any declared entity before text is read (expansion timing).
|
data/lib/mailreport/version.rb
CHANGED
data/mailreport.gemspec
CHANGED
|
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
|
|
|
9
9
|
spec.authors = [ "Simon Lev" ]
|
|
10
10
|
|
|
11
11
|
spec.summary = "DMARC report parsing for Ruby."
|
|
12
|
-
spec.description = "Answers one question: how does your mail look on their end? Reads the reports receivers send back about your domain."
|
|
12
|
+
spec.description = "Answers one question: how does your mail look on their end? Reads the reports receivers send back about your domain. Parses DMARC aggregate (RUA) and failure (RUF) reports."
|
|
13
13
|
|
|
14
14
|
spec.homepage = "https://github.com/mailpiece/mailreport"
|
|
15
15
|
spec.license = "MIT"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mailreport
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Simon Lev
|
|
@@ -38,7 +38,8 @@ dependencies:
|
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
39
|
version: '6.3'
|
|
40
40
|
description: 'Answers one question: how does your mail look on their end? Reads the
|
|
41
|
-
reports receivers send back about your domain.
|
|
41
|
+
reports receivers send back about your domain. Parses DMARC aggregate (RUA) and
|
|
42
|
+
failure (RUF) reports.'
|
|
42
43
|
executables: []
|
|
43
44
|
extensions: []
|
|
44
45
|
extra_rdoc_files: []
|