Skip to content
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

SCRAM-SHA-1(-PLUS) / SCRAM-SHA-256(-PLUS) support #310

Merged
merged 25 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9069c9c
Add SCRAM-SHA support to SMTP authentication
wneessen Oct 1, 2024
e8fc6cd
Add SCRAM-SHA support to SMTP authentication
wneessen Oct 1, 2024
4f1a607
Add support for SCRAM-SHA authentication methods
wneessen Oct 1, 2024
ebd1710
Update dependencies in go.mod and go.sum
wneessen Oct 1, 2024
738f43e
Add GetTLSConnectionState method to SMTP client
wneessen Oct 1, 2024
b96badb
Add license file for go.sum
wneessen Oct 1, 2024
c797f0b
Add REUSE.toml
wneessen Oct 1, 2024
3013975
Rename and refactor SCRAM authentication methods
wneessen Oct 1, 2024
27838f5
Improve TLS state handling and add SCRAM-SHA-256 auth support
wneessen Oct 1, 2024
e8f3c44
Add SCRAM-SHA1-PLUS authentication tests
wneessen Oct 1, 2024
5b5991f
Merge branch 'main' into feature/242_support-scram-sha
wneessen Oct 1, 2024
e5b87db
Update README to clarify library features and dependencies
wneessen Oct 1, 2024
cace489
Update README.md wordings for clarity
wneessen Oct 1, 2024
687843e
Enhance contributors section and add sponsors acknowledgment
wneessen Oct 1, 2024
abab0af
Simplify sponsor appreciation message
wneessen Oct 1, 2024
bcf7084
Add detailed documentation comments for SCRAM methods
wneessen Oct 1, 2024
324be9d
Refactor SCRAM tests to include SHA-256-PLUS
wneessen Oct 1, 2024
7499bae
Add unit tests for SCRAM-SHA authentication methods
wneessen Oct 1, 2024
b69ad27
Add comments for SMTP authentication mechanisms
wneessen Oct 1, 2024
8838414
Fix incorrect error types for unsupported SMTP authentication
wneessen Oct 1, 2024
5058fd5
Add test for SCRAM-SHA authentication failure cases
wneessen Oct 1, 2024
15b9ddf
Refactor error handling for non-TLS SMTP connections
wneessen Oct 1, 2024
f823112
Refactor: consolidate ErrNonTLSConnection variable
wneessen Oct 1, 2024
986a988
Reset SMTP auth when setting SMTP auth type
wneessen Oct 1, 2024
72b3f53
Add tests for unsupported SCRAM-SHA authentications
wneessen Oct 1, 2024
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
10 changes: 0 additions & 10 deletions .reuse/dep5

This file was deleted.

52 changes: 28 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,34 @@ SPDX-License-Identifier: CC0-1.0

<p align="center"><img src="./assets/gopher2.svg" width="250" alt="go-mail logo"/></p>

