diff --git a/.golangci.yml b/.golangci.yml index ab8f7109..39864137 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,11 +8,12 @@ linters: - errcheck # Mandatory. Do not disable. - ineffassign # Mandatory. Do not disable. - staticcheck # Mandatory. Do not disable. - - govet - - gosimple - gosec - bodyclose # https://github.com/timakin/bodyclose + - govet + - gosimple - goimports + - revive - gocyclo - noctx - gomodguard @@ -67,6 +68,420 @@ linters-settings: # https://staticcheck.io/docs/options#checks checks: ["all"] + revive: + rules: + # TODO(v5): enable: + # # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#argument-limit + # - name: argument-limit + # severity: warning + # disabled: false + # exclude: [""] + # arguments: [ 4 ] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#atomic + - name: atomic + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bare-return + - name: bare-return + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#blank-imports + - name: blank-imports + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#bool-literal-in-expr + - name: bool-literal-in-expr + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#call-to-gc + - name: call-to-gc + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#comment-spacings + - name: comment-spacings + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#confusing-results + - name: confusing-results + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#constant-logical-expr + - name: constant-logical-expr + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-as-argument + - name: context-as-argument + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#context-keys-type + - name: context-keys-type + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#datarace + - name: datarace + severity: warning + disabled: false + exclude: [""] + + # TODO(DE-1373): enable: + # # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#defer + # - name: defer + # severity: warning + # disabled: false + # exclude: [""] + # arguments: + # - [ "call-chain", "loop" ] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#dot-imports + - name: dot-imports + severity: warning + disabled: false + exclude: [""] + arguments: [ ] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#duplicated-imports + - name: duplicated-imports + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#early-return + - name: early-return + severity: warning + disabled: false + exclude: [""] + arguments: + - "preserveScope" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-block + - name: empty-block + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#empty-lines + - name: empty-lines + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-map-style + - name: enforce-map-style + severity: warning + disabled: false + exclude: [""] + arguments: + - "make" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-repeated-arg-type-style + - name: enforce-repeated-arg-type-style + severity: warning + disabled: false + exclude: [""] + arguments: + - "short" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#enforce-slice-style + - name: enforce-slice-style + severity: warning + disabled: false + exclude: [""] + arguments: + - "make" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-naming + - name: error-naming + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-return + - name: error-return + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#error-strings + - name: error-strings + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#errorf + - name: errorf + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#function-result-limit + - name: function-result-limit + severity: warning + disabled: false + exclude: [""] + arguments: [ 3 ] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#get-return + - name: get-return + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#identical-branches + - name: identical-branches + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#if-return + - name: if-return + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-alias-naming + - name: import-alias-naming + severity: warning + disabled: false + exclude: [""] + arguments: + - "^[a-z][a-z0-9]{0,}$" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#import-shadowing + - name: import-shadowing + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#imports-blocklist + - name: imports-blocklist + severity: warning + disabled: false + exclude: [""] + arguments: + - "crypto/md5" + - "crypto/sha1" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#increment-decrement + - name: increment-decrement + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#indent-error-flow + - name: indent-error-flow + severity: warning + disabled: false + exclude: [""] + arguments: + - "preserveScope" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#modifies-parameter + - name: modifies-parameter + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#modifies-value-receiver + - name: modifies-value-receiver + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#optimize-operands-order + - name: optimize-operands-order + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#package-comments + - name: package-comments + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range + - name: range + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-address + - name: range-val-address + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#range-val-in-closure + - name: range-val-in-closure + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#receiver-naming + - name: receiver-naming + severity: warning + disabled: false + exclude: [""] + arguments: + - maxLength: 2 + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redefines-builtin-id + - name: redefines-builtin-id + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#redundant-import-alias + - name: redundant-import-alias + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-format + - name: string-format + severity: warning + disabled: false + exclude: [""] + arguments: + - - 'fmt.Errorf[0]' + - '/(^|[^\.!?])$/' + - must not end in punctuation + - - panic + - '/^[^\n]*$/' + - must not contain line breaks + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#string-of-int + - name: string-of-int + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#struct-tag + - name: struct-tag + severity: warning + disabled: false + exclude: [""] + arguments: + - "json,inline" + - "bson,outline,gnu" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#superfluous-else + - name: superfluous-else + severity: warning + disabled: false + exclude: [""] + arguments: + - "preserveScope" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-equal + - name: time-equal + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#time-naming + - name: time-naming + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unchecked-type-assertion + - name: unchecked-type-assertion + severity: warning + disabled: false + exclude: [""] + arguments: + - acceptIgnoredAssertionResult: true + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unconditional-recursion + - name: unconditional-recursion + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unexported-return + - name: unexported-return + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unreachable-code + - name: unreachable-code + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-parameter + - name: unused-parameter + severity: warning + disabled: false + exclude: [""] + arguments: + - allowRegex: "^_" + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#unused-receiver + - name: unused-receiver + severity: warning + disabled: false + exclude: [""] + arguments: + - allowRegex: "^_" + + # TODO(Go1.18+): enable: + # # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#use-any + # - name: use-any + # severity: warning + # disabled: false + # exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#useless-break + - name: useless-break + severity: warning + disabled: false + exclude: [""] + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-declaration + - name: var-declaration + severity: warning + disabled: false + exclude: [""] + + # TODO(v5): enable: + # # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#var-naming + # - name: var-naming + # severity: warning + # disabled: false + # exclude: [""] + # arguments: + # - - upperCaseConst: true # Extra parameter (upperCaseConst|skipPackageNameChecks) + + # https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md#waitgroup-by-value + - name: waitgroup-by-value + severity: warning + disabled: false + exclude: [""] + issues: # Which files to exclude: they will be analyzed, but issues from them won't be reported. # There is no need to include all autogenerated files, diff --git a/attachments_test.go b/attachments_test.go index a4db67ce..d843371b 100644 --- a/attachments_test.go +++ b/attachments_test.go @@ -62,7 +62,12 @@ func findAcceptedMessage(mg mailgun.Mailgun, id string) (*events.Accepted, error for it.Next(context.Background(), &page) { for _, event := range page { if event.GetName() == events.EventAccepted && event.GetID() == id { - return event.(*events.Accepted), nil + e, ok := event.(*events.Accepted) + if !ok { + return nil, fmt.Errorf("unexpected event type: %T", event) + } + + return e, nil } } } diff --git a/events.go b/events.go index 4fe7e410..7ba9550c 100644 --- a/events.go +++ b/events.go @@ -90,7 +90,7 @@ func (ei *EventIterator) Err() error { // Next retrieves the next page of events from the api. Returns false when there // no more pages to retrieve or if there was an error. Use `.Err()` to retrieve // the error -func (ei *EventIterator) Next(ctx context.Context, events *[]Event) bool { +func (ei *EventIterator) Next(ctx context.Context, ee *[]Event) bool { if ei.err != nil { return false } @@ -98,7 +98,7 @@ func (ei *EventIterator) Next(ctx context.Context, events *[]Event) bool { if ei.err != nil { return false } - *events, ei.err = ParseEvents(ei.Items) + *ee, ei.err = ParseEvents(ei.Items) if ei.err != nil { return false } @@ -111,7 +111,7 @@ func (ei *EventIterator) Next(ctx context.Context, events *[]Event) bool { // First retrieves the first page of events from the api. Returns false if there // was an error. It also sets the iterator object to the first page. // Use `.Err()` to retrieve the error. -func (ei *EventIterator) First(ctx context.Context, events *[]Event) bool { +func (ei *EventIterator) First(ctx context.Context, ee *[]Event) bool { if ei.err != nil { return false } @@ -119,7 +119,7 @@ func (ei *EventIterator) First(ctx context.Context, events *[]Event) bool { if ei.err != nil { return false } - *events, ei.err = ParseEvents(ei.Items) + *ee, ei.err = ParseEvents(ei.Items) return true } @@ -127,7 +127,7 @@ func (ei *EventIterator) First(ctx context.Context, events *[]Event) bool { // Calling Last() is invalid unless you first call First() or Next() // Returns false if there was an error. It also sets the iterator object // to the last page. Use `.Err()` to retrieve the error. -func (ei *EventIterator) Last(ctx context.Context, events *[]Event) bool { +func (ei *EventIterator) Last(ctx context.Context, ee *[]Event) bool { if ei.err != nil { return false } @@ -135,14 +135,14 @@ func (ei *EventIterator) Last(ctx context.Context, events *[]Event) bool { if ei.err != nil { return false } - *events, ei.err = ParseEvents(ei.Items) + *ee, ei.err = ParseEvents(ei.Items) return true } // Previous retrieves the previous page of events from the api. Returns false when there // no more pages to retrieve or if there was an error. Use `.Err()` to retrieve // the error if any -func (ei *EventIterator) Previous(ctx context.Context, events *[]Event) bool { +func (ei *EventIterator) Previous(ctx context.Context, ee *[]Event) bool { if ei.err != nil { return false } @@ -153,7 +153,7 @@ func (ei *EventIterator) Previous(ctx context.Context, events *[]Event) bool { if ei.err != nil { return false } - *events, ei.err = ParseEvents(ei.Items) + *ee, ei.err = ParseEvents(ei.Items) return len(ei.Items) != 0 } @@ -234,7 +234,7 @@ func (ep *EventPoller) Err() error { return ep.err } -func (ep *EventPoller) Poll(ctx context.Context, events *[]Event) bool { +func (ep *EventPoller) Poll(ctx context.Context, ee *[]Event) bool { var currentPage string var results []Event @@ -266,7 +266,7 @@ func (ep *EventPoller) Poll(ctx context.Context, events *[]Event) bool { // If we have events to return if len(results) != 0 { - *events = results + *ee = results return true } @@ -284,7 +284,6 @@ func (ep *EventPoller) Poll(ctx context.Context, events *[]Event) bool { case <-timer.C: } } - } // Given time.Time{} return a float64 as given in mailgun event timestamps diff --git a/examples_test.go b/examples_test.go index ba440c9c..216b8c09 100644 --- a/examples_test.go +++ b/examples_test.go @@ -146,7 +146,6 @@ func ExampleMailgunImpl_VerifyWebhookSignature() { } http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - var payload mailgun.WebhookPayload if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { fmt.Printf("decode JSON error: %s", err) diff --git a/exports.go b/exports.go index 75cc8e37..0cb3f65b 100644 --- a/exports.go +++ b/exports.go @@ -67,7 +67,7 @@ func (mg *MailgunImpl) GetExportLink(ctx context.Context, id string) (string, er c := mg.Client() // Ensure the client doesn't attempt to retry - c.CheckRedirect = func(req *http.Request, via []*http.Request) error { + c.CheckRedirect = func(_ *http.Request, _ []*http.Request) error { return errors.New("redirect") } @@ -84,10 +84,10 @@ func (mg *MailgunImpl) GetExportLink(ctx context.Context, id string) (string, er if Debug { if CaptureCurlOutput { r.mu.Lock() - r.capturedCurlOutput = r.curlString(req, nil) + r.capturedCurlOutput = curlString(req, nil) r.mu.Unlock() } else { - fmt.Println(r.curlString(req, nil)) + fmt.Println(curlString(req, nil)) } } diff --git a/httphelpers.go b/httphelpers.go index 0628250e..dc02040d 100644 --- a/httphelpers.go +++ b/httphelpers.go @@ -76,8 +76,8 @@ type jsonEncodedPayload struct { payload interface{} } -func newHTTPRequest(url string) *httpRequest { - return &httpRequest{URL: url, Client: http.DefaultClient} +func newHTTPRequest(uri string) *httpRequest { + return &httpRequest{URL: uri, Client: http.DefaultClient} } func (r *httpRequest) addParameter(name, value string) { @@ -109,11 +109,11 @@ func (j *jsonEncodedPayload) getPayloadBuffer() (*bytes.Buffer, error) { return bytes.NewBuffer(b), nil } -func (j *jsonEncodedPayload) getContentType() (string, error) { +func (*jsonEncodedPayload) getContentType() (string, error) { return "application/json", nil } -func (j *jsonEncodedPayload) getValues() []keyValuePair { +func (*jsonEncodedPayload) getValues() []keyValuePair { return nil } @@ -134,7 +134,7 @@ func (f *urlEncodedPayload) getPayloadBuffer() (*bytes.Buffer, error) { return bytes.NewBufferString(data.Encode()), nil } -func (f *urlEncodedPayload) getContentType() (string, error) { +func (*urlEncodedPayload) getContentType() (string, error) { return "application/x-www-form-urlencoded", nil } @@ -176,12 +176,13 @@ func (f *FormDataPayload) getPayloadBuffer() (*bytes.Buffer, error) { defer writer.Close() for _, keyVal := range f.Values { - if tmp, err := writer.CreateFormField(keyVal.key); err == nil { - _, err := tmp.Write([]byte(keyVal.value)) - if err != nil { - return nil, err - } - } else { + tmp, err := writer.CreateFormField(keyVal.key) + if err != nil { + return nil, err + } + + _, err = tmp.Write([]byte(keyVal.value)) + if err != nil { return nil, err } } @@ -197,7 +198,7 @@ func (f *FormDataPayload) getPayloadBuffer() (*bytes.Buffer, error) { return nil, err } - // TODO(DE-1139): defer in a loop: + // TODO(DE-1373): defer in a loop: defer fp.Close() _, err = io.Copy(tmp, fp) @@ -207,28 +208,29 @@ func (f *FormDataPayload) getPayloadBuffer() (*bytes.Buffer, error) { } for _, file := range f.ReadClosers { - if tmp, err := writer.CreateFormFile(file.key, file.name); err == nil { - // TODO(DE-1139): defer in a loop: - defer file.value.Close() + tmp, err := writer.CreateFormFile(file.key, file.name) + if err != nil { + return nil, err + } - _, err := io.Copy(tmp, file.value) - if err != nil { - return nil, err - } - } else { + // TODO(DE-1373): defer in a loop: + defer file.value.Close() + + _, err = io.Copy(tmp, file.value) + if err != nil { return nil, err } } for _, buff := range f.Buffers { - if tmp, err := writer.CreateFormFile(buff.key, buff.name); err == nil { - r := bytes.NewReader(buff.value) + tmp, err := writer.CreateFormFile(buff.key, buff.name) + if err != nil { + return nil, err + } - _, err := io.Copy(tmp, r) - if err != nil { - return nil, err - } - } else { + r := bytes.NewReader(buff.value) + _, err = io.Copy(tmp, r) + if err != nil { return nil, err } } @@ -327,10 +329,10 @@ func (r *httpRequest) makeRequest(ctx context.Context, method string, payload pa if Debug { if CaptureCurlOutput { r.mu.Lock() - r.capturedCurlOutput = r.curlString(req, payload) + r.capturedCurlOutput = curlString(req, payload) r.mu.Unlock() } else { - fmt.Println(r.curlString(req, payload)) + fmt.Println(curlString(req, payload)) } } @@ -383,8 +385,7 @@ func (r *httpRequest) generateUrlWithParameters() (string, error) { return uri.String(), nil } -func (r *httpRequest) curlString(req *http.Request, p payload) string { - +func curlString(req *http.Request, p payload) string { parts := []string{"curl", "-i", "-X", req.Method, req.URL.String()} for key, value := range req.Header { if key == "Authorization" { @@ -399,8 +400,6 @@ func (r *httpRequest) curlString(req *http.Request, p payload) string { parts = append(parts, fmt.Sprintf("-H \"Host: %s\"", req.Host)) } - // parts = append(parts, fmt.Sprintf(" --user '%s:%s'", r.BasicAuthUser, r.BasicAuthPassword)) - if p != nil { contentType, _ := p.getContentType() if contentType == "application/json" { diff --git a/mailgun.go b/mailgun.go index ff9e4bd6..cbff246d 100644 --- a/mailgun.go +++ b/mailgun.go @@ -386,7 +386,7 @@ func (mg *MailgunImpl) SetAPIBase(address string) { // AddOverrideHeader allows the user to specify additional headers that will be included in the HTTP request // This is mostly useful for testing the Mailgun API hosted at a different endpoint. -func (mg *MailgunImpl) AddOverrideHeader(k string, v string) { +func (mg *MailgunImpl) AddOverrideHeader(k, v string) { if mg.overrideHeaders == nil { mg.overrideHeaders = make(map[string]string) } diff --git a/mailgun_test.go b/mailgun_test.go index f4e11c74..2fc30bed 100644 --- a/mailgun_test.go +++ b/mailgun_test.go @@ -38,7 +38,7 @@ func TestInvalidBaseAPI(t *testing.T) { } func TestValidBaseAPI(t *testing.T) { - testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { var resp mailgun.DomainResponse b, err := json.Marshal(resp) require.NoError(t, err) diff --git a/members.go b/members.go index f3781a17..2bf83e9b 100644 --- a/members.go +++ b/members.go @@ -21,9 +21,9 @@ var ( // This attribute may be used to filter the results returned by GetSubscribers(). // All, Subscribed, and Unsubscribed provides a convenient and readable syntax for specifying the scope of the search. var ( - All *bool = nil - Subscribed *bool = &yes - Unsubscribed *bool = &no + All *bool + Subscribed = &yes + Unsubscribed = &no ) // A Member structure represents a member of the mailing list. diff --git a/messages.go b/messages.go index 4c7a5588..d419883d 100644 --- a/messages.go +++ b/messages.go @@ -397,7 +397,7 @@ func (m *plainMessage) RecipientCount() int { return len(m.bcc) + len(m.cc) } -func (m *mimeMessage) RecipientCount() int { +func (*mimeMessage) RecipientCount() int { // TODO(v5): 10 + len(m.to) return 10 } @@ -411,13 +411,13 @@ func (m *plainMessage) AddCC(r string) { m.cc = append(m.cc, r) } -func (m *mimeMessage) AddCC(_ string) {} +func (*mimeMessage) AddCC(_ string) {} func (m *plainMessage) AddBCC(r string) { m.bcc = append(m.bcc, r) } -func (m *mimeMessage) AddBCC(_ string) {} +func (*mimeMessage) AddBCC(_ string) {} // Deprecated: use SetHTML instead. // @@ -430,7 +430,7 @@ func (m *plainMessage) SetHTML(h string) { m.html = h } -func (m *mimeMessage) SetHTML(_ string) {} +func (*mimeMessage) SetHTML(_ string) {} // Deprecated: use SetAmpHTML instead. // TODO(v5): remove this method @@ -442,7 +442,7 @@ func (m *plainMessage) SetAmpHTML(h string) { m.ampHtml = h } -func (m *mimeMessage) SetAmpHTML(_ string) {} +func (*mimeMessage) SetAmpHTML(_ string) {} // AddTag attaches tags to the message. Tags are useful for metrics gathering and event tracking purposes. // Refer to the Mailgun documentation for further details. @@ -459,7 +459,7 @@ func (m *plainMessage) SetTemplate(t string) { m.template = t } -func (m *mimeMessage) SetTemplate(_ string) {} +func (*mimeMessage) SetTemplate(_ string) {} // Deprecated: is no longer supported and is deprecated for new software. // TODO(v5): remove this method. @@ -678,7 +678,7 @@ type SendableMessage interface { // // See the public mailgun documentation for all possible return codes and error messages // TODO(v5): switch m to SendableMessage interface - https://bryanftan.medium.com/accept-interfaces-return-structs-in-go-d4cab29a301b -func (mg *MailgunImpl) Send(ctx context.Context, m *Message) (mes string, id string, err error) { +func (mg *MailgunImpl) Send(ctx context.Context, m *Message) (mes, id string, err error) { if mg.domain == "" { err = errors.New("you must provide a valid domain before calling Send()") return "", "", err @@ -692,17 +692,17 @@ func (mg *MailgunImpl) Send(ctx context.Context, m *Message) (mes string, id str if mg.apiKey == "" { err = errors.New("you must provide a valid api-key before calling Send()") - return + return "", "", err } if !isValid(m) { err = ErrInvalidMessage - return + return "", "", err } if m.STOPeriod() != "" && m.RecipientCount() > 1 { err = errors.New("STO can only be used on a per-message basis") - return + return "", "", err } payload := NewFormDataPayload() @@ -741,7 +741,7 @@ func (mg *MailgunImpl) Send(ctx context.Context, m *Message) (mes string, id str mg.capturedCurlOutput = r.capturedCurlOutput } - return + return mes, id, err } func addMessageValues(dst *FormDataPayload, src SendableMessage) error { @@ -893,11 +893,11 @@ func (m *mimeMessage) AddValues(p *FormDataPayload) { p.addReadCloser("message", "message.mime", m.body) } -func (m *plainMessage) Endpoint() string { +func (*plainMessage) Endpoint() string { return messagesEndpoint } -func (m *mimeMessage) Endpoint() string { +func (*mimeMessage) Endpoint() string { return mimeMessagesEndpoint } @@ -977,15 +977,14 @@ func validateStringList(list []string, requireOne bool) bool { if list == nil { return !requireOne - } else { - for _, a := range list { - if a == "" { - return false - } else { - // TODO(vtopc): hasOne is always true: - hasOne = hasOne || true - } + } + + for _, a := range list { + if a == "" { + return false } + + hasOne = true } return hasOne diff --git a/messages_test.go b/messages_test.go index e56f6637..953567dd 100644 --- a/messages_test.go +++ b/messages_test.go @@ -459,7 +459,7 @@ func TestSendDomainError(t *testing.T) { {"smtp://example.com", false}, } - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { rsp := `{ "message":"Queued. Thank you", "id":"<20111114174239.25659.5817@samples.mailgun.org>" @@ -490,7 +490,7 @@ func TestSendEOFError(t *testing.T) { toUser = "test@test.com" ) - srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) { + srv := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) { panic("") })) defer srv.Close() diff --git a/messages_v5.go b/messages_v5.go index 6788275d..62c8d1fd 100644 --- a/messages_v5.go +++ b/messages_v5.go @@ -311,25 +311,25 @@ func (m *plainMessageV5) AddCC(r string) { m.cc = append(m.cc, r) } -func (m *mimeMessageV5) AddCC(_ string) {} +func (*mimeMessageV5) AddCC(_ string) {} func (m *plainMessageV5) AddBCC(r string) { m.bcc = append(m.bcc, r) } -func (m *mimeMessageV5) AddBCC(_ string) {} +func (*mimeMessageV5) AddBCC(_ string) {} func (m *plainMessageV5) SetHTML(h string) { m.html = h } -func (m *mimeMessageV5) SetHTML(_ string) {} +func (*mimeMessageV5) SetHTML(_ string) {} func (m *plainMessageV5) SetAmpHTML(h string) { m.ampHtml = h } -func (m *mimeMessageV5) SetAmpHTML(_ string) {} +func (*mimeMessageV5) SetAmpHTML(_ string) {} // AddTag attaches tags to the message. Tags are useful for metrics gathering and event tracking purposes. // Refer to the Mailgun documentation for further details. @@ -346,7 +346,7 @@ func (m *plainMessageV5) SetTemplate(t string) { m.template = t } -func (m *mimeMessageV5) SetTemplate(_ string) {} +func (*mimeMessageV5) SetTemplate(_ string) {} func (m *plainMessageV5) AddValues(p *FormDataPayload) { p.addValue("from", m.from) @@ -373,11 +373,11 @@ func (m *mimeMessageV5) AddValues(p *FormDataPayload) { p.addReadCloser("message", "message.mime", m.body) } -func (m *plainMessageV5) Endpoint() string { +func (*plainMessageV5) Endpoint() string { return messagesEndpoint } -func (m *mimeMessageV5) Endpoint() string { +func (*mimeMessageV5) Endpoint() string { return mimeMessagesEndpoint } @@ -402,7 +402,7 @@ func (m *mimeMessageV5) Endpoint() string { // } // // See the public mailgun documentation for all possible return codes and error messages -func (mg *MailgunImpl) sendV5(ctx context.Context, m SendableMessage) (mes string, id string, err error) { +func (mg *MailgunImpl) sendV5(ctx context.Context, m SendableMessage) (mes, id string, err error) { // TODO(vtopc): move domain checks into NewMessage and NewMIMEMessage? if m.Domain() == "" { err = errors.New("you must provide a valid domain before calling Send()") @@ -417,17 +417,17 @@ func (mg *MailgunImpl) sendV5(ctx context.Context, m SendableMessage) (mes strin if mg.apiKey == "" { err = errors.New("you must provide a valid api-key before calling Send()") - return + return "", "", err } if !isValid(m) { err = ErrInvalidMessage - return + return "", "", err } if m.STOPeriod() != "" && m.RecipientCount() > 1 { err = errors.New("STO can only be used on a per-message basis") - return + return "", "", err } payload := NewFormDataPayload() @@ -454,7 +454,7 @@ func (mg *MailgunImpl) sendV5(ctx context.Context, m SendableMessage) (mes strin id = response.Id } - return + return mes, id, err } func (m *plainMessageV5) isValid() bool { diff --git a/parse.go b/parse.go index abd3f00f..4fdb73fb 100644 --- a/parse.go +++ b/parse.go @@ -39,6 +39,7 @@ var EventNames = map[string]func() Event{ func new_(e interface{}) func() Event { typ := reflect.TypeOf(e) return func() Event { + //nolint:revive // unchecked-type-assertion: this func is called on init only, so there should be no runtime panics: return reflect.New(typ).Interface().(Event) } } diff --git a/parse_test.go b/parse_test.go index 03aa954c..82d2403d 100644 --- a/parse_test.go +++ b/parse_test.go @@ -29,6 +29,7 @@ func TestParseErrors(t *testing.T) { require.Contains(t, err.Error(), "failed to parse event 'accepted'") } +//nolint:revive // This is a test function. func TestParseSuccess(t *testing.T) { event, err := ParseEvent([]byte(`{ "event": "accepted", diff --git a/routes.go b/routes.go index 97226c9f..bfce338f 100644 --- a/routes.go +++ b/routes.go @@ -303,8 +303,8 @@ func (mg *MailgunImpl) GetRoute(ctx context.Context, id string) (Route, error) { if err != nil { return Route{}, err } - return *envelope.Route, err + return *envelope.Route, err } // UpdateRoute provides an "in-place" update of the specified route. diff --git a/spam_complaints_test.go b/spam_complaints_test.go index 8a51c005..9e271c9f 100644 --- a/spam_complaints_test.go +++ b/spam_complaints_test.go @@ -103,5 +103,4 @@ func TestCreateDeleteComplaintList(t *testing.T) { require.NoError(t, mg.DeleteComplaint(ctx, address)) require.False(t, hasComplaint(address)) } - } diff --git a/storage_test.go b/storage_test.go index 159982d7..e22434e1 100644 --- a/storage_test.go +++ b/storage_test.go @@ -53,5 +53,6 @@ func findStoredMessageURL(mg mailgun.Mailgun, id string) (string, error) { if it.Err() != nil { return "", it.Err() } - return "", fmt.Errorf("No stored messages found. Try changing MG_EMAIL_TO to an address that stores messages and try again.") + + return "", fmt.Errorf("no stored messages found; try changing MG_EMAIL_TO to an address that stores messages and try again") } diff --git a/stored_messages.go b/stored_messages.go index ac224b15..ac144b8f 100644 --- a/stored_messages.go +++ b/stored_messages.go @@ -62,7 +62,7 @@ func (mg *MailgunImpl) GetStoredMessage(ctx context.Context, url string) (Stored } // Given a storage id resend the stored message to the specified recipients -func (mg *MailgunImpl) ReSend(ctx context.Context, url string, recipients ...string) (string, string, error) { +func (mg *MailgunImpl) ReSend(ctx context.Context, url string, recipients ...string) (msg, id string, err error) { r := newHTTPRequest(url) r.setClient(mg.Client()) r.setBasicAuth(basicAuthUser, mg.APIKey()) @@ -78,12 +78,12 @@ func (mg *MailgunImpl) ReSend(ctx context.Context, url string, recipients ...str } var resp sendMessageResponse - err := postResponseFromJSON(ctx, r, payload, &resp) + err = postResponseFromJSON(ctx, r, payload, &resp) if err != nil { return "", "", err } - return resp.Message, resp.Id, nil + return resp.Message, resp.Id, nil } // GetStoredMessageRaw retrieves the raw MIME body of a received e-mail message. diff --git a/subaccounts_test.go b/subaccounts_test.go index a56301dd..8d92d63e 100644 --- a/subaccounts_test.go +++ b/subaccounts_test.go @@ -45,7 +45,7 @@ func TestSubaccountDetails(t *testing.T) { iterator := mg.ListSubaccounts(nil) require.NotNil(t, iterator) - page := []mailgun.Subaccount{} + page := make([]mailgun.Subaccount, 0, 1) require.True(t, iterator.Next(context.Background(), &page)) require.NoError(t, iterator.Err()) diff --git a/tags.go b/tags.go index e8f477df..85214004 100644 --- a/tags.go +++ b/tags.go @@ -67,9 +67,9 @@ func (mg *MailgunImpl) ListTags(opts *ListTagOptions) *TagIterator { } } - url, err := req.generateUrlWithParameters() + uri, err := req.generateUrlWithParameters() return &TagIterator{ - tagsResponse: tagsResponse{Paging: Paging{Next: url, First: url}}, + tagsResponse: tagsResponse{Paging: Paging{Next: uri, First: uri}}, err: err, mg: mg, } @@ -154,9 +154,9 @@ func (ti *TagIterator) Err() error { return ti.err } -func (ti *TagIterator) fetch(ctx context.Context, url string) error { +func (ti *TagIterator) fetch(ctx context.Context, uri string) error { ti.Items = nil - req := newHTTPRequest(url) + req := newHTTPRequest(uri) req.setClient(ti.mg.Client()) req.setBasicAuth(basicAuthUser, ti.mg.APIKey()) return getResponseFromJSON(ctx, req, &ti.tagsResponse) diff --git a/tags_test.go b/tags_test.go index 507e4e57..1e642529 100644 --- a/tags_test.go +++ b/tags_test.go @@ -72,14 +72,16 @@ func waitForTag(mg mailgun.Mailgun, tag string) error { if err != nil { if mailgun.GetStatusFromErr(err) == 404 { time.Sleep(time.Second * 2) - attempts += 1 + attempts++ continue } + return err } - return nil + return nil } + return errors.Errorf("Waited to long for tag '%s' to show up", tag) } diff --git a/template_test.go b/template_test.go index 5e81c47a..74bd74b0 100644 --- a/template_test.go +++ b/template_test.go @@ -76,13 +76,15 @@ func waitForTemplate(mg mailgun.Mailgun, id string) error { if err != nil { if mailgun.GetStatusFromErr(err) == 404 { time.Sleep(time.Second * 2) - attempts += 1 + attempts++ continue } + return err } - return nil + return nil } + return errors.Errorf("Waited to long for template '%s' to show up", id) } diff --git a/unsubscribes_test.go b/unsubscribes_test.go index 250030cc..9643abbd 100644 --- a/unsubscribes_test.go +++ b/unsubscribes_test.go @@ -89,7 +89,6 @@ func TestCreateDestroyUnsubscription(t *testing.T) { _, err := mg.GetUnsubscribe(ctx, email) require.NoError(t, err) - /*t.Logf("Received %d out of %d unsubscribe records.\n", len(us), n)*/ // Destroy the unsubscription record require.NoError(t, mg.DeleteUnsubscribe(ctx, email))