@@ -5,12 +5,12 @@ import (
5
5
"github.com/wjdp/htmltest/issues"
6
6
"github.com/wjdp/htmltest/output"
7
7
"golang.org/x/net/html"
8
+ "net"
8
9
"net/http"
9
10
"net/url"
10
11
"os"
11
12
"path"
12
13
"strings"
13
- "net"
14
14
)
15
15
16
16
func (hT * HTMLTest ) checkLink (document * htmldoc.Document , node * html.Node ) {
@@ -349,45 +349,68 @@ func (hT *HTMLTest) checkMailto(ref *htmldoc.Reference) {
349
349
return
350
350
}
351
351
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
355
353
var dnserr * net.DNSError
356
354
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
375
364
hT .issueStore .AddIssue (issues.Issue {
376
365
Level : issues .LevelWarning ,
377
366
Message : "unable to perform LookupMX, unknown error" ,
378
367
Reference : ref ,
379
368
})
380
369
return
381
370
}
382
- }
383
371
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
+
391
414
}
392
415
}
393
416
0 commit comments