Skip to content

feat(endpoints): Added new endpoints #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/miekg/dns v1.1.61 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/tools v0.22.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
)

Expand Down
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80 h1:6Yzfa6GP0rIo/kUL
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde h1:x0TT0RDC7UhAVbbWWBzr41ElhJx5tXPWkIHA2HWPRuw=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
Expand All @@ -45,6 +47,10 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
Expand All @@ -55,6 +61,8 @@ golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
Expand All @@ -79,6 +87,10 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
Expand Down
156 changes: 156 additions & 0 deletions handlers/archives.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package handlers

import (
"encoding/json"
"fmt"
"math"
"net/http"
"net/url"
"strconv"
"time"
)

const archiveAPIURL = "https://web.archive.org/cdx/search/cdx"

func convertTimestampToDate(timestamp string) (time.Time, error) {
mask := "20060102150405"
return time.Parse(mask, timestamp)

Check warning on line 17 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L15-L17

Added lines #L15 - L17 were not covered by tests
}

func countPageChanges(results [][]string) int {
prevDigest := ""
changeCount := -1
for _, curr := range results {
if curr[2] != prevDigest {
prevDigest = curr[2]
changeCount++

Check warning on line 26 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L20-L26

Added lines #L20 - L26 were not covered by tests
}
}
return changeCount

Check warning on line 29 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L29

Added line #L29 was not covered by tests
}

func getAveragePageSize(scans [][]string) int {
totalSize := 0
for _, scan := range scans {
size, err := strconv.Atoi(scan[3])
if err != nil {
continue

Check warning on line 37 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L32-L37

Added lines #L32 - L37 were not covered by tests
}
totalSize += size

Check warning on line 39 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L39

Added line #L39 was not covered by tests
}
return totalSize / len(scans)

Check warning on line 41 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L41

Added line #L41 was not covered by tests
}

func getScanFrequency(firstScan, lastScan time.Time, totalScans, changeCount int) map[string]string {
formatToTwoDecimal := func(num float64) string {
return fmt.Sprintf("%.2f", num)

Check warning on line 46 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L44-L46

Added lines #L44 - L46 were not covered by tests
}

dayFactor := lastScan.Sub(firstScan).Hours() / 24
daysBetweenScans := formatToTwoDecimal(dayFactor / float64(totalScans))
daysBetweenChanges := formatToTwoDecimal(dayFactor / float64(changeCount))
scansPerDay := formatToTwoDecimal(float64(totalScans-1) / dayFactor)
changesPerDay := formatToTwoDecimal(float64(changeCount) / dayFactor)

Check warning on line 53 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L49-L53

Added lines #L49 - L53 were not covered by tests

if math.IsNaN(dayFactor / float64(totalScans)) {
daysBetweenScans = "0.00"

Check warning on line 56 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L55-L56

Added lines #L55 - L56 were not covered by tests
}
if math.IsNaN(dayFactor / float64(changeCount)) {
daysBetweenChanges = "0.00"

Check warning on line 59 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L58-L59

Added lines #L58 - L59 were not covered by tests
}
if math.IsNaN(float64(totalScans-1) / dayFactor) {
scansPerDay = "0.00"

Check warning on line 62 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L61-L62

Added lines #L61 - L62 were not covered by tests
}
if math.IsNaN(float64(changeCount) / dayFactor) {
changesPerDay = "0.00"

Check warning on line 65 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L64-L65

Added lines #L64 - L65 were not covered by tests
}

return map[string]string{
"daysBetweenScans": daysBetweenScans,
"daysBetweenChanges": daysBetweenChanges,
"scansPerDay": scansPerDay,
"changesPerDay": changesPerDay,

Check warning on line 72 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L68-L72

Added lines #L68 - L72 were not covered by tests
}
}

