SPF allows include: directives, but there are also limits to the number of DNS lookups which can be made. Since included rules can contain other included rules, it is not simple to determine how many levels you have, and you can quickly exceed the number of DNS lookups
RFC 7208 (section 4.6.4) states
Some mechanisms and modifiers (collectively, "terms") cause DNS queries at the time of evaluation, and some do not. The following terms cause DNS queries: the "include", "a", "mx", "ptr", and "exists" mechanisms, and the "redirect" modifier. SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS
The following scripts does not take all of that into account, though it could be easily modified to do so. Instead, it simply builds a visual display of the include tree. To get an accurate account, add the records in the RFC above, or simply visit http://mxtoolbox.com/ which has some very good tools to check your spf records
Note: this was a quick and dirty, and could use some cleanup, especially since there aren't even comments in it. Requires a system with the commands dig and grep on it.
#! /usr/bin/env perl use warnings; use strict; sub getIncludes { my $indent = shift; my $return = ''; foreach my $domain ( @_ ) { $return .= ' 'x$indent . "$domain\n"; my @lines = `dig $domain TXT | grep spf`; chomp @lines; foreach my $entry ( @lines ) { while ( $entry =~ m/include:([_a-zA-Z0-9\-\.]+)/g ) { $return .= &getIncludes( $indent+3, $1 ); } # while } # foreach } # foreach return $return; } # sub while ( my $domain = shift ) { print &getIncludes( 0, $domain ); } 1;