The main idea of this library was to provide a simple interface to sending mails for
The main idea of this library was to provide a simple interface for sending mails to
my [JS-Mailer](https://github.com/wneessen/js-mailer) project. It quickly evolved into a full-fledged mail library.

go-mail follows idiomatic Go style and best practice. It's only dependency is the Go Standard Library. It combines a lot
of functionality from the standard library to give easy and convenient access to mail and SMTP related tasks.
go-mail follows idiomatic Go style and best practice. It has a small dependency footprint by mainly relying on the
Go Standard Library and the Go extended packages. It combines a lot of functionality from the standard library to
give easy and convenient access to mail and SMTP related tasks.

Parts of this library (especially some parts of [msgwriter.go](msgwriter.go)) have been forked/ported from the
[go-mail/mail](https://github.com/go-mail/mail) respectively [go-gomail/gomail](https://github.com/go-gomail/gomail)
which both seems to not be maintained anymore.
In the early days, parts of this library (especially some parts of [msgwriter.go](msgwriter.go)) had been
forked/ported from [go-mail/mail](https://github.com/go-mail/mail) and respectively [go-gomail/gomail](https://github.com/go-gomail/gomail). Today
most of the ported code has been refactored.

The smtp package of go-mail is forked from the original Go stdlib's `net/smtp` and then extended by the go-mail
team.
The `smtp` package of go-mail has been forked from the original Go stdlib's `net/smtp` package and has then been extended
by the go-mail team to fit the packages needs (more SMTP Auth methods, logging, concurrency-safety, etc.).

## Features

Some of the features of this library:
Here are some highlights of go-mail's featureset:

* [X] Only Standard Library dependant
* [X] Very small dependency footprint (mainly Go Stdlib and Go extended packages)
* [X] Modern, idiomatic Go
* [X] Sane and secure defaults
* [X] Explicit SSL/TLS support
* [X] Implicit StartTLS support with different policies
* [X] Makes use of contexts for a better control flow and timeout/cancelation handling
* [X] SMTP Auth support (LOGIN, PLAIN, CRAM-MD, XOAUTH2)
* [X] SMTP Auth support (LOGIN, PLAIN, CRAM-MD, XOAUTH2, SCRAM-SHA-1(-PLUS), SCRAM-SHA-256(-PLUS))
* [X] RFC5322 compliant mail address validation
* [X] Support for common mail header field generation (Message-ID, Date, Bulk-Precedence, Priority, etc.)
* [X] Reusing the same SMTP connection to send multiple mails
* [X] Concurrency-safe reusing the same SMTP connection to send multiple mails
* [X] Support for attachments and inline embeds (from file system, `io.Reader` or `embed.FS`)
* [X] Support for different encodings
* [X] Middleware support for 3rd-party libraries to alter mail messages
Expand Down Expand Up @@ -99,15 +100,18 @@ We provide example code in both our GoDocs as well as on our official Website (s
check out our [Getting started](https://go-mail.dev/getting-started/introduction/) guide.

## Authors/Contributors
go-mail was initially authored and developed by [Winni Neessen](https://github.com/wneessen/).

Big thanks to the following people, for contributing to the go-mail project (either in form of code or by
reviewing code, writing documenation or helping to translate the website):
* [Christian Vette](https://github.com/cvette)
* [Dhia Gharsallaoui](https://github.com/dhia-gharsallaoui)
* [inliquid](https://github.com/inliquid)
* [iwittkau](https://github.com/iwittkau)
* [James Elliott](https://github.com/james-d-elliott)
* [Maria Letta](https://github.com/MariaLetta) (designed the go-mail logo)
* [Nicola Murino](https://github.com/drakkan)
* [sters](https://github.com/sters)
go-mail was initially created and developed by [Winni Neessen](https://github.com/wneessen/), but over time a lot of amazing people
contributed ot the project. Big thanks to all of them for improving the go-mail project (be it writing code, testing
code, reviewing code, writing documenation or helping to translate the website):

<a href="https://github.com/wneessen/go-mail/graphs/contributors">
<img src="https://contrib.rocks/image?repo=wneessen/go-mail" />
</a>

A huge thank you also goes to [Maria Letta](https://github.com/MariaLetta) for designing our super cool go-mail logo!

## Sponsors
We sincerely thank our amazing sponsors for their generous support! Your contributions do not go unnoticed and helps
keeping up the project!

* [kolaente](https://github.com/kolaente)
9 changes: 9 additions & 0 deletions REUSE.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SPDX-FileCopyrightText: Copyright (c) 2022-2024 The go-mail Authors
#
# SPDX-License-Identifier: MIT

version = 1
SPDX-PackageName = "go-mail"
SPDX-PackageSupplier = "Winni Neessen <[email protected]>"
SPDX-PackageDownloadLocation = "https://github.com/wneessen/go-mail"
annotations = []
28 changes: 28 additions & 0 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ const (
// SMTPAuthXOAUTH2 is the "XOAUTH2" SASL authentication mechanism.
// https://developers.google.com/gmail/imap/xoauth2-protocol
SMTPAuthXOAUTH2 SMTPAuthType = "XOAUTH2"

// SMTPAuthSCRAMSHA1 represents the SCRAM-SHA-1 SMTP authentication mechanism
// https://datatracker.ietf.org/doc/html/rfc5802
SMTPAuthSCRAMSHA1 SMTPAuthType = "SCRAM-SHA-1"

// SMTPAuthSCRAMSHA1PLUS represents the "SCRAM-SHA-1-PLUS" authentication mechanism for SMTP.
// https://datatracker.ietf.org/doc/html/rfc5802
SMTPAuthSCRAMSHA1PLUS SMTPAuthType = "SCRAM-SHA-1-PLUS"

// SMTPAuthSCRAMSHA256 represents the SCRAM-SHA-256 authentication mechanism for SMTP.
// https://datatracker.ietf.org/doc/html/rfc7677
SMTPAuthSCRAMSHA256 SMTPAuthType = "SCRAM-SHA-256"

// SMTPAuthSCRAMSHA256PLUS represents the "SCRAM-SHA-256-PLUS" SMTP AUTH type.
// https://datatracker.ietf.org/doc/html/rfc7677
SMTPAuthSCRAMSHA256PLUS SMTPAuthType = "SCRAM-SHA-256-PLUS"
)

// SMTP Auth related static errors
Expand All @@ -43,4 +59,16 @@ var (

// ErrXOauth2AuthNotSupported should be used if the target server does not support the "XOAUTH2" schema
ErrXOauth2AuthNotSupported = errors.New("server does not support SMTP AUTH type: XOAUTH2")

// ErrSCRAMSHA1AuthNotSupported should be used if the target server does not support the "SCRAM-SHA-1" schema
ErrSCRAMSHA1AuthNotSupported = errors.New("server does not support SMTP AUTH type: SCRAM-SHA-1")

// ErrSCRAMSHA1PLUSAuthNotSupported should be used if the target server does not support the "SCRAM-SHA-1-PLUS" schema
ErrSCRAMSHA1PLUSAuthNotSupported = errors.New("server does not support SMTP AUTH type: SCRAM-SHA-1-PLUS")

// ErrSCRAMSHA256AuthNotSupported should be used if the target server does not support the "SCRAM-SHA-256" schema
ErrSCRAMSHA256AuthNotSupported = errors.New("server does not support SMTP AUTH type: SCRAM-SHA-256")

// ErrSCRAMSHA256PLUSAuthNotSupported should be used if the target server does not support the "SCRAM-SHA-256-PLUS" schema
ErrSCRAMSHA256PLUSAuthNotSupported = errors.New("server does not support SMTP AUTH type: SCRAM-SHA-256-PLUS")
)
41 changes: 40 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,7 @@
// SetSMTPAuth overrides the current SMTP AUTH type setting with the given value
func (c *Client) SetSMTPAuth(authtype SMTPAuthType) {
c.smtpAuthType = authtype
c.smtpAuth = nil
}

// SetSMTPAuthCustom overrides the current SMTP AUTH setting with the given custom smtp.Auth
Expand Down Expand Up @@ -748,7 +749,17 @@
return err
}
}
_, c.isEncrypted = c.smtpClient.TLSConnectionState()
tlsConnState, err := c.smtpClient.GetTLSConnectionState()
if err != nil {
switch {
case errors.Is(err, smtp.ErrNonTLSConnection):
c.isEncrypted = false
return nil
default:
return fmt.Errorf("failed to get TLS connection state: %w", err)

Check warning on line 759 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L758-L759

Added lines #L758 - L759 were not covered by tests
}
}
c.isEncrypted = tlsConnState.HandshakeComplete
}
return nil
}
Expand Down Expand Up @@ -785,6 +796,34 @@
return ErrXOauth2AuthNotSupported
}
c.smtpAuth = smtp.XOAuth2Auth(c.user, c.pass)
case SMTPAuthSCRAMSHA1:
if !strings.Contains(smtpAuthType, string(SMTPAuthSCRAMSHA1)) {
return ErrSCRAMSHA1AuthNotSupported
}
c.smtpAuth = smtp.ScramSHA1Auth(c.user, c.pass)

Check warning on line 803 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L803

Added line #L803 was not covered by tests
case SMTPAuthSCRAMSHA256:
if !strings.Contains(smtpAuthType, string(SMTPAuthSCRAMSHA256)) {
return ErrSCRAMSHA256AuthNotSupported
}
c.smtpAuth = smtp.ScramSHA256Auth(c.user, c.pass)

Check warning on line 808 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L808

Added line #L808 was not covered by tests
case SMTPAuthSCRAMSHA1PLUS:
if !strings.Contains(smtpAuthType, string(SMTPAuthSCRAMSHA1PLUS)) {
return ErrSCRAMSHA1PLUSAuthNotSupported
}
tlsConnState, err := c.smtpClient.GetTLSConnectionState()
if err != nil {
return err

Check warning on line 815 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L813-L815

Added lines #L813 - L815 were not covered by tests
}
c.smtpAuth = smtp.ScramSHA1PlusAuth(c.user, c.pass, tlsConnState)

Check warning on line 817 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L817

Added line #L817 was not covered by tests
case SMTPAuthSCRAMSHA256PLUS:
if !strings.Contains(smtpAuthType, string(SMTPAuthSCRAMSHA256PLUS)) {
return ErrSCRAMSHA256PLUSAuthNotSupported
}
tlsConnState, err := c.smtpClient.GetTLSConnectionState()
if err != nil {
return err

Check warning on line 824 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L822-L824

Added lines #L822 - L824 were not covered by tests
}
c.smtpAuth = smtp.ScramSHA256PlusAuth(c.user, c.pass, tlsConnState)

Check warning on line 826 in client.go

View check run for this annotation

Codecov / codecov/patch

client.go#L826

Added line #L826 was not covered by tests
default:
return fmt.Errorf("unsupported SMTP AUTH type %q", c.smtpAuthType)
}
Expand Down
Loading
Loading