Compare commits

..

No commits in common. "c9523e85ae3cc24002fa5a42a6575ba1a3813d06" and "637f5e03dd5f2bdc1cbb14142686fcc72b4d4cf1" have entirely different histories.

10 changed files with 22 additions and 25 deletions

View file

@ -6,9 +6,9 @@ freebsd_task:
name: FreeBSD name: FreeBSD
matrix: matrix:
- name: FreeBSD 13.3 - name: FreeBSD 13.2
freebsd_instance: freebsd_instance:
image_family: freebsd-13-3 image_family: freebsd-13-2
- name: FreeBSD 14.0 - name: FreeBSD 14.0
freebsd_instance: freebsd_instance:
image_family: freebsd-14-0 image_family: freebsd-14-0

View file

@ -36,7 +36,7 @@ jobs:
strategy: strategy:
matrix: matrix:
os: [ubuntu-latest, macos-latest, windows-latest] os: [ubuntu-latest, macos-latest, windows-latest]
go: ['1.20', '1.21', '1.22', '1.23'] go: [1.18, 1.19, '1.20', '1.21', '1.22']
steps: steps:
- name: Harden Runner - name: Harden Runner
uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
@ -50,14 +50,14 @@ jobs:
with: with:
go-version: ${{ matrix.go }} go-version: ${{ matrix.go }}
- name: Install sendmail - name: Install sendmail
if: matrix.go == '1.23' && matrix.os == 'ubuntu-latest' if: matrix.go == '1.22' && matrix.os == 'ubuntu-latest'
run: | run: |
sudo apt-get -y install sendmail; which sendmail sudo apt-get -y install sendmail; which sendmail
- name: Run Tests - name: Run Tests
run: | run: |
go test -v -race --coverprofile=coverage.coverprofile --covermode=atomic ./... go test -v -race --coverprofile=coverage.coverprofile --covermode=atomic ./...
- name: Upload coverage to Codecov - name: Upload coverage to Codecov
if: success() && matrix.go == '1.23' && matrix.os == 'ubuntu-latest' if: success() && matrix.go == '1.22' && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
with: with:
token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos token: ${{ secrets.CODECOV_TOKEN }} # not required for public repos

View file

@ -26,7 +26,7 @@ jobs:
- uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 - uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with: with:
go-version: '1.23' go-version: '1.22'
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0 uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0

View file

@ -38,7 +38,7 @@ jobs:
- name: Setup Go - name: Setup Go
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2 uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with: with:
go-version: '1.23.x' go-version: '1.22.x'
- name: Run unit Tests - name: Run unit Tests
run: | run: |

View file

