Skip to content

Commit

Permalink
Merge branch 'release/v1.17.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
axllent committed Apr 24, 2024
2 parents 7fe47d2 + b5af86d commit a5cbba3
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 890 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

Notable changes to Mailpit will be documented in this file.

## [v1.17.1]

### Chore
- Update node dependencies
- Update Go dependencies
- Clearer error messages for read/write permission failures ([#281](https://github.com/axllent/mailpit/issues/281))

### Fix
- Prevent error when two identical tags are added at the exact same time ([#283](https://github.com/axllent/mailpit/issues/283))


## [v1.17.0]

### Chore
Expand Down
33 changes: 15 additions & 18 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ func VerifyConfig() error {
UIAuthFile = filepath.Clean(UIAuthFile)

if !isFile(UIAuthFile) {
return fmt.Errorf("[ui] HTTP password file not found: %s", UIAuthFile)
return fmt.Errorf("[ui] HTTP password file not found or readable: %s", UIAuthFile)
}

b, err := os.ReadFile(UIAuthFile)
Expand All @@ -243,11 +243,11 @@ func VerifyConfig() error {
UITLSKey = filepath.Clean(UITLSKey)

if !isFile(UITLSCert) {
return fmt.Errorf("[ui] TLS certificate not found: %s", UITLSCert)
return fmt.Errorf("[ui] TLS certificate not found or readable: %s", UITLSCert)
}

if !isFile(UITLSKey) {
return fmt.Errorf("[ui] TLS key not found: %s", UITLSKey)
return fmt.Errorf("[ui] TLS key not found or readable: %s", UITLSKey)
}
}

Expand All @@ -260,11 +260,11 @@ func VerifyConfig() error {
SMTPTLSKey = filepath.Clean(SMTPTLSKey)

if !isFile(SMTPTLSCert) {
return fmt.Errorf("[smtp] TLS certificate not found: %s", SMTPTLSCert)
return fmt.Errorf("[smtp] TLS certificate not found or readable: %s", SMTPTLSCert)
}

if !isFile(SMTPTLSKey) {
return fmt.Errorf("[smtp] TLS key not found: %s", SMTPTLSKey)
return fmt.Errorf("[smtp] TLS key not found or readable: %s", SMTPTLSKey)
}
} else if SMTPRequireTLS {
return errors.New("[smtp] TLS cannot be required without an SMTP TLS certificate and key")
Expand All @@ -282,7 +282,7 @@ func VerifyConfig() error {
SMTPAuthFile = filepath.Clean(SMTPAuthFile)

if !isFile(SMTPAuthFile) {
return fmt.Errorf("[smtp] password file not found: %s", SMTPAuthFile)
return fmt.Errorf("[smtp] password file not found or readable: %s", SMTPAuthFile)
}

b, err := os.ReadFile(SMTPAuthFile)
Expand Down Expand Up @@ -321,11 +321,11 @@ func VerifyConfig() error {
POP3TLSKey = filepath.Clean(POP3TLSKey)

if !isFile(POP3TLSCert) {
return fmt.Errorf("[pop3] TLS certificate not found: %s", POP3TLSCert)
return fmt.Errorf("[pop3] TLS certificate not found or readable: %s", POP3TLSCert)
}

if !isFile(POP3TLSKey) {
return fmt.Errorf("[pop3] TLS key not found: %s", POP3TLSKey)
return fmt.Errorf("[pop3] TLS key not found or readable: %s", POP3TLSKey)
}
}
if POP3TLSCert != "" && POP3TLSKey == "" || POP3TLSCert == "" && POP3TLSKey != "" {
Expand All @@ -341,7 +341,7 @@ func VerifyConfig() error {
POP3AuthFile = filepath.Clean(POP3AuthFile)

if !isFile(POP3AuthFile) {
return fmt.Errorf("[pop3] password file not found: %s", POP3AuthFile)
return fmt.Errorf("[pop3] password file not found or readable: %s", POP3AuthFile)
}

b, err := os.ReadFile(POP3AuthFile)
Expand Down Expand Up @@ -459,7 +459,7 @@ func parseRelayConfig(c string) error {
c = filepath.Clean(c)

if !isFile(c) {
return fmt.Errorf("[smtp] relay configuration not found: %s", c)
return fmt.Errorf("[smtp] relay configuration not found or readable: %s", c)
}

data, err := os.ReadFile(c)
Expand Down Expand Up @@ -536,20 +536,17 @@ func validateRelayConfig() error {
return nil
}

// IsFile returns if a path is a file
// IsFile returns whether a file exists and is readable
func isFile(path string) bool {
info, err := os.Stat(path)
if os.IsNotExist(err) || !info.Mode().IsRegular() {
return false
}

return true
f, err := os.Open(filepath.Clean(path))
defer f.Close()
return err == nil
}

// IsDir returns whether a path is a directory
func isDir(path string) bool {
info, err := os.Stat(path)
if os.IsNotExist(err) || !info.IsDir() {
if err != nil || os.IsNotExist(err) || !info.IsDir() {
return false
}

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ require (
golang.org/x/sys v0.19.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect
modernc.org/libc v1.49.3 // indirect
modernc.org/libc v1.50.2 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/strutil v1.2.0 // indirect
Expand Down
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -191,18 +191,18 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk=
modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA=
modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI=
modernc.org/cc/v4 v4.21.0 h1:D/gLKtcztomvWbsbvBKo3leKQv+86f+DdqEZBBXhnag=
modernc.org/cc/v4 v4.21.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.17.0 h1:cX97L5Bv/7PEmyk1oEAD890fQu5/yUQRYeYBsCSnzww=
modernc.org/ccgo/v4 v4.17.0/go.mod h1:keES1eiOIBJhbA5qKrV7ADG3w8DsX8G7jfHAT76riOg=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b h1:BnN1t+pb1cy61zbvSUV7SeI0PwosMhlAEi/vBY4qxp8=
modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg=
modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo=
modernc.org/libc v1.50.2 h1:I0+3wlRvXmAEjAJvD7BhP1kmKHwkzV0rOcqFcD85u+0=
modernc.org/libc v1.50.2/go.mod h1:Fd8TZdfRorOd1vB0QCtYSHYAuzobS4xS3mhMGUkeVcA=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
Expand Down
13 changes: 12 additions & 1 deletion internal/storage/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ func InitDB() error {

config.Database = p

if sqlDriver == "sqlite" {
if !isFile(p) {
// try create a file to ensure permissions
f, err := os.Create(p)
if err != nil {
return fmt.Errorf("[db] %s", err.Error())
}
_ = f.Close()
}
}

var err error

db, err = sql.Open(sqlDriver, dsn)
Expand All @@ -73,7 +84,7 @@ func InitDB() error {
for i := 1; i < 6; i++ {
if err := Ping(); err != nil {
logger.Log().Errorf("[db] %s", err.Error())
logger.Log().Infof("[db] reconnecting in 5 seconds (%d/5)", i)
logger.Log().Infof("[db] reconnecting in 5 seconds (attempt %d/5)", i)
time.Sleep(5 * time.Second)
} else {
continue
Expand Down
16 changes: 12 additions & 4 deletions internal/storage/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"regexp"
"sort"
"strings"
"sync"

"github.com/axllent/mailpit/config"
"github.com/axllent/mailpit/internal/logger"
Expand All @@ -15,6 +16,7 @@ import (

var (
addressPlusRe = regexp.MustCompile(`(?U)^(.*){1,}\+(.*)@`)
addTagMutex sync.RWMutex
)

// SetMessageTags will set the tags for a given database ID
Expand Down Expand Up @@ -58,14 +60,18 @@ func SetMessageTags(id string, tags []string) error {

// AddMessageTag adds a tag to a message
func AddMessageTag(id, name string) error {
// prevent two identical tags being added at the same time
addTagMutex.Lock()

var tagID int

q := sqlf.From(tenant("tags")).
Select("ID").To(&tagID).
Where("Name = ?", name)

// tag exists - add tag to message
// if tag exists - add tag to message
if err := q.QueryRowAndClose(context.TODO(), db); err == nil {
addTagMutex.Unlock()
// check message does not already have this tag
var count int
if _, err := sqlf.From(tenant("message_tags")).
Expand All @@ -89,15 +95,17 @@ func AddMessageTag(id, name string) error {
return err
}

logger.Log().Debugf("[tags] adding tag \"%s\" to %s", name, id)

// tag dos not exist, add new one
// new tag, add to the database
if _, err := sqlf.InsertInto(tenant("tags")).
Set("Name", name).
ExecAndClose(context.TODO(), db); err != nil {
addTagMutex.Unlock()
return err
}

addTagMutex.Unlock()

// add tag to the message
return AddMessageTag(id, name)
}

Expand Down
Loading

0 comments on commit a5cbba3

Please sign in to comment.