ansible-role-mail/files/postscreen_access_spf_gener...

63 lines
1.2 KiB
Ruby

#!/usr/bin/env ruby
require 'shellwords'
require 'ipaddress'
require 'resolv'
class R
def initialize opts=nil
@resolv = Resolv::DNS.new opts
end
IN = Resolv::DNS::Resource::IN
def a( q) @resolv.getresources( q, IN::A) end
def aaaa( q) @resolv.getresources( q, IN::AAAA) end
def txt( q) @resolv.getresources( q, IN::TXT) end
def mx( q) @resolv.getresources( q, IN::MX) end
def ip q
a(q) + aaaa(q)
end
end
$resolv = R.new
def bb d
$resolv.txt( d).map do |l|
v, *as = l.data.split( ' ')
if "v=spf1" == v
as.map do |a|
case a
when /\Aa:(.*)\z/
$resolv.ip( $1).map( &:address)
when "mx"
$resolv.mx( d).map do |l|
$resolv.ip( l.exchange.to_s).map( &:address)
end
when /\Aip[46]:(.*)\z/ then $1
when /\A(?:redirect=|include:)(.*)\z/ then bb $1
when /\A[-~+]all/ then nil
else nil
end
end
end
end
end
ARGV.
flat_map do |d|
bb( d).
flatten.
compact.
uniq.
map {|x| IPAddress.parse( x).first.to_string rescue ArgumentError }.
select {|x| String === x }.
uniq.
map {|x| [x, d]}
end.
group_by {|(x,d)| x }.
each {|x,xs| xs.map! &:last }.
sort_by {|x,ds| x = IPAddress.parse x; [x.class.name, x] }.
each do |(x,ds)|
puts "#{x} permit # #{ds.uniq.sort.join ' '}"
end