I thought for a couple of minutes wether to answer this question. The reason for this being that you obviously expect us to read that modules code for you and come up with a solution. Which, to be honest with you, is a bit of a thing considered that you have "requirements", implicating business.
However, others may learn from it and you will have to put enough effort into it to make the code robust enough (IPv6, anyone?).
Basically, you have two questions: "How to get the SPF record for a domain and return it when there is one?" and "How to properly deal with code submissions on github (or git based code hosters in general)?"
How to get the SPF record for a domain, if there is one?
At the end of the day, SPF is a convention utilizing existing technology. An SPF entry is nothing else than a specially formatted TXT resource record in a domain.
Hence, you do not need any package to find our whether a domain has an SPF entry:
package main
import (
"flag"
"log"
"net"
"os"
"regexp"
)
var domain string
var spfPattern *regexp.Regexp
var verbose bool
func init() {
// some flags to make the problem more usable.
flag.StringVar(&domain, "domain", "", "the domain to check for SPF records")
flag.BoolVar(&verbose, "verbose", false, "print moar!")
// Obviously, this is a very, very simple pattern.
// It lacks any true validation whether the TXT record
// is in fact a valid SPF. Expanding the regex should
// not be too hard and I leave it up to you.
spfPattern = regexp.MustCompile(`\s*v=spf1.*`)
}
func main() {
flag.Parse()
// Lookup ALL resource records rs of type TXT for domain.
rs, err := net.LookupTXT(domain)
// If there was an error accessing the TXT records...
if err != nil {
// ...we inform the user and...
log.Printf("accessing TXT records for %s", err)
// ...inform the caller that something went wrong.
os.Exit(1)
}
// Now we have all TXT records for the domain we iterate through them...
for _, rr := range rs {
// ... and if one of them matches the pattern of an SPF record...
if spfPattern.MatchString(rr) {
// ...we inform the user if the user requested it...
if verbose {
log.Printf("%s has a valid SPFv1 record: %s", domain, rr)
}
// ...or simply inform the caller, as per the UNIX convention
// "No news is good news!"
os.Exit(0)
}
}
// We have iterated through all TXT records and did not find matching
// the pattern of an SPF record, so we need to inform both the user...
log.Println("No valid SPF record found.")
// ...and the caller.
os.Exit(2)
}
How to properly deal with code contributions
If you see code you think needs expansions, or you found a bug and you want to fix it, the first think you should do is to fork the original repository -- basically, you make a copy of it, with the advantage to retain the commit history.
Next, you clone your fork, and do the work you want to do on that fork. You should use one or more branches for your changes.
Every commit should be as atomic as possible. Ideally, the library compiles and the tests run before and after any commit.
When you are done, and you think your code is ready for release, you create a pull request. A pull request basically says "Hey, owner of the original repository, I have made some changes and improved the code, you might want to consider merging my changes into the original code!"
A lot of projects nowadays use a branching model called "gitflow", and I strongly suggest you memorize it until you can sing it backwards with even a severely high BAC.
