@@ -5,12 +5,12 @@ import (
55 "github.com/wjdp/htmltest/issues"
66 "github.com/wjdp/htmltest/output"
77 "golang.org/x/net/html"
8+ "net"
89 "net/http"
910 "net/url"
1011 "os"
1112 "path"
1213 "strings"
13- "net"
1414)
1515
1616func (hT * HTMLTest ) checkLink (document * htmldoc.Document , node * html.Node ) {
@@ -349,45 +349,68 @@ func (hT *HTMLTest) checkMailto(ref *htmldoc.Reference) {
349349 return
350350 }
351351
352- // split off domain, check mx, fallback to A or AAAA if that fais
353- domain := strings .Split (ref .URL .Opaque , "@" )[1 ]
354- _ , err := net .LookupMX (domain )
352+ // split off domain, check mx, fallback to A or AAAA if that fails
355353 var dnserr * net.DNSError
356354 var ok bool
357- if err != nil {
358- if dnserr , ok = err .(* net.DNSError ); ok {
359- switch dnserr .Err {
360- case "no such host" :
361- // current no MX records, but we should try again with A record
362- _ , err := net .LookupHost (domain )
363- if dnserr , ok = err .(* net.DNSError ); ok {
364- break
365- } else {
366- hT .issueStore .AddIssue (issues.Issue {
367- Level : issues .LevelWarning ,
368- Message : "unable to perform LookupHost, unknown error" ,
369- Reference : ref ,
370- })
371- return
372- }
373- }
374- } else {
355+
356+ domain := strings .Split (ref .URL .Opaque , "@" )[1 ]
357+
358+ for domain != "" {
359+ // if a simple MX lookup works, we are done, continue
360+ if _ , err := net .LookupMX (domain ); err == nil {
361+ break // success, time to exit
362+ } else if dnserr , ok = err .(* net.DNSError ); ! ok || dnserr .Err != "no such host" {
363+ // this isn't an error we are expecting to see here
375364 hT .issueStore .AddIssue (issues.Issue {
376365 Level : issues .LevelWarning ,
377366 Message : "unable to perform LookupMX, unknown error" ,
378367 Reference : ref ,
379368 })
380369 return
381370 }
382- }
383371
384- // check if we finally have a dnserr
385- if dnserr != nil {
386- hT .issueStore .AddIssue (issues.Issue {
387- Level : issues .LevelError ,
388- Message : "email cannot be routed to domain, no MX/A/AAAA records" ,
389- Reference : ref ,
390- })
372+ // do we have to restart because of a CNAME
373+ if cname , err := net .LookupCNAME (domain ); err == nil && cname != domain {
374+ // we have a valid CNAME, try with that. Loops return NXDOMAIN by default
375+ domain = cname
376+ continue
377+
378+ } else if dnserr , ok = err .(* net.DNSError ); ! ok || dnserr .Err != "no such host" {
379+ // this isn't an error we are expecting to see here
380+ hT .issueStore .AddIssue (issues.Issue {
381+ Level : issues .LevelWarning ,
382+ Message : "unable to perform LookupCNAME, unknown error" ,
383+ Reference : ref ,
384+ })
385+ return
386+ }
387+
388+ // an A or AAAA record here would be valid
389+ if _ , err := net .LookupHost (domain ); err == nil {
390+ break // its not ideal, but a valid A/AAAA record is acceptable for email
391+ } else {
392+ dnserr , ok = err .(* net.DNSError )
393+ if ! ok || dnserr .Err != "no such host" {
394+ // we shouldn't see this here
395+ hT .issueStore .AddIssue (issues.Issue {
396+ Level : issues .LevelWarning ,
397+ Message : "unable to perform LookupHost, unknown error" ,
398+ Reference : ref ,
399+ })
400+ return
401+ }
402+
403+ if dnserr .Err == "no such host" {
404+ // represents NXDOMAIN or no records
405+ hT .issueStore .AddIssue (issues.Issue {
406+ Level : issues .LevelError ,
407+ Message : "email domain could not be resolved correctly" ,
408+ Reference : ref ,
409+ })
410+ return
411+ }
412+ }
413+
391414 }
392415}
393416
0 commit comments