@ -3,9 +3,8 @@
## SPDX-License-Identifier: MIT ## SPDX-License-Identifier: MIT
[run] [run]
go = "1.23" go = "1.22"
tests = true tests = true
exclude-dirs = ["examples"]
[linters] [linters]
enable = ["stylecheck", "whitespace", "containedctx", "contextcheck", "decorder", enable = ["stylecheck", "whitespace", "containedctx", "contextcheck", "decorder",

View file

@ -5,7 +5,7 @@
package mail package mail
import ( import (
"errors" "fmt"
"io" "io"
) )
@ -26,7 +26,7 @@ var newlineBytes = []byte(SingleNewLine)
// line length is reached // line length is reached
func (l *Base64LineBreaker) Write(data []byte) (numBytes int, err error) { func (l *Base64LineBreaker) Write(data []byte) (numBytes int, err error) {
if l.out == nil { if l.out == nil {
err = errors.New(ErrNoOutWriter) err = fmt.Errorf(ErrNoOutWriter)
return return
} }
if l.used+len(data) < MaxBodyLength { if l.used+len(data) < MaxBodyLength {

2
doc.go
View file

@ -6,4 +6,4 @@
package mail package mail
// VERSION is used in the default user agent string // VERSION is used in the default user agent string
const VERSION = "0.4.3" const VERSION = "0.4.2"

12
msg.go
View file

@ -743,7 +743,7 @@ func (m *Msg) SetBodyWriter(
// The content type will be set to text/html automatically // The content type will be set to text/html automatically
func (m *Msg) SetBodyHTMLTemplate(tpl *ht.Template, data interface{}, opts ...PartOption) error { func (m *Msg) SetBodyHTMLTemplate(tpl *ht.Template, data interface{}, opts ...PartOption) error {
if tpl == nil { if tpl == nil {
return errors.New(errTplPointerNil) return fmt.Errorf(errTplPointerNil)
} }
buffer := bytes.Buffer{} buffer := bytes.Buffer{}
if err := tpl.Execute(&buffer, data); err != nil { if err := tpl.Execute(&buffer, data); err != nil {
@ -758,7 +758,7 @@ func (m *Msg) SetBodyHTMLTemplate(tpl *ht.Template, data interface{}, opts ...Pa
// The content type will be set to text/plain automatically // The content type will be set to text/plain automatically
func (m *Msg) SetBodyTextTemplate(tpl *tt.Template, data interface{}, opts ...PartOption) error { func (m *Msg) SetBodyTextTemplate(tpl *tt.Template, data interface{}, opts ...PartOption) error {
if tpl == nil { if tpl == nil {
return errors.New(errTplPointerNil) return fmt.Errorf(errTplPointerNil)
} }
buf := bytes.Buffer{} buf := bytes.Buffer{}
if err := tpl.Execute(&buf, data); err != nil { if err := tpl.Execute(&buf, data); err != nil {
@ -790,7 +790,7 @@ func (m *Msg) AddAlternativeWriter(
// The content type will be set to text/html automatically // The content type will be set to text/html automatically
func (m *Msg) AddAlternativeHTMLTemplate(tpl *ht.Template, data interface{}, opts ...PartOption) error { func (m *Msg) AddAlternativeHTMLTemplate(tpl *ht.Template, data interface{}, opts ...PartOption) error {
if tpl == nil { if tpl == nil {
return errors.New(errTplPointerNil) return fmt.Errorf(errTplPointerNil)
} }
buffer := bytes.Buffer{} buffer := bytes.Buffer{}
if err := tpl.Execute(&buffer, data); err != nil { if err := tpl.Execute(&buffer, data); err != nil {
@ -805,7 +805,7 @@ func (m *Msg) AddAlternativeHTMLTemplate(tpl *ht.Template, data interface{}, opt
// The content type will be set to text/plain automatically // The content type will be set to text/plain automatically
func (m *Msg) AddAlternativeTextTemplate(tpl *tt.Template, data interface{}, opts ...PartOption) error { func (m *Msg) AddAlternativeTextTemplate(tpl *tt.Template, data interface{}, opts ...PartOption) error {
if tpl == nil { if tpl == nil {
return errors.New(errTplPointerNil) return fmt.Errorf(errTplPointerNil)
} }
buffer := bytes.Buffer{} buffer := bytes.Buffer{}
if err := tpl.Execute(&buffer, data); err != nil { if err := tpl.Execute(&buffer, data); err != nil {
@ -1314,7 +1314,7 @@ func fileFromReadSeeker(name string, reader io.ReadSeeker) *File {
// fileFromHTMLTemplate returns a File pointer form a given html/template.Template // fileFromHTMLTemplate returns a File pointer form a given html/template.Template
func fileFromHTMLTemplate(name string, tpl *ht.Template, data interface{}) (*File, error) { func fileFromHTMLTemplate(name string, tpl *ht.Template, data interface{}) (*File, error) {
if tpl == nil { if tpl == nil {
return nil, errors.New(errTplPointerNil) return nil, fmt.Errorf(errTplPointerNil)
} }
buffer := bytes.Buffer{} buffer := bytes.Buffer{}
if err := tpl.Execute(&buffer, data); err != nil { if err := tpl.Execute(&buffer, data); err != nil {
@ -1326,7 +1326,7 @@ func fileFromHTMLTemplate(name string, tpl *ht.Template, data interface{}) (*Fil
// fileFromTextTemplate returns a File pointer form a given text/template.Template // fileFromTextTemplate returns a File pointer form a given text/template.Template
func fileFromTextTemplate(name string, tpl *tt.Template, data interface{}) (*File, error) { func fileFromTextTemplate(name string, tpl *tt.Template, data interface{}) (*File, error) {
if tpl == nil { if tpl == nil {
return nil, errors.New(errTplPointerNil) return nil, fmt.Errorf(errTplPointerNil)
} }
buffer := bytes.Buffer{} buffer := bytes.Buffer{}
if err := tpl.Execute(&buffer, data); err != nil { if err := tpl.Execute(&buffer, data); err != nil {

View file

@ -122,7 +122,7 @@ func TestMsgWriter_writeMsg(t *testing.T) {
em += fmt.Sprintf("* incorrect %q field", ea[e]) em += fmt.Sprintf("* incorrect %q field", ea[e])
} }
em += fmt.Sprintf("\n\nFull message:\n%s", ms) em += fmt.Sprintf("\n\nFull message:\n%s", ms)
t.Error(em) t.Errorf(em)
} }
} }

View file

@ -21,14 +21,12 @@ const (
// //
// See: https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-xlogin/. // See: https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-xlogin/.
LoginXUsernameChallenge = "Username:" LoginXUsernameChallenge = "Username:"
LoginXUsernameLowerChallenge = "username:"
// LoginXPasswordChallenge represents the Password Challenge response sent by the SMTP server per the AUTH LOGIN // LoginXPasswordChallenge represents the Password Challenge response sent by the SMTP server per the AUTH LOGIN
// extension. // extension.
// //
// See: https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-xlogin/. // See: https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-xlogin/.
LoginXPasswordChallenge = "Password:" LoginXPasswordChallenge = "Password:"
LoginXPasswordLowerChallenge = "password:"
// LoginXDraftUsernameChallenge represents the Username Challenge response sent by the SMTP server per the IETF // LoginXDraftUsernameChallenge represents the Username Challenge response sent by the SMTP server per the IETF
// draft AUTH LOGIN extension. It should be noted this extension is an expired draft which was never formally // draft AUTH LOGIN extension. It should be noted this extension is an expired draft which was never formally
@ -78,9 +76,9 @@ func (a *loginAuth) Start(server *ServerInfo) (string, []byte, error) {
func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) { func (a *loginAuth) Next(fromServer []byte, more bool) ([]byte, error) {
if more { if more {
switch string(fromServer) { switch string(fromServer) {
case LoginXUsernameChallenge, LoginXUsernameLowerChallenge, LoginXDraftUsernameChallenge: case LoginXUsernameChallenge, LoginXDraftUsernameChallenge:
return []byte(a.username), nil return []byte(a.username), nil
case LoginXPasswordChallenge, LoginXPasswordLowerChallenge, LoginXDraftPasswordChallenge: case LoginXPasswordChallenge, LoginXDraftPasswordChallenge:
return []byte(a.password), nil return []byte(a.password), nil
default: default:
return nil, fmt.Errorf("unexpected server response: %s", string(fromServer)) return nil, fmt.Errorf("unexpected server response: %s", string(fromServer))