Class: MtaSts::Fetcher

Inherits:
Object
  • Object
show all
Defined in:
lib/mta_sts/fetcher.rb

Overview

HTTPS GET of mta-sts./.well-known/mta-sts.txt (RFC 8461 §3.3)

Defined Under Namespace

Classes: BlockedAddress, Body, CertificateError, Error, HttpError, Timeout

Constant Summary collapse

WELL_KNOWN_PATH =
"/.well-known/mta-sts.txt"
PORT =
443
OPEN_TIMEOUT =
10
READ_TIMEOUT =
10
TOTAL_TIMEOUT =

read_timeout renews per read; this one does not — stops a slow-drip body

30
MAX_BODY_BYTES =
64 * 1024
USER_AGENT =
"mta_sts/#{VERSION} (+https://github.com/mailpiece/mta_sts)"
RESERVED_V4 =

Special-use IPv4 no policy is published in. RFC 1918, loopback and link-local are left to the IPAddr predicates.

%w[
  0.0.0.0/8 100.64.0.0/10 192.0.0.0/24 192.0.2.0/24 192.88.99.0/24
  198.18.0.0/15 198.51.100.0/24 203.0.113.0/24 224.0.0.0/4 240.0.0.0/4
].map { |range| IPAddr.new(range) }.freeze
RESERVED_V6 =
%w[
  ::/128 64:ff9b:1::/48 100::/64 2001::/32 2001:2::/48 2001:db8::/32
  2002::/16 fec0::/10 ff00::/8
].map { |range| IPAddr.new(range) }.freeze
NAT64 =

RFC 6052 §2.2 with a /96 prefix

IPAddr.new("64:ff9b::/96")

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(open_timeout: OPEN_TIMEOUT, read_timeout: READ_TIMEOUT, total_timeout: TOTAL_TIMEOUT, max_body_bytes: MAX_BODY_BYTES, resolver: MailResolver::Resolver.new, permitted: Fetcher.method(:public_address?)) ⇒ Fetcher

Returns a new instance of Fetcher.



112
113
114
115
116
117
118
119
120
121
# File 'lib/mta_sts/fetcher.rb', line 112

def initialize(open_timeout: OPEN_TIMEOUT, read_timeout: READ_TIMEOUT,
               total_timeout: TOTAL_TIMEOUT, max_body_bytes: MAX_BODY_BYTES,
               resolver: MailResolver::Resolver.new, permitted: Fetcher.method(:public_address?))
  @open_timeout = open_timeout
  @read_timeout = read_timeout
  @total_timeout = total_timeout
  @max_body_bytes = max_body_bytes
  @resolver = resolver
  @permitted = permitted
end

Class Method Details

.public_address?(address) ⇒ Boolean

The policy host is named by the domain being delivered to, so where it resolves is a stranger's to choose.

Returns:

  • (Boolean)


70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/mta_sts/fetcher.rb', line 70

def public_address?(address)
  ip = address.is_a?(IPAddr) ? address : IPAddr.new(address.to_s)

  case
  # No resolver legitimately answers with an address wrapped in another,
  # whatever it wraps.
  when ip.ipv4_mapped? || ipv4_compat?(ip) then false
  when ip.ipv4?                           then public_v4?(ip)
  when NAT64.include?(ip)                 then public_v4?(embedded_v4(ip))
  else                                         public_v6?(ip)
  end
rescue IPAddr::Error
  false
end

Instance Method Details

#fetch(host) ⇒ Object



123
124
125
# File 'lib/mta_sts/fetcher.rb', line 123

def fetch(host)
  get(normalize(host))
end