Attachment deduplication (SHA-256 content-addressable storage): - Identical files stored once globally (m8sh/sha256/<hash>) - Reference-counted deletion: blob removed only when last ref deleted - StoreAttachmentDedup, DeleteAttachmentDedup, StoreAttachmentFromReader Comprehensive safety limits: - USER_QUOTA: 5 GB default (admins unlimited, 0 = unlimited) - MAX_ATTACHMENT_SIZE: 100 MB per file - MAX_ATTACHMENTS_PER_MESSAGE: 50 files - MAX_MESSAGE_SIZE: 1 MB body - MAX_CONVERSATIONS: 1000 per user - MAX_MESSAGES_PER_CONVERSATION: 10000 Block-domain shredding: - ShredAttachmentsForDomain deletes all blobs + metadata for domain - Dedup-aware: only removes blobs with no remaining references Assisted-By: Cline:anthropic-claude-sonnet-4-20250514
58 lines
2.6 KiB
Go
58 lines
2.6 KiB
Go
// Copyright 2026 The M8SH Authors. All rights reserved.
|
|
// SPDX-License-Identifier: GPL-3.0
|
|
|
|
package setting
|
|
|
|
import (
|
|
"time"
|
|
|
|
"gitea.dev/modules/log"
|
|
)
|
|
|
|
// MailServer holds the configuration for the built-in M8SH SMTP server.
|
|
// Section [mail_server] in app.ini. Domain and certs are NOT configured here;
|
|
// they come from [server].DOMAIN and the existing TLS config respectively,
|
|
// so M8SH stays merge-friendly with upstream Gitea.
|
|
type MailServer struct {
|
|
Enabled bool `ini:"ENABLED"`
|
|
DKIMPrivateKey string `ini:"DKIM_PRIVATE_KEY"` // base64 PEM, auto-generated if empty
|
|
HealthcheckInterv time.Duration `ini:"HEALTHCHECK_INTERVAL"`
|
|
// Storage quota per user in bytes. Admins have unlimited quota.
|
|
// Default: 5 GB. Set to 0 for unlimited.
|
|
UserQuota int64 `ini:"USER_QUOTA"`
|
|
// Maximum attachment size in bytes per single file. Default: 100 MB.
|
|
MaxAttachmentSize int64 `ini:"MAX_ATTACHMENT_SIZE"`
|
|
// Maximum number of attachments per message. Default: 50.
|
|
MaxAttachmentsPerMessage int `ini:"MAX_ATTACHMENTS_PER_MESSAGE"`
|
|
// Maximum message body size in bytes. Default: 1 MB.
|
|
MaxMessageSize int64 `ini:"MAX_MESSAGE_SIZE"`
|
|
// Maximum number of conversations per user. Default: 1000.
|
|
MaxConversations int `ini:"MAX_CONVERSATIONS"`
|
|
// Maximum number of messages per conversation. Default: 10000.
|
|
MaxMessagesPerConversation int `ini:"MAX_MESSAGES_PER_CONVERSATION"`
|
|
}
|
|
|
|
// M8SHMailServer is the global M8SH mail server config.
|
|
var M8SHMailServer *MailServer
|
|
|
|
func loadMailServerFrom(rootCfg ConfigProvider) {
|
|
sec := rootCfg.Section("mail_server")
|
|
m := &MailServer{}
|
|
if err := sec.MapTo(m); err != nil {
|
|
log.Fatal("Unable to map [mail_server] section on to M8SHMailServer. Error: %v", err)
|
|
return
|
|
}
|
|
// Enabled by default — the mail server starts automatically.
|
|
// Set ENABLED = false to disable email delivery (HTTPS chat still works).
|
|
m.Enabled = sec.Key("ENABLED").MustBool(true)
|
|
m.HealthcheckInterv = sec.Key("HEALTHCHECK_INTERVAL").MustDuration(5 * time.Minute)
|
|
m.DKIMPrivateKey = sec.Key("DKIM_PRIVATE_KEY").String()
|
|
// Defaults: 5 GB quota, 100 MB files, 50 atts/msg, 1 MB body, 1k threads, 10k msgs/thread
|
|
m.UserQuota = sec.Key("USER_QUOTA").MustInt64(5 * 1024 * 1024 * 1024)
|
|
m.MaxAttachmentSize = sec.Key("MAX_ATTACHMENT_SIZE").MustInt64(100 * 1024 * 1024)
|
|
m.MaxAttachmentsPerMessage = sec.Key("MAX_ATTACHMENTS_PER_MESSAGE").MustInt(50)
|
|
m.MaxMessageSize = sec.Key("MAX_MESSAGE_SIZE").MustInt64(1024 * 1024)
|
|
m.MaxConversations = sec.Key("MAX_CONVERSATIONS").MustInt(1000)
|
|
m.MaxMessagesPerConversation = sec.Key("MAX_MESSAGES_PER_CONVERSATION").MustInt(10000)
|
|
M8SHMailServer = m
|
|
} |