mirror of
https://github.com/axllent/mailpit.git
synced 2025-06-08 23:46:21 +02:00
Chore: Code cleanup
This commit is contained in:
parent
073ddd33d5
commit
a56fd1f53d
@ -78,5 +78,6 @@ func clean(text string) string {
|
|||||||
}, text)
|
}, text)
|
||||||
|
|
||||||
text = re.ReplaceAllString(text, " ")
|
text = re.ReplaceAllString(text, " ")
|
||||||
|
|
||||||
return strings.TrimSpace(text)
|
return strings.TrimSpace(text)
|
||||||
}
|
}
|
||||||
|
@ -30,14 +30,17 @@ type Conn struct {
|
|||||||
|
|
||||||
// Opt represents the client configuration.
|
// Opt represents the client configuration.
|
||||||
type Opt struct {
|
type Opt struct {
|
||||||
|
// Host name
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
|
// Port number
|
||||||
Port int `json:"port"`
|
Port int `json:"port"`
|
||||||
|
// DialTimeout default is 3 seconds.
|
||||||
// Default is 3 seconds.
|
|
||||||
DialTimeout time.Duration `json:"dial_timeout"`
|
DialTimeout time.Duration `json:"dial_timeout"`
|
||||||
|
// Dialer
|
||||||
Dialer Dialer `json:"-"`
|
Dialer Dialer `json:"-"`
|
||||||
|
// TLSEnabled sets whether SLS is enabled
|
||||||
TLSEnabled bool `json:"tls_enabled"`
|
TLSEnabled bool `json:"tls_enabled"`
|
||||||
|
// TLSSkipVerify skips TLS verification (ie: self-signed)
|
||||||
TLSSkipVerify bool `json:"tls_skip_verify"`
|
TLSSkipVerify bool `json:"tls_skip_verify"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,15 +53,14 @@ type Dialer interface {
|
|||||||
type MessageID struct {
|
type MessageID struct {
|
||||||
// ID is the numerical index (non-unique) of the message.
|
// ID is the numerical index (non-unique) of the message.
|
||||||
ID int
|
ID int
|
||||||
|
// Size in bytes
|
||||||
Size int
|
Size int
|
||||||
|
|
||||||
// UID is only present if the response is to the UIDL command.
|
// UID is only present if the response is to the UIDL command.
|
||||||
UID string
|
UID string
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
lineBreak = []byte("\r\n")
|
lineBreak = []byte("\r\n")
|
||||||
|
|
||||||
respOK = []byte("+OK") // `+OK` without additional info
|
respOK = []byte("+OK") // `+OK` without additional info
|
||||||
respOKInfo = []byte("+OK ") // `+OK <info>`
|
respOKInfo = []byte("+OK ") // `+OK <info>`
|
||||||
respErr = []byte("-ERR") // `-ERR` without additional info
|
respErr = []byte("-ERR") // `-ERR` without additional info
|
||||||
@ -126,6 +128,7 @@ func (c *Conn) Send(b string) error {
|
|||||||
if _, err := c.w.WriteString(b + "\r\n"); err != nil {
|
if _, err := c.w.WriteString(b + "\r\n"); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.w.Flush()
|
return c.w.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,12 +226,14 @@ func (c *Conn) Auth(user, password string) error {
|
|||||||
// User sends the username to the server.
|
// User sends the username to the server.
|
||||||
func (c *Conn) User(s string) error {
|
func (c *Conn) User(s string) error {
|
||||||
_, err := c.Cmd("USER", false, s)
|
_, err := c.Cmd("USER", false, s)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass sends the password to the server.
|
// Pass sends the password to the server.
|
||||||
func (c *Conn) Pass(s string) error {
|
func (c *Conn) Pass(s string) error {
|
||||||
_, err := c.Cmd("PASS", false, s)
|
_, err := c.Cmd("PASS", false, s)
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/axllent/mailpit/internal/tools"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProtoVersion is the protocol version
|
// ProtoVersion is the protocol version
|
||||||
@ -81,6 +83,7 @@ func (c *Client) dial() (connection, error) {
|
|||||||
}
|
}
|
||||||
return net.DialUnix("unix", nil, unixAddr)
|
return net.DialUnix("unix", nil, unixAddr)
|
||||||
}
|
}
|
||||||
|
|
||||||
panic("Client.net must be either \"tcp\" or \"unix\"")
|
panic("Client.net must be either \"tcp\" or \"unix\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,26 +110,25 @@ func (c *Client) report(email []byte) ([]string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bw := bufio.NewWriter(conn)
|
bw := bufio.NewWriter(conn)
|
||||||
_, err = bw.WriteString("REPORT SPAMC/" + ProtoVersion + "\r\n")
|
if _, err := bw.WriteString("REPORT SPAMC/" + ProtoVersion + "\r\n"); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = bw.WriteString("Content-length: " + strconv.Itoa(len(email)) + "\r\n\r\n")
|
|
||||||
if err != nil {
|
if _, err := bw.WriteString("Content-length: " + strconv.Itoa(len(email)) + "\r\n\r\n"); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
_, err = bw.Write(email)
|
|
||||||
if err != nil {
|
if _, err := bw.Write(email); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
err = bw.Flush()
|
|
||||||
if err != nil {
|
if err := bw.Flush(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client is supposed to close its writing side of the connection
|
// Client is supposed to close its writing side of the connection
|
||||||
// after sending its request.
|
// after sending its request.
|
||||||
err = conn.CloseWrite()
|
if err := conn.CloseWrite(); err != nil {
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +136,7 @@ func (c *Client) report(email []byte) ([]string, error) {
|
|||||||
lines []string
|
lines []string
|
||||||
br = bufio.NewReader(conn)
|
br = bufio.NewReader(conn)
|
||||||
)
|
)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
line, err := br.ReadString('\n')
|
line, err := br.ReadString('\n')
|
||||||
if err == io.EOF {
|
if err == io.EOF {
|
||||||
@ -171,11 +174,12 @@ func (c *Client) parseOutput(output []string) Result {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// summary
|
// summary
|
||||||
if spamMainRe.MatchString(row) {
|
if spamMainRe.MatchString(row) {
|
||||||
res := spamMainRe.FindStringSubmatch(row)
|
res := spamMainRe.FindStringSubmatch(row)
|
||||||
if len(res) == 4 {
|
if len(res) == 4 {
|
||||||
if strings.ToLower(res[1]) == "true" || strings.ToLower(res[1]) == "yes" {
|
if tools.InArray(res[1], []string{"true", "yes"}) {
|
||||||
result.Spam = true
|
result.Spam = true
|
||||||
} else {
|
} else {
|
||||||
result.Spam = false
|
result.Spam = false
|
||||||
@ -197,8 +201,8 @@ func (c *Client) parseOutput(output []string) Result {
|
|||||||
reachedRules = true
|
reachedRules = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// details
|
// details
|
||||||
// row = strings.Trim(row, " \t\r\n")
|
|
||||||
if reachedRules && spamDetailsRe.MatchString(row) {
|
if reachedRules && spamDetailsRe.MatchString(row) {
|
||||||
res := spamDetailsRe.FindStringSubmatch(row)
|
res := spamDetailsRe.FindStringSubmatch(row)
|
||||||
if len(res) == 5 {
|
if len(res) == 5 {
|
||||||
@ -207,6 +211,7 @@ func (c *Client) parseOutput(output []string) Result {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,12 +227,11 @@ func (c *Client) Ping() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = io.WriteString(conn, fmt.Sprintf("PING SPAMC/%s\r\n\r\n", ProtoVersion))
|
if _, err := io.WriteString(conn, fmt.Sprintf("PING SPAMC/%s\r\n\r\n", ProtoVersion)); err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = conn.CloseWrite()
|
|
||||||
if err != nil {
|
if err := conn.CloseWrite(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,5 +245,6 @@ func (c *Client) Ping() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,12 @@ var (
|
|||||||
|
|
||||||
// InitDB will initialise the database
|
// InitDB will initialise the database
|
||||||
func InitDB() error {
|
func InitDB() error {
|
||||||
|
var (
|
||||||
|
dsn string
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
p := config.Database
|
p := config.Database
|
||||||
var dsn string
|
|
||||||
|
|
||||||
if p == "" {
|
if p == "" {
|
||||||
// when no path is provided then we create a temporary file
|
// when no path is provided then we create a temporary file
|
||||||
@ -74,8 +78,6 @@ func InitDB() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
|
||||||
|
|
||||||
db, err = sql.Open(sqlDriver, dsn)
|
db, err = sql.Open(sqlDriver, dsn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -430,6 +430,21 @@ func GetAttachmentPart(id, partID string) (*enmime.Part, error) {
|
|||||||
return nil, errors.New("attachment not found")
|
return nil, errors.New("attachment not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AttachmentSummary returns a summary of the attachment without any binary data
|
||||||
|
func AttachmentSummary(a *enmime.Part) Attachment {
|
||||||
|
o := Attachment{}
|
||||||
|
o.PartID = a.PartID
|
||||||
|
o.FileName = a.FileName
|
||||||
|
if o.FileName == "" {
|
||||||
|
o.FileName = a.ContentID
|
||||||
|
}
|
||||||
|
o.ContentType = a.ContentType
|
||||||
|
o.ContentID = a.ContentID
|
||||||
|
o.Size = float64(len(a.Content))
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
// LatestID returns the latest message ID
|
// LatestID returns the latest message ID
|
||||||
//
|
//
|
||||||
// If a query argument is set in the request the function will return the
|
// If a query argument is set in the request the function will return the
|
||||||
|
@ -43,9 +43,13 @@ func ReindexAll() {
|
|||||||
logger.Log().Infof("reindexing %d messages", total)
|
logger.Log().Infof("reindexing %d messages", total)
|
||||||
|
|
||||||
type updateStruct struct {
|
type updateStruct struct {
|
||||||
|
// ID in database
|
||||||
ID string
|
ID string
|
||||||
|
// SearchText for searching
|
||||||
SearchText string
|
SearchText string
|
||||||
|
// Snippet for UI
|
||||||
Snippet string
|
Snippet string
|
||||||
|
// Metadata info
|
||||||
Metadata string
|
Metadata string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,5 +141,6 @@ func chunkBy[T any](items []T, chunkSize int) (chunks [][]T) {
|
|||||||
for chunkSize < len(items) {
|
for chunkSize < len(items) {
|
||||||
items, chunks = items[chunkSize:], append(chunks, items[0:chunkSize:chunkSize])
|
items, chunks = items[chunkSize:], append(chunks, items[0:chunkSize:chunkSize])
|
||||||
}
|
}
|
||||||
|
|
||||||
return append(chunks, items)
|
return append(chunks, items)
|
||||||
}
|
}
|
||||||
|
@ -198,6 +198,7 @@ func DeleteSearch(search, timezone string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dbLastAction = time.Now()
|
dbLastAction = time.Now()
|
||||||
|
|
||||||
addDeletedSize(int64(deleteSize))
|
addDeletedSize(int64(deleteSize))
|
||||||
|
|
||||||
logMessagesDeleted(total)
|
logMessagesDeleted(total)
|
||||||
|
@ -3,8 +3,6 @@ package storage
|
|||||||
import (
|
import (
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jhillyerd/enmime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Message data excluding physical attachments
|
// Message data excluding physical attachments
|
||||||
@ -114,21 +112,6 @@ type DBMailSummary struct {
|
|||||||
ReplyTo []*mail.Address
|
ReplyTo []*mail.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
// AttachmentSummary returns a summary of the attachment without any binary data
|
|
||||||
func AttachmentSummary(a *enmime.Part) Attachment {
|
|
||||||
o := Attachment{}
|
|
||||||
o.PartID = a.PartID
|
|
||||||
o.FileName = a.FileName
|
|
||||||
if o.FileName == "" {
|
|
||||||
o.FileName = a.ContentID
|
|
||||||
}
|
|
||||||
o.ContentType = a.ContentType
|
|
||||||
o.ContentID = a.ContentID
|
|
||||||
o.Size = float64(len(a.Content))
|
|
||||||
|
|
||||||
return o
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListUnsubscribe contains a summary of List-Unsubscribe & List-Unsubscribe-Post headers
|
// ListUnsubscribe contains a summary of List-Unsubscribe & List-Unsubscribe-Post headers
|
||||||
// including validation of the link structure
|
// including validation of the link structure
|
||||||
type ListUnsubscribe struct {
|
type ListUnsubscribe struct {
|
||||||
|
@ -13,8 +13,11 @@ import (
|
|||||||
|
|
||||||
// TagFilter struct
|
// TagFilter struct
|
||||||
type TagFilter struct {
|
type TagFilter struct {
|
||||||
|
// Match is the user-defined match
|
||||||
Match string
|
Match string
|
||||||
|
// SQL represents the SQL equivalent of Match
|
||||||
SQL *sqlf.Stmt
|
SQL *sqlf.Stmt
|
||||||
|
// Tags to add on match
|
||||||
Tags []string
|
Tags []string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ func addMessageTag(id, name string) (string, error) {
|
|||||||
Set("ID", id).
|
Set("ID", id).
|
||||||
Set("TagID", tagID).
|
Set("TagID", tagID).
|
||||||
ExecAndClose(context.TODO(), db)
|
ExecAndClose(context.TODO(), db)
|
||||||
|
|
||||||
return foundName.String, err
|
return foundName.String, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,14 +11,14 @@ func Plural(total int, singular, plural string) string {
|
|||||||
if total == 1 {
|
if total == 1 {
|
||||||
return fmt.Sprintf("%d %s", total, singular)
|
return fmt.Sprintf("%d %s", total, singular)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%d %s", total, plural)
|
return fmt.Sprintf("%d %s", total, plural)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InArray tests if a string is within an array. It is not case sensitive.
|
// InArray tests if a string is within an array. It is not case sensitive.
|
||||||
func InArray(k string, arr []string) bool {
|
func InArray(k string, arr []string) bool {
|
||||||
k = strings.ToLower(k)
|
|
||||||
for _, v := range arr {
|
for _, v := range arr {
|
||||||
if strings.ToLower(v) == k {
|
if strings.EqualFold(v, k) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,5 +71,6 @@ func Unzip(src string, dest string) ([]string, error) {
|
|||||||
return filenames, err
|
return filenames, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return filenames, nil
|
return filenames, nil
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ var (
|
|||||||
// AllowPrereleases defines whether pre-releases may be included
|
// AllowPrereleases defines whether pre-releases may be included
|
||||||
AllowPrereleases = false
|
AllowPrereleases = false
|
||||||
|
|
||||||
|
// temporary directory
|
||||||
tempDir string
|
tempDir string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ var (
|
|||||||
SMTPAddr = "localhost:1025"
|
SMTPAddr = "localhost:1025"
|
||||||
// FromAddr email address
|
// FromAddr email address
|
||||||
FromAddr string
|
FromAddr string
|
||||||
|
|
||||||
// UseB - used to set from `-bs`
|
// UseB - used to set from `-bs`
|
||||||
UseB bool
|
UseB bool
|
||||||
// UseS - used to set from `-bs`
|
// UseS - used to set from `-bs`
|
||||||
|
@ -79,5 +79,6 @@ func getSafeArg(args []string, nr int) (string, error) {
|
|||||||
if nr < len(args) {
|
if nr < len(args) {
|
||||||
return args[nr], nil
|
return args[nr], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", errors.New("-ERR out of range")
|
return "", errors.New("-ERR out of range")
|
||||||
}
|
}
|
||||||
|
@ -220,6 +220,7 @@ func middleWareFunc(fn http.HandlerFunc) http.HandlerFunc {
|
|||||||
fn(w, r)
|
fn(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Encoding", "gzip")
|
w.Header().Set("Content-Encoding", "gzip")
|
||||||
gz := gzip.NewWriter(w)
|
gz := gzip.NewWriter(w)
|
||||||
defer gz.Close()
|
defer gz.Close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user