func getWaybackData(url *url.URL) (map[string]interface{}, error) {
cdxUrl := fmt.Sprintf("%s?url=%s&output=json&fl=timestamp,statuscode,digest,length,offset", archiveAPIURL, url)

Check warning on line 77 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L76-L77

Added lines #L76 - L77 were not covered by tests

client := http.Client{
Timeout: 60 * time.Second,

Check warning on line 80 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L79-L80

Added lines #L79 - L80 were not covered by tests
}

resp, err := client.Get(cdxUrl)
if err != nil {
return nil, err

Check warning on line 85 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L83-L85

Added lines #L83 - L85 were not covered by tests
}
defer resp.Body.Close()

Check warning on line 87 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L87

Added line #L87 was not covered by tests

var data [][]string
err = json.NewDecoder(resp.Body).Decode(&data)
if err != nil {
return nil, err

Check warning on line 92 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L89-L92

Added lines #L89 - L92 were not covered by tests
}

if len(data) <= 1 {
return map[string]interface{}{
"skipped": "Site has never before been archived via the Wayback Machine",
}, nil

Check warning on line 98 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L95-L98

Added lines #L95 - L98 were not covered by tests
}

if len(data) < 1 {
return nil, fmt.Errorf("data slice is empty")

Check warning on line 102 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L101-L102

Added lines #L101 - L102 were not covered by tests
}

// Remove the header row
data = data[1:]

Check warning on line 106 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L106

Added line #L106 was not covered by tests

if len(data) < 1 {
return nil, fmt.Errorf("data slice became empty after removing the first element")

Check warning on line 109 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L108-L109

Added lines #L108 - L109 were not covered by tests
}

// Access the first element of the remaining data
firstScan, err := convertTimestampToDate(data[0][0])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to do a length check, before accessing data[0] and data[len(data)-1] to avoid potential panics?

if err != nil {
return nil, err

Check warning on line 115 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L113-L115

Added lines #L113 - L115 were not covered by tests
}
lastScan, err := convertTimestampToDate(data[len(data)-1][0])
if err != nil {
return nil, err

Check warning on line 119 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L117-L119

Added lines #L117 - L119 were not covered by tests
}
totalScans := len(data)
changeCount := countPageChanges(data)

Check warning on line 122 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L121-L122

Added lines #L121 - L122 were not covered by tests

return map[string]interface{}{
"firstScan": firstScan.Format(time.RFC3339),
"lastScan": lastScan.Format(time.RFC3339),
"totalScans": totalScans,
"changeCount": changeCount,
"averagePageSize": getAveragePageSize(data),
"scanFrequency": getScanFrequency(firstScan, lastScan, totalScans, changeCount),
"scans": data,
"scanUrl": url,
}, nil

Check warning on line 133 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L124-L133

Added lines #L124 - L133 were not covered by tests
}

func HandleArchives() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rawURL, err := extractURL(r)
if err != nil {
JSONError(w, ErrMissingURLParameter, http.StatusBadRequest)
return

Check warning on line 141 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L136-L141

Added lines #L136 - L141 were not covered by tests
}

data, err := getWaybackData(rawURL)
if err != nil {
http.Error(w, fmt.Sprintf("Error fetching Wayback data: %v", err), http.StatusInternalServerError)
return

Check warning on line 147 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L144-L147

Added lines #L144 - L147 were not covered by tests
}

w.Header().Set("Content-Type", "application/json")
err = json.NewEncoder(w).Encode(data)
if err != nil {
http.Error(w, fmt.Sprintf("Error encoding response: %v", err), http.StatusInternalServerError)

Check warning on line 153 in handlers/archives.go

View check run for this annotation

Codecov / codecov/patch

handlers/archives.go#L150-L153

Added lines #L150 - L153 were not covered by tests
}
})
}
142 changes: 142 additions & 0 deletions handlers/mail-config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
package handlers

import (
"net/http"
"strings"

"github.com/miekg/dns"
)

func ResolveMx(domain string) ([]*dns.MX, int, error) {
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), dns.TypeMX)
r, _, err := c.Exchange(m, "8.8.8.8:53")
if err != nil {
return nil, dns.RcodeServerFailure, err

Check warning on line 16 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L10-L16

Added lines #L10 - L16 were not covered by tests
}
if r.Rcode != dns.RcodeSuccess {
return nil, r.Rcode, &dns.Error{}

Check warning on line 19 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L18-L19

Added lines #L18 - L19 were not covered by tests
}
var mxRecords []*dns.MX
for _, ans := range r.Answer {
if mx, ok := ans.(*dns.MX); ok {
mxRecords = append(mxRecords, mx)

Check warning on line 24 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L21-L24

Added lines #L21 - L24 were not covered by tests
}
}
if len(mxRecords) == 0 {
return nil, dns.RcodeNameError, nil

Check warning on line 28 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L27-L28

Added lines #L27 - L28 were not covered by tests
}
return mxRecords, dns.RcodeSuccess, nil

Check warning on line 30 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L30

Added line #L30 was not covered by tests
}

func ResolveTxt(domain string) ([]string, int, error) {
c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), dns.TypeTXT)
r, _, err := c.Exchange(m, "8.8.8.8:53")
if err != nil {
return nil, dns.RcodeServerFailure, err

Check warning on line 39 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L33-L39

Added lines #L33 - L39 were not covered by tests
}
if r.Rcode != dns.RcodeSuccess {
return nil, r.Rcode, &dns.Error{}

Check warning on line 42 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L41-L42

Added lines #L41 - L42 were not covered by tests
}
var txtRecords []string
for _, ans := range r.Answer {
if txt, ok := ans.(*dns.TXT); ok {
txtRecords = append(txtRecords, txt.Txt...)

Check warning on line 47 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L44-L47

Added lines #L44 - L47 were not covered by tests
}
}
if len(txtRecords) == 0 {
return nil, dns.RcodeNameError, nil

Check warning on line 51 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L50-L51

Added lines #L50 - L51 were not covered by tests
}
return txtRecords, dns.RcodeSuccess, nil

