diff --git a/CHANGELOG.md b/CHANGELOG.md index 86b107a..0af4b51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ Notable changes to Mailpit will be documented in this file. +## [v1.15.1] + +### Chore +- Code cleanup, remove redundant functionality +- Add labels to Docker image ([#267](https://github.com/axllent/mailpit/issues/267)) + +### Feature +- Add readyz subcommand for Docker healthcheck ([#270](https://github.com/axllent/mailpit/issues/270)) + + ## [v1.15.0] ### Chore diff --git a/Dockerfile b/Dockerfile index 13e7517..fa7f27f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,10 +12,19 @@ CGO_ENABLED=0 go build -ldflags "-s -w -X github.com/axllent/mailpit/config.Vers FROM alpine:latest +LABEL org.opencontainers.image.title="Mailpit" \ + org.opencontainers.image.description="An email and SMTP testing tool with API for developers" \ + org.opencontainers.image.source="https://github.com/axllent/mailpit" \ + org.opencontainers.image.url="https://mailpit.axllent.org" \ + org.opencontainers.image.documentation="https://mailpit.axllent.org/docs/" \ + org.opencontainers.image.licenses="MIT" + COPY --from=builder /mailpit /mailpit RUN apk add --no-cache tzdata EXPOSE 1025/tcp 1110/tcp 8025/tcp +HEALTHCHECK --interval=15s CMD /mailpit readyz + ENTRYPOINT ["/mailpit"] diff --git a/cmd/ingest.go b/cmd/ingest.go index c575668..cab2419 100644 --- a/cmd/ingest.go +++ b/cmd/ingest.go @@ -49,9 +49,7 @@ The --recent flag will only consider files with a modification date within the l return nil } - info.ModTime() - - if ingestRecent > 0 && time.Now().Sub(info.ModTime()) > time.Duration(ingestRecent)*24*time.Hour { + if ingestRecent > 0 && time.Since(info.ModTime()) > time.Duration(ingestRecent)*24*time.Hour { return nil } diff --git a/cmd/readyz.go b/cmd/readyz.go new file mode 100644 index 0000000..d65a7a2 --- /dev/null +++ b/cmd/readyz.go @@ -0,0 +1,75 @@ +package cmd + +import ( + "crypto/tls" + "fmt" + "net/http" + "os" + "path" + "strings" + "time" + + "github.com/axllent/mailpit/config" + "github.com/spf13/cobra" +) + +var ( + useHTTPS bool +) + +// readyzCmd represents the healthcheck command +var readyzCmd = &cobra.Command{ + Use: "readyz", + Short: "Run a healthcheck to test if Mailpit is running", + Long: `This command connects to the /readyz endpoint of a running Mailpit server +and exits with a status of 0 if the connection is successful, else with a +status 1 if unhealthy. + +If running within Docker, it should automatically detect environment +settings to determine the HTTP bind interface & port. +`, + Run: func(cmd *cobra.Command, args []string) { + webroot := strings.TrimRight(path.Join("/", config.Webroot, "/"), "/") + "/" + proto := "http" + if useHTTPS { + proto = "https" + } + + uri := fmt.Sprintf("%s://%s%sreadyz", proto, config.HTTPListen, webroot) + + conf := &http.Transport{ + IdleConnTimeout: time.Second * 5, + ExpectContinueTimeout: time.Second * 5, + TLSHandshakeTimeout: time.Second * 5, + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + client := &http.Client{Transport: conf} + + res, err := client.Get(uri) + if err != nil || res.StatusCode != 200 { + os.Exit(1) + } + }, +} + +func init() { + rootCmd.AddCommand(readyzCmd) + + if len(os.Getenv("MP_UI_BIND_ADDR")) > 0 { + config.HTTPListen = os.Getenv("MP_UI_BIND_ADDR") + } + + if len(os.Getenv("MP_WEBROOT")) > 0 { + config.Webroot = os.Getenv("MP_WEBROOT") + } + + config.UITLSCert = os.Getenv("MP_UI_TLS_CERT") + + if config.UITLSCert != "" { + useHTTPS = true + } + + readyzCmd.Flags().StringVarP(&config.HTTPListen, "listen", "l", config.HTTPListen, "Set the HTTP bind interface & port") + readyzCmd.Flags().StringVar(&config.Webroot, "webroot", config.Webroot, "Set the webroot for web UI & API") + readyzCmd.Flags().BoolVar(&useHTTPS, "https", useHTTPS, "Connect via HTTPS (ignores HTTPS validation)") +} diff --git a/cmd/root.go b/cmd/root.go index 98658af..792ce3b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -17,8 +17,6 @@ import ( "github.com/spf13/cobra" ) -var cfgFile string - // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "mailpit", @@ -91,7 +89,7 @@ func init() { rootCmd.Flags().BoolVarP(&logger.VerboseLogging, "verbose", "v", logger.VerboseLogging, "Verbose logging") // Web UI / API - rootCmd.Flags().StringVarP(&config.HTTPListen, "listen", "l", config.HTTPListen, "HTTP bind interface and port for UI") + rootCmd.Flags().StringVarP(&config.HTTPListen, "listen", "l", config.HTTPListen, "HTTP bind interface & port for UI") rootCmd.Flags().StringVar(&config.Webroot, "webroot", config.Webroot, "Set the webroot for web UI & API") rootCmd.Flags().StringVar(&config.UIAuthFile, "ui-auth-file", config.UIAuthFile, "A password file for web UI & API authentication") rootCmd.Flags().StringVar(&config.UITLSCert, "ui-tls-cert", config.UITLSCert, "TLS certificate for web UI (HTTPS) - requires ui-tls-key") diff --git a/internal/linkcheck/main.go b/internal/linkcheck/main.go index d00c632..8a1f2ab 100644 --- a/internal/linkcheck/main.go +++ b/internal/linkcheck/main.go @@ -32,9 +32,7 @@ func RunTests(msg *storage.Message, followRedirects bool) (Response, error) { func extractTextLinks(msg *storage.Message) []string { links := []string{} - for _, match := range linkRe.FindAllString(msg.Text, -1) { - links = append(links, match) - } + links = append(links, linkRe.FindAllString(msg.Text, -1)...) return links } diff --git a/internal/storage/cron.go b/internal/storage/cron.go index 0a39a32..f2d5ca1 100644 --- a/internal/storage/cron.go +++ b/internal/storage/cron.go @@ -63,7 +63,7 @@ func pruneMessages() { ids := []string{} var prunedSize int64 var size int - if err := q.Query(nil, db, func(row *sql.Rows) { + if err := q.Query(context.TODO(), db, func(row *sql.Rows) { var id string if err := row.Scan(&id, &size); err != nil { diff --git a/internal/storage/database.go b/internal/storage/database.go index 540d67c..583cffb 100644 --- a/internal/storage/database.go +++ b/internal/storage/database.go @@ -2,6 +2,7 @@ package storage import ( + "context" "database/sql" "fmt" "os" @@ -114,6 +115,11 @@ func Close() { } } +// Ping the database connection and return an error if unsuccessful +func Ping() error { + return db.Ping() +} + // StatsGet returns the total/unread statistics for a mailbox func StatsGet() MailboxStats { var ( @@ -137,7 +143,7 @@ func CountTotal() int { _ = sqlf.From("mailbox"). Select("COUNT(*)").To(&total). - QueryRowAndClose(nil, db) + QueryRowAndClose(context.TODO(), db) return total } @@ -146,11 +152,10 @@ func CountTotal() int { func CountUnread() int { var total int - q := sqlf.From("mailbox"). + _ = sqlf.From("mailbox"). Select("COUNT(*)").To(&total). - Where("Read = ?", 0) - - _ = q.QueryRowAndClose(nil, db) + Where("Read = ?", 0). + QueryRowAndClose(context.TODO(), db) return total } @@ -159,26 +164,23 @@ func CountUnread() int { func CountRead() int { var total int - q := sqlf.From("mailbox"). + _ = sqlf.From("mailbox"). Select("COUNT(*)").To(&total). - Where("Read = ?", 1) - - _ = q.QueryRowAndClose(nil, db) + Where("Read = ?", 1). + QueryRowAndClose(context.TODO(), db) return total } -// IsUnread returns the number of emails in the database that are unread. -// If an ID is supplied, then it is just limited to that message. +// IsUnread returns whether a message is unread or not. func IsUnread(id string) bool { var unread int - q := sqlf.From("mailbox"). + _ = sqlf.From("mailbox"). Select("COUNT(*)").To(&unread). Where("Read = ?", 0). - Where("ID = ?", id) - - _ = q.QueryRowAndClose(nil, db) + Where("ID = ?", id). + QueryRowAndClose(context.TODO(), db) return unread == 1 } @@ -187,11 +189,10 @@ func IsUnread(id string) bool { func MessageIDExists(id string) bool { var total int - q := sqlf.From("mailbox"). + _ = sqlf.From("mailbox"). Select("COUNT(*)").To(&total). - Where("MessageID = ?", id) - - _ = q.QueryRowAndClose(nil, db) + Where("MessageID = ?", id). + QueryRowAndClose(context.TODO(), db) return total != 0 } diff --git a/internal/storage/messages.go b/internal/storage/messages.go index 03da204..2228f06 100644 --- a/internal/storage/messages.go +++ b/internal/storage/messages.go @@ -154,7 +154,7 @@ func List(start, limit int) ([]MessageSummary, error) { Limit(limit). Offset(start) - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + if err := q.QueryAndClose(context.TODO(), db, func(row *sql.Rows) { var created int64 var id string var messageID string @@ -245,7 +245,7 @@ func GetMessage(id string) (*Message, error) { Select(`Created`). Where(`ID = ?`, id) - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + if err := q.QueryAndClose(context.TODO(), db, func(row *sql.Rows) { var created int64 if err := row.Scan(&created); err != nil { @@ -564,7 +564,7 @@ func DeleteAllMessages() error { _ = sqlf.From("mailbox"). Select("COUNT(*)").To(&total). - QueryRowAndClose(nil, db) + QueryRowAndClose(context.TODO(), db) // begin a transaction to ensure both the message // summaries and data are deleted successfully diff --git a/internal/storage/migrations.go b/internal/storage/migrations.go index c83e14d..a6e6087 100644 --- a/internal/storage/migrations.go +++ b/internal/storage/migrations.go @@ -1,6 +1,7 @@ package storage import ( + "context" "database/sql" "encoding/json" @@ -140,7 +141,7 @@ func migrateTagsToManyMany() { Where("Tags != ?", "[]"). Where("Tags IS NOT NULL") - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + if err := q.QueryAndClose(context.TODO(), db, func(row *sql.Rows) { var id string var jsonTags string if err := row.Scan(&id, &jsonTags); err != nil { @@ -169,7 +170,7 @@ func migrateTagsToManyMany() { if _, err := sqlf.Update("mailbox"). Set("Tags", nil). Where("ID = ?", id). - ExecAndClose(nil, db); err != nil { + ExecAndClose(context.TODO(), db); err != nil { logger.Log().Errorf("[migration] %s", err.Error()) } } @@ -182,7 +183,7 @@ func migrateTagsToManyMany() { if _, err := sqlf.Update("mailbox"). Set("Tags", nil). Where("Tags = ?", "[]"). - ExecAndClose(nil, db); err != nil { + ExecAndClose(context.TODO(), db); err != nil { logger.Log().Errorf("[migration] %s", err.Error()) } } diff --git a/internal/storage/reindex.go b/internal/storage/reindex.go index f099bb2..8f1a3c4 100644 --- a/internal/storage/reindex.go +++ b/internal/storage/reindex.go @@ -26,7 +26,7 @@ func ReindexAll() { err := sqlf.Select("ID").To(&i). From("mailbox"). OrderBy("Created DESC"). - QueryAndClose(nil, db, func(row *sql.Rows) { + QueryAndClose(context.TODO(), db, func(row *sql.Rows) { ids = append(ids, i) }) diff --git a/internal/storage/search.go b/internal/storage/search.go index 8068521..3c869f6 100644 --- a/internal/storage/search.go +++ b/internal/storage/search.go @@ -29,7 +29,7 @@ func Search(search string, start, limit int) ([]MessageSummary, int, error) { q := searchQueryBuilder(search) var err error - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + if err := q.QueryAndClose(context.TODO(), db, func(row *sql.Rows) { var created int64 var id string var messageID string @@ -101,7 +101,7 @@ func DeleteSearch(search string) error { ids := []string{} deleteSize := 0 - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + if err := q.QueryAndClose(context.TODO(), db, func(row *sql.Rows) { var created int64 var id string var messageID string diff --git a/internal/storage/settings.go b/internal/storage/settings.go index 5a8a218..c81da5e 100644 --- a/internal/storage/settings.go +++ b/internal/storage/settings.go @@ -1,6 +1,7 @@ package storage import ( + "context" "database/sql" "github.com/axllent/mailpit/internal/logger" @@ -14,7 +15,7 @@ func SettingGet(k string) string { Select("Value").To(&result). Where("Key = ?", k). Limit(1). - QueryAndClose(nil, db, func(row *sql.Rows) {}) + QueryAndClose(context.TODO(), db, func(row *sql.Rows) {}) if err != nil { logger.Log().Errorf("[db] %s", err.Error()) return "" @@ -40,7 +41,7 @@ func getDeletedSize() int64 { Select("Value").To(&result). Where("Key = ?", "DeletedSize"). Limit(1). - QueryAndClose(nil, db, func(row *sql.Rows) {}) + QueryAndClose(context.TODO(), db, func(row *sql.Rows) {}) if err != nil { logger.Log().Errorf("[db] %s", err.Error()) return 0 @@ -54,7 +55,7 @@ func totalMessagesSize() int64 { var result sql.NullInt64 err := sqlf.From("mailbox"). Select("SUM(Size)").To(&result). - QueryAndClose(nil, db, func(row *sql.Rows) {}) + QueryAndClose(context.TODO(), db, func(row *sql.Rows) {}) if err != nil { logger.Log().Errorf("[db] %s", err.Error()) return 0 diff --git a/internal/storage/tags.go b/internal/storage/tags.go index 2dec4db..a2f8b71 100644 --- a/internal/storage/tags.go +++ b/internal/storage/tags.go @@ -1,6 +1,7 @@ package storage import ( + "context" "database/sql" "regexp" "sort" @@ -64,14 +65,14 @@ func AddMessageTag(id, name string) error { Where("Name = ?", name) // tag exists - add tag to message - if err := q.QueryRowAndClose(nil, db); err == nil { + if err := q.QueryRowAndClose(context.TODO(), db); err == nil { // check message does not already have this tag var count int if _, err := sqlf.From("message_tags"). Select("COUNT(ID)").To(&count). Where("ID = ?", id). Where("TagID = ?", tagID). - ExecAndClose(nil, db); err != nil { + ExecAndClose(context.TODO(), db); err != nil { return err } if count != 0 { @@ -84,7 +85,7 @@ func AddMessageTag(id, name string) error { _, err := sqlf.InsertInto("message_tags"). Set("ID", id). Set("TagID", tagID). - ExecAndClose(nil, db) + ExecAndClose(context.TODO(), db) return err } @@ -94,7 +95,7 @@ func AddMessageTag(id, name string) error { if err := sqlf.InsertInto("tags"). Set("Name", name). Returning("ID").To(&tagID). - QueryRowAndClose(nil, db); err != nil { + QueryRowAndClose(context.TODO(), db); err != nil { return err } @@ -104,7 +105,7 @@ func AddMessageTag(id, name string) error { Select("COUNT(ID)").To(&count). Where("ID = ?", id). Where("TagID = ?", tagID). - ExecAndClose(nil, db); err != nil { + ExecAndClose(context.TODO(), db); err != nil { return err } if count != 0 { @@ -115,7 +116,7 @@ func AddMessageTag(id, name string) error { _, err := sqlf.InsertInto("message_tags"). Set("ID", id). Set("TagID", tagID). - ExecAndClose(nil, db) + ExecAndClose(context.TODO(), db) return err } @@ -124,7 +125,7 @@ func DeleteMessageTag(id, name string) error { if _, err := sqlf.DeleteFrom("message_tags"). Where("message_tags.ID = ?", id). Where(`message_tags.Key IN (SELECT Key FROM message_tags LEFT JOIN tags ON TagID=tags.ID WHERE Name = ?)`, name). - ExecAndClose(nil, db); err != nil { + ExecAndClose(context.TODO(), db); err != nil { return err } @@ -135,7 +136,7 @@ func DeleteMessageTag(id, name string) error { func DeleteAllMessageTags(id string) error { if _, err := sqlf.DeleteFrom("message_tags"). Where("message_tags.ID = ?", id). - ExecAndClose(nil, db); err != nil { + ExecAndClose(context.TODO(), db); err != nil { return err } @@ -151,7 +152,7 @@ func GetAllTags() []string { Select(`DISTINCT Name`). From("tags").To(&name). OrderBy("Name"). - QueryAndClose(nil, db, func(row *sql.Rows) { + QueryAndClose(context.TODO(), db, func(row *sql.Rows) { tags = append(tags, name) }); err != nil { logger.Log().Errorf("[db] %s", err.Error()) @@ -173,7 +174,7 @@ func GetAllTagsCount() map[string]int64 { LeftJoin("message_tags", "tags.ID = message_tags.TagID"). GroupBy("message_tags.TagID"). OrderBy("Name"). - QueryAndClose(nil, db, func(row *sql.Rows) { + QueryAndClose(context.TODO(), db, func(row *sql.Rows) { tags[name] = total // tags = append(tags, name) }); err != nil { @@ -192,7 +193,7 @@ func pruneUnusedTags() error { toDel := []int{} - if err := q.QueryAndClose(nil, db, func(row *sql.Rows) { + if err := q.QueryAndClose(context.TODO(), db, func(row *sql.Rows) { var n string var id int var c int @@ -214,7 +215,7 @@ func pruneUnusedTags() error { for _, id := range toDel { if _, err := sqlf.DeleteFrom("tags"). Where("ID = ?", id). - ExecAndClose(nil, db); err != nil { + ExecAndClose(context.TODO(), db); err != nil { return err } } @@ -282,7 +283,7 @@ func getMessageTags(id string) []string { LeftJoin("message_tags", "Tags.ID=message_tags.TagID"). Where(`message_tags.ID = ?`, id). OrderBy("Name"). - QueryAndClose(nil, db, func(row *sql.Rows) { + QueryAndClose(context.TODO(), db, func(row *sql.Rows) { tags = append(tags, name) }); err != nil { logger.Log().Errorf("[tags] %s", err.Error()) diff --git a/internal/storage/utils.go b/internal/storage/utils.go index 6dbdd8b..f57001e 100644 --- a/internal/storage/utils.go +++ b/internal/storage/utils.go @@ -103,42 +103,3 @@ func inArray(k string, arr []string) bool { func escPercentChar(s string) string { return strings.ReplaceAll(s, "%", "%%") } - -// Escape certain characters in search phrases -func escSearch(str string) string { - dest := make([]byte, 0, 2*len(str)) - var escape byte - for i := 0; i < len(str); i++ { - c := str[i] - - escape = 0 - - switch c { - case 0: /* Must be escaped for 'mysql' */ - escape = '0' - break - case '\n': /* Must be escaped for logs */ - escape = 'n' - break - case '\r': - escape = 'r' - break - case '\\': - escape = '\\' - break - case '\'': - escape = '\'' - break - case '\032': //十进制26,八进制32,十六进制1a, /* This gives problems on Win32 */ - escape = 'Z' - } - - if escape != 0 { - dest = append(dest, '\\', escape) - } else { - dest = append(dest, c) - } - } - - return string(dest) -} diff --git a/internal/updater/targz.go b/internal/updater/targz.go index 02d30c1..ad4c527 100644 --- a/internal/updater/targz.go +++ b/internal/updater/targz.go @@ -98,53 +98,6 @@ func makeAbsolute(inputFilePath, outputFilePath string) (string, string, error) return inputFilePath, outputFilePath, err } -// Write path without the prefix in subPath to tar writer. -func writeTarGz(path string, tarWriter *tar.Writer, fileInfo os.FileInfo, subPath string) error { - file, err := os.Open(filepath.Clean(path)) - if err != nil { - return err - } - - defer func() { - if err := file.Close(); err != nil { - fmt.Printf("Error closing file: %s\n", err) - } - }() - - evaledPath, err := filepath.EvalSymlinks(path) - if err != nil { - return err - } - - subPath, err = filepath.EvalSymlinks(subPath) - if err != nil { - return err - } - - link := "" - if evaledPath != path { - link = evaledPath - } - - header, err := tar.FileInfoHeader(fileInfo, link) - if err != nil { - return err - } - header.Name = evaledPath[len(subPath):] - - err = tarWriter.WriteHeader(header) - if err != nil { - return err - } - - _, err = io.Copy(tarWriter, file) - if err != nil { - return err - } - - return err -} - // Extract the file in filePath to directory. func extract(filePath string, directory string) error { file, err := os.Open(filepath.Clean(filePath)) @@ -200,7 +153,7 @@ func extract(filePath string, directory string) error { // set file ownership (if allowed) // Chtimes() && Chmod() only set after once extraction is complete - os.Chown(filename, header.Uid, header.Gid) // #nosec + _ = os.Chown(filename, header.Uid, header.Gid) // add directory info to slice to process afterwards postExtraction = append(postExtraction, DirInfo{filename, header}) @@ -249,15 +202,15 @@ func extract(filePath string, directory string) error { } // set file permissions, timestamps & uid/gid - os.Chmod(filename, os.FileMode(header.Mode)) // #nosec - os.Chtimes(filename, header.AccessTime, header.ModTime) // #nosec - os.Chown(filename, header.Uid, header.Gid) // #nosec + _ = os.Chmod(filename, os.FileMode(header.Mode)) + _ = os.Chtimes(filename, header.AccessTime, header.ModTime) + _ = os.Chown(filename, header.Uid, header.Gid) } if len(postExtraction) > 0 { for _, dir := range postExtraction { - os.Chtimes(dir.Path, dir.Header.AccessTime, dir.Header.ModTime) // #nosec - os.Chmod(dir.Path, dir.Header.FileInfo().Mode().Perm()) // #nosec + _ = os.Chtimes(dir.Path, dir.Header.AccessTime, dir.Header.ModTime) + _ = os.Chmod(dir.Path, dir.Header.FileInfo().Mode().Perm()) } } diff --git a/internal/updater/updater.go b/internal/updater/updater.go index da83201..1c0fc90 100644 --- a/internal/updater/updater.go +++ b/internal/updater/updater.go @@ -335,16 +335,6 @@ func mkDirIfNotExists(path string) error { return nil } -// IsFile returns if a path is a file -func isFile(path string) bool { - info, err := os.Stat(path) - if os.IsNotExist(err) || !info.Mode().IsRegular() { - return false - } - - return true -} - // IsDir returns if a path is a directory func isDir(path string) bool { info, err := os.Stat(path) diff --git a/server/apiv1/thumbnails.go b/server/apiv1/thumbnails.go index 8a1291e..a53190c 100644 --- a/server/apiv1/thumbnails.go +++ b/server/apiv1/thumbnails.go @@ -114,7 +114,7 @@ func blankImage(a *enmime.Part, w http.ResponseWriter) { rect := image.Rect(0, 0, thumbWidth, thumbHeight) img := image.NewRGBA(rect) background := color.RGBA{255, 255, 255, 255} - draw.Draw(img, img.Bounds(), &image.Uniform{background}, image.ZP, draw.Src) + draw.Draw(img, img.Bounds(), &image.Uniform{background}, image.Point{}, draw.Src) var b bytes.Buffer foo := bufio.NewWriter(&b) dstImageFill := imaging.Fill(img, thumbWidth, thumbHeight, imaging.Center, imaging.Lanczos) diff --git a/server/handlers/k8sready.go b/server/handlers/k8sready.go index 875b2b4..9ab8500 100644 --- a/server/handlers/k8sready.go +++ b/server/handlers/k8sready.go @@ -3,12 +3,14 @@ package handlers import ( "net/http" "sync/atomic" + + "github.com/axllent/mailpit/internal/storage" ) // ReadyzHandler is a ready probe that signals k8s to be able to retrieve traffic func ReadyzHandler(isReady *atomic.Value) http.HandlerFunc { return func(w http.ResponseWriter, _ *http.Request) { - if isReady == nil || !isReady.Load().(bool) { + if isReady == nil || !isReady.Load().(bool) || storage.Ping() != nil { http.Error(w, http.StatusText(http.StatusServiceUnavailable), http.StatusServiceUnavailable) return } diff --git a/server/pop3/pop3.go b/server/pop3/pop3.go index 43bf339..bc70db3 100644 --- a/server/pop3/pop3.go +++ b/server/pop3/pop3.go @@ -41,9 +41,9 @@ func Run() { var err error if config.POP3TLSCert != "" { - cer, err := tls.LoadX509KeyPair(config.POP3TLSCert, config.POP3TLSKey) - if err != nil { - logger.Log().Errorf("[pop3] %s", err.Error()) + cer, err2 := tls.LoadX509KeyPair(config.POP3TLSCert, config.POP3TLSKey) + if err2 != nil { + logger.Log().Errorf("[pop3] %s", err2.Error()) return } @@ -273,6 +273,10 @@ func handleClient(conn net.Conn) { m := messages[nr-1] headers, body, err := getTop(m.ID, lines) + if err != nil { + sendResponse(conn, err.Error()) + return + } sendData(conn, "+OK Top of message follows") sendData(conn, headers+"\r\n") diff --git a/server/server_test.go b/server/server_test.go index f3250f5..c65c830 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -47,8 +47,6 @@ func TestAPIv1Messages(t *testing.T) { insertEmailData(t) assertStatsEqual(t, ts.URL+"/api/v1/messages", 100, 100) - // store this for later tests - m, err = fetchMessages(ts.URL + "/api/v1/messages") if err != nil { t.Errorf(err.Error()) @@ -56,7 +54,6 @@ func TestAPIv1Messages(t *testing.T) { // read first 10 messages t.Log("Read first 10 messages including raw & headers") - putIDS := []string{} for idx, msg := range m.Messages { if idx == 10 { break @@ -71,13 +68,10 @@ func TestAPIv1Messages(t *testing.T) { t.Errorf(err.Error()) } - // het headers + // get headers if _, err := clientGet(ts.URL + "/api/v1/message/" + msg.ID + "/headers"); err != nil { t.Errorf(err.Error()) } - - // store for later - putIDS = append(putIDS, msg.ID) } // 10 should be marked as read diff --git a/server/websockets/client.go b/server/websockets/client.go index c4523c0..231008e 100644 --- a/server/websockets/client.go +++ b/server/websockets/client.go @@ -22,14 +22,10 @@ const ( // Send pings to peer with this period. Must be less than pongWait. pingPeriod = (pongWait * 9) / 10 - - // Maximum message size allowed from peer. - maxMessageSize = 512 ) var ( newline = []byte{'\n'} - space = []byte{' '} // MessageHub global MessageHub *Hub