mirror of
https://github.com/axllent/mailpit.git
synced 2025-06-23 00:29:15 +02:00
Merge branch 'feature/label' into develop
This commit is contained in:
@ -82,6 +82,7 @@ func init() {
|
|||||||
initConfigFromEnv()
|
initConfigFromEnv()
|
||||||
|
|
||||||
rootCmd.Flags().StringVarP(&config.Database, "database", "d", config.Database, "Database to store persistent data")
|
rootCmd.Flags().StringVarP(&config.Database, "database", "d", config.Database, "Database to store persistent data")
|
||||||
|
rootCmd.Flags().StringVar(&config.Label, "label", config.Label, "Optional label identify this Mailpit instance")
|
||||||
rootCmd.Flags().StringVar(&config.TenantID, "tenant-id", config.TenantID, "Database tenant ID to isolate data")
|
rootCmd.Flags().StringVar(&config.TenantID, "tenant-id", config.TenantID, "Database tenant ID to isolate data")
|
||||||
rootCmd.Flags().IntVarP(&config.MaxMessages, "max", "m", config.MaxMessages, "Max number of messages to store")
|
rootCmd.Flags().IntVarP(&config.MaxMessages, "max", "m", config.MaxMessages, "Max number of messages to store")
|
||||||
rootCmd.Flags().BoolVar(&config.UseMessageDates, "use-message-dates", config.UseMessageDates, "Use message dates as the received dates")
|
rootCmd.Flags().BoolVar(&config.UseMessageDates, "use-message-dates", config.UseMessageDates, "Use message dates as the received dates")
|
||||||
@ -172,6 +173,8 @@ func initConfigFromEnv() {
|
|||||||
|
|
||||||
config.TenantID = os.Getenv("MP_TENANT_ID")
|
config.TenantID = os.Getenv("MP_TENANT_ID")
|
||||||
|
|
||||||
|
config.Label = os.Getenv("MP_LABEL")
|
||||||
|
|
||||||
if len(os.Getenv("MP_MAX_MESSAGES")) > 0 {
|
if len(os.Getenv("MP_MAX_MESSAGES")) > 0 {
|
||||||
config.MaxMessages, _ = strconv.Atoi(os.Getenv("MP_MAX_MESSAGES"))
|
config.MaxMessages, _ = strconv.Atoi(os.Getenv("MP_MAX_MESSAGES"))
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/axllent/mailpit/internal/auth"
|
"github.com/axllent/mailpit/internal/auth"
|
||||||
"github.com/axllent/mailpit/internal/logger"
|
"github.com/axllent/mailpit/internal/logger"
|
||||||
"github.com/axllent/mailpit/internal/spamassassin"
|
"github.com/axllent/mailpit/internal/spamassassin"
|
||||||
|
"github.com/axllent/mailpit/internal/tools"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -32,6 +33,10 @@ var (
|
|||||||
// allowing multiple isolated instances of Mailpit to share a database.
|
// allowing multiple isolated instances of Mailpit to share a database.
|
||||||
TenantID = ""
|
TenantID = ""
|
||||||
|
|
||||||
|
// Label to identify this Mailpit instance (optional).
|
||||||
|
// This gets applied to web UI, SMTP and optional POP3 server.
|
||||||
|
Label = ""
|
||||||
|
|
||||||
// MaxMessages is the maximum number of messages a mailbox can have (auto-pruned every minute)
|
// MaxMessages is the maximum number of messages a mailbox can have (auto-pruned every minute)
|
||||||
MaxMessages = 500
|
MaxMessages = 500
|
||||||
|
|
||||||
@ -201,7 +206,9 @@ func VerifyConfig() error {
|
|||||||
Database = filepath.Join(Database, "mailpit.db")
|
Database = filepath.Join(Database, "mailpit.db")
|
||||||
}
|
}
|
||||||
|
|
||||||
TenantID = strings.TrimSpace(TenantID)
|
Label = tools.Normalize(Label)
|
||||||
|
|
||||||
|
TenantID = tools.Normalize(TenantID)
|
||||||
if TenantID != "" {
|
if TenantID != "" {
|
||||||
logger.Log().Infof("[db] using tenant \"%s\"", TenantID)
|
logger.Log().Infof("[db] using tenant \"%s\"", TenantID)
|
||||||
re := regexp.MustCompile(`[^a-zA-Z0-9\_]`)
|
re := regexp.MustCompile(`[^a-zA-Z0-9\_]`)
|
||||||
|
@ -2,6 +2,7 @@ package tools
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,3 +25,14 @@ func InArray(k string, arr []string) bool {
|
|||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Normalize will remove any extra spaces, remove newlines, and trim leading and trailing spaces
|
||||||
|
func Normalize(s string) string {
|
||||||
|
nlRe := regexp.MustCompile(`\r?\r`)
|
||||||
|
re := regexp.MustCompile(`\s+`)
|
||||||
|
|
||||||
|
s = nlRe.ReplaceAllString(s, " ")
|
||||||
|
s = re.ReplaceAllString(s, " ")
|
||||||
|
|
||||||
|
return strings.TrimSpace(s)
|
||||||
|
}
|
||||||
|
@ -12,6 +12,8 @@ import (
|
|||||||
//
|
//
|
||||||
// swagger:model WebUIConfiguration
|
// swagger:model WebUIConfiguration
|
||||||
type webUIConfiguration struct {
|
type webUIConfiguration struct {
|
||||||
|
// Optional label to identify this Mailpit instance
|
||||||
|
Label string
|
||||||
// Message Relay information
|
// Message Relay information
|
||||||
MessageRelay struct {
|
MessageRelay struct {
|
||||||
// Whether message relaying (release) is enabled
|
// Whether message relaying (release) is enabled
|
||||||
@ -53,6 +55,7 @@ func WebUIConfig(w http.ResponseWriter, _ *http.Request) {
|
|||||||
// default: ErrorResponse
|
// default: ErrorResponse
|
||||||
conf := webUIConfiguration{}
|
conf := webUIConfiguration{}
|
||||||
|
|
||||||
|
conf.Label = config.Label
|
||||||
conf.MessageRelay.Enabled = config.ReleaseEnabled
|
conf.MessageRelay.Enabled = config.ReleaseEnabled
|
||||||
if config.ReleaseEnabled {
|
if config.ReleaseEnabled {
|
||||||
conf.MessageRelay.SMTPServer = fmt.Sprintf("%s:%d", config.SMTPRelayConfig.Host, config.SMTPRelayConfig.Port)
|
conf.MessageRelay.SMTPServer = fmt.Sprintf("%s:%d", config.SMTPRelayConfig.Host, config.SMTPRelayConfig.Port)
|
||||||
|
@ -112,7 +112,11 @@ func handleClient(conn net.Conn) {
|
|||||||
logger.Log().Debugf("[pop3] connection opened by %s", conn.RemoteAddr().String())
|
logger.Log().Debugf("[pop3] connection opened by %s", conn.RemoteAddr().String())
|
||||||
|
|
||||||
// First welcome the new connection
|
// First welcome the new connection
|
||||||
sendResponse(conn, "+OK Mailpit POP3 server")
|
serverName := "Mailpit"
|
||||||
|
if config.Label != "" {
|
||||||
|
serverName = fmt.Sprintf("Mailpit (%s)", config.Label)
|
||||||
|
}
|
||||||
|
sendResponse(conn, fmt.Sprintf("+OK %s POP3 server", serverName))
|
||||||
|
|
||||||
// Set 10 minutes timeout according to RFC1939
|
// Set 10 minutes timeout according to RFC1939
|
||||||
timeoutDuration := 600 * time.Second
|
timeoutDuration := 600 * time.Second
|
||||||
|
@ -223,6 +223,10 @@ func listenAndServe(addr string, handler smtpd.MsgIDHandler, authHandler smtpd.A
|
|||||||
DisableReverseDNS: DisableReverseDNS,
|
DisableReverseDNS: DisableReverseDNS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.Label != "" {
|
||||||
|
srv.Appname = fmt.Sprintf("Mailpit (%s)", config.Label)
|
||||||
|
}
|
||||||
|
|
||||||
if config.SMTPAuthAllowInsecure {
|
if config.SMTPAuthAllowInsecure {
|
||||||
srv.AuthMechs = map[string]bool{"CRAM-MD5": false, "PLAIN": true, "LOGIN": true}
|
srv.AuthMechs = map[string]bool{"CRAM-MD5": false, "PLAIN": true, "LOGIN": true}
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,16 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
document.title = document.title + ' - ' + location.hostname
|
|
||||||
|
|
||||||
// load global config
|
// load global config
|
||||||
this.get(this.resolve('/api/v1/webui'), false, function (response) {
|
this.get(this.resolve('/api/v1/webui'), false, function (response) {
|
||||||
mailbox.uiConfig = response.data
|
mailbox.uiConfig = response.data
|
||||||
|
|
||||||
|
if (mailbox.uiConfig.Label) {
|
||||||
|
document.title = document.title + ' - ' + mailbox.uiConfig.Label
|
||||||
|
} else {
|
||||||
|
document.title = document.title + ' - ' + location.hostname
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -133,16 +133,14 @@ export default {
|
|||||||
{{ getRelativeCreated(message) }}
|
{{ getRelativeCreated(message) }}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-truncate d-lg-none privacy">
|
<div class="text-truncate d-lg-none privacy">
|
||||||
<span v-if="message.From" :title="'From: ' + message.From.Address">{{
|
<span v-if="message.From" :title="'From: ' + message.From.Address">
|
||||||
message.From.Name ?
|
{{ message.From.Name ? message.From.Name : message.From.Address }}
|
||||||
message.From.Name : message.From.Address
|
</span>
|
||||||
}}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="text-truncate d-none d-lg-block privacy">
|
<div class="text-truncate d-none d-lg-block privacy">
|
||||||
<b v-if="message.From" :title="'From: ' + message.From.Address">{{
|
<b v-if="message.From" :title="'From: ' + message.From.Address">
|
||||||
message.From.Name ?
|
{{ message.From.Name ? message.From.Name : message.From.Address }}
|
||||||
message.From.Name : message.From.Address
|
</b>
|
||||||
}}</b>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="d-none d-lg-block text-truncate text-muted small privacy">
|
<div class="d-none d-lg-block text-truncate text-muted small privacy">
|
||||||
{{ getPrimaryEmailTo(message) }}
|
{{ getPrimaryEmailTo(message) }}
|
||||||
|
@ -68,7 +68,12 @@ export default {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="!modals">
|
<template v-if="!modals">
|
||||||
<div class="list-group my-2">
|
<div class="text-center badge text-bg-primary py-2 mt-2 w-100 text-truncate fw-normal"
|
||||||
|
v-if="mailbox.uiConfig.Label">
|
||||||
|
{{ mailbox.uiConfig.Label }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-group my-2" :class="mailbox.uiConfig.Label ? 'mt-1' : ''">
|
||||||
<button @click="reloadInbox" class="list-group-item list-group-item-action active">
|
<button @click="reloadInbox" class="list-group-item list-group-item-action active">
|
||||||
<i class="bi bi-envelope-fill me-1" v-if="mailbox.connected"></i>
|
<i class="bi bi-envelope-fill me-1" v-if="mailbox.connected"></i>
|
||||||
<i class="bi bi-arrow-clockwise me-1" v-else></i>
|
<i class="bi bi-arrow-clockwise me-1" v-else></i>
|
||||||
|
@ -54,7 +54,12 @@ export default {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="!modals">
|
<template v-if="!modals">
|
||||||
<div class="list-group my-2">
|
<div class="text-center badge text-bg-primary py-2 mt-2 w-100 text-truncate fw-normal"
|
||||||
|
v-if="mailbox.uiConfig.Label">
|
||||||
|
{{ mailbox.uiConfig.Label }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-group my-2" :class="mailbox.uiConfig.Label ? 'mt-1' : ''">
|
||||||
<RouterLink to="/" class="list-group-item list-group-item-action" @click="pagination.start = 0">
|
<RouterLink to="/" class="list-group-item list-group-item-action" @click="pagination.start = 0">
|
||||||
<i class="bi bi-arrow-return-left me-1"></i>
|
<i class="bi bi-arrow-return-left me-1"></i>
|
||||||
<span class="ms-1">Inbox</span>
|
<span class="ms-1">Inbox</span>
|
||||||
@ -77,7 +82,8 @@ export default {
|
|||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<!-- Modals -->
|
<!-- Modals -->
|
||||||
<div class="modal fade" id="DeleteAllModal" tabindex="-1" aria-labelledby="DeleteAllModalLabel" aria-hidden="true">
|
<div class="modal fade" id="DeleteAllModal" tabindex="-1" aria-labelledby="DeleteAllModalLabel"
|
||||||
|
aria-hidden="true">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
|
@ -317,8 +317,12 @@ export default {
|
|||||||
<div class="row flex-fill" style="min-height:0">
|
<div class="row flex-fill" style="min-height:0">
|
||||||
<div class="d-none d-md-block col-xl-2 col-md-3 mh-100 position-relative"
|
<div class="d-none d-md-block col-xl-2 col-md-3 mh-100 position-relative"
|
||||||
style="overflow-y: auto; overflow-x: hidden;">
|
style="overflow-y: auto; overflow-x: hidden;">
|
||||||
|
<div class="text-center badge text-bg-primary py-2 mt-2 w-100 text-truncate fw-normal"
|
||||||
|
v-if="mailbox.uiConfig.Label">
|
||||||
|
{{ mailbox.uiConfig.Label }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="list-group my-2">
|
<div class="list-group my-2" :class="mailbox.uiConfig.Label ? 'mt-1' : ''">
|
||||||
<button @click="goBack()" class="list-group-item list-group-item-action">
|
<button @click="goBack()" class="list-group-item list-group-item-action">
|
||||||
<i class="bi bi-arrow-return-left me-1"></i>
|
<i class="bi bi-arrow-return-left me-1"></i>
|
||||||
<span class="ms-1">Return</span>
|
<span class="ms-1">Return</span>
|
||||||
|
@ -1635,6 +1635,10 @@
|
|||||||
"description": "Whether messages with duplicate IDs are ignored",
|
"description": "Whether messages with duplicate IDs are ignored",
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
},
|
},
|
||||||
|
"Label": {
|
||||||
|
"description": "Optional label to identify this Mailpit instance",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"MessageRelay": {
|
"MessageRelay": {
|
||||||
"description": "Message Relay information",
|
"description": "Message Relay information",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
Reference in New Issue
Block a user