Check warning on line 53 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L53

Added line #L53 was not covered by tests
}

func HandleMailConfig() http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
rawURL, err := extractURL(r)
if err != nil {
JSONError(w, ErrMissingURLParameter, http.StatusBadRequest)
return

Check warning on line 61 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L56-L61

Added lines #L56 - L61 were not covered by tests
}

mxRecords, rcode, err := ResolveMx(rawURL.Hostname())
if err != nil {
JSONError(w, err, http.StatusInternalServerError)
return

Check warning on line 67 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L64-L67

Added lines #L64 - L67 were not covered by tests
}

if rcode == dns.RcodeNameError || rcode == dns.RcodeServerFailure {
JSON(w, map[string]string{"skipped": "No mail server in use on this domain"}, http.StatusOK)
return

Check warning on line 72 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L70-L72

Added lines #L70 - L72 were not covered by tests
}

txtRecords, rcode, err := ResolveTxt(rawURL.Hostname())
if err != nil {
JSONError(w, err, http.StatusInternalServerError)
return

Check warning on line 78 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L75-L78

Added lines #L75 - L78 were not covered by tests
}

if rcode == dns.RcodeNameError || rcode == dns.RcodeServerFailure {
JSON(w, map[string]string{"skipped": "No mail server in use on this domain"}, http.StatusOK)
return

Check warning on line 83 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L81-L83

Added lines #L81 - L83 were not covered by tests
}

emailTxtRecords := filterEmailTxtRecords(txtRecords)
mailServices := identifyMailServices(emailTxtRecords, mxRecords)

Check warning on line 87 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L86-L87

Added lines #L86 - L87 were not covered by tests

JSON(w, map[string]interface{}{
"mxRecords": mxRecords,
"txtRecords": emailTxtRecords,
"mailServices": mailServices,
}, http.StatusOK)

Check warning on line 93 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L89-L93

Added lines #L89 - L93 were not covered by tests
})
}

func filterEmailTxtRecords(records []string) []string {
var emailTxtRecords []string
for _, record := range records {
if strings.HasPrefix(record, "v=spf1") ||
strings.HasPrefix(record, "v=DKIM1") ||
strings.HasPrefix(record, "v=DMARC1") ||
strings.HasPrefix(record, "protonmail-verification=") ||
strings.HasPrefix(record, "google-site-verification=") ||
strings.HasPrefix(record, "MS=") ||
strings.HasPrefix(record, "zoho-verification=") ||
strings.HasPrefix(record, "titan-verification=") ||
strings.Contains(record, "bluehost.com") {
emailTxtRecords = append(emailTxtRecords, record)

Check warning on line 109 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L97-L109

Added lines #L97 - L109 were not covered by tests
}
}
return emailTxtRecords

Check warning on line 112 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L112

Added line #L112 was not covered by tests
}

func identifyMailServices(emailTxtRecords []string, mxRecords []*dns.MX) []map[string]string {
var mailServices []map[string]string
for _, record := range emailTxtRecords {
if strings.HasPrefix(record, "protonmail-verification=") {
mailServices = append(mailServices, map[string]string{"provider": "ProtonMail", "value": strings.Split(record, "=")[1]})
} else if strings.HasPrefix(record, "google-site-verification=") {
mailServices = append(mailServices, map[string]string{"provider": "Google Workspace", "value": strings.Split(record, "=")[1]})
} else if strings.HasPrefix(record, "MS=") {
mailServices = append(mailServices, map[string]string{"provider": "Microsoft 365", "value": strings.Split(record, "=")[1]})
} else if strings.HasPrefix(record, "zoho-verification=") {
mailServices = append(mailServices, map[string]string{"provider": "Zoho", "value": strings.Split(record, "=")[1]})
} else if strings.HasPrefix(record, "titan-verification=") {
mailServices = append(mailServices, map[string]string{"provider": "Titan", "value": strings.Split(record, "=")[1]})
} else if strings.Contains(record, "bluehost.com") {
mailServices = append(mailServices, map[string]string{"provider": "BlueHost", "value": record})

Check warning on line 129 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L115-L129

Added lines #L115 - L129 were not covered by tests
}
}

for _, mx := range mxRecords {
if strings.Contains(mx.Mx, "yahoodns.net") {
mailServices = append(mailServices, map[string]string{"provider": "Yahoo", "value": mx.Mx})
} else if strings.Contains(mx.Mx, "mimecast.com") {
mailServices = append(mailServices, map[string]string{"provider": "Mimecast", "value": mx.Mx})

Check warning on line 137 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L133-L137

Added lines #L133 - L137 were not covered by tests
}
}

return mailServices

Check warning on line 141 in handlers/mail-config.go

View check run for this annotation

Codecov / codecov/patch

handlers/mail-config.go#L141

Added line #L141 was not covered by tests
}
Loading