chore(maildir): 补充邮件目录归属处理
Docker Release / Check web and api (push) Waiting to run
Docker Release / Resolve release tag (push) Blocked by required conditions
Docker Release / Build and publish all-in-one (push) Blocked by required conditions
Docker Release / Build and publish api (push) Blocked by required conditions
Docker Release / Build and publish web (push) Blocked by required conditions
Docker Release / Build and publish dovecot (push) Blocked by required conditions
Docker Release / Build and publish postfix (push) Blocked by required conditions
Docker Release / Build and publish rspamd (push) Blocked by required conditions
Docker Release / Create GitHub release (push) Blocked by required conditions
Docker Release / Check web and api (push) Waiting to run
Docker Release / Resolve release tag (push) Blocked by required conditions
Docker Release / Build and publish all-in-one (push) Blocked by required conditions
Docker Release / Build and publish api (push) Blocked by required conditions
Docker Release / Build and publish web (push) Blocked by required conditions
Docker Release / Build and publish dovecot (push) Blocked by required conditions
Docker Release / Build and publish postfix (push) Blocked by required conditions
Docker Release / Build and publish rspamd (push) Blocked by required conditions
Docker Release / Create GitHub release (push) Blocked by required conditions
- 新增 Unix 与非 Unix 平台的目录归属处理实现。 - 在写入、移动和标记邮件时同步调整 Maildir 目录与文件归属。 - 扩展目录初始化逻辑,确保父目录与子目录权限一致。
This commit is contained in:
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build !unix
|
||||||
|
|
||||||
|
package app
|
||||||
|
|
||||||
|
func applyMaildirOwnership(path string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
//go:build unix
|
||||||
|
|
||||||
|
package app
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
const (
|
||||||
|
maildirOwnerUID = 5000
|
||||||
|
maildirOwnerGID = 5000
|
||||||
|
)
|
||||||
|
|
||||||
|
func applyMaildirOwnership(path string) error {
|
||||||
|
if os.Geteuid() != 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return os.Chown(path, maildirOwnerUID, maildirOwnerGID)
|
||||||
|
}
|
||||||
@@ -120,7 +120,7 @@ func (a *App) writeRawMessageToMaildirFolder(ctx context.Context, messageID, fol
|
|||||||
if strings.EqualFold(folderName, "Inbox") && !state.IsRead {
|
if strings.EqualFold(folderName, "Inbox") && !state.IsRead {
|
||||||
subdir = "new"
|
subdir = "new"
|
||||||
}
|
}
|
||||||
if err := ensureMaildirFolderDirs(folderBase); err != nil {
|
if err := ensureMaildirFolderDirs(base, folderBase); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
filename := maildirFilename(messageID, state.MessageID)
|
filename := maildirFilename(messageID, state.MessageID)
|
||||||
@@ -130,6 +130,10 @@ func (a *App) writeRawMessageToMaildirFolder(ctx context.Context, messageID, fol
|
|||||||
if err := os.WriteFile(tmpPath, raw, 0o600); err != nil {
|
if err := os.WriteFile(tmpPath, raw, 0o600); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := applyMaildirOwnership(tmpPath); err != nil {
|
||||||
|
_ = os.Remove(tmpPath)
|
||||||
|
return err
|
||||||
|
}
|
||||||
if err := os.Rename(tmpPath, finalPath); err != nil {
|
if err := os.Rename(tmpPath, finalPath); err != nil {
|
||||||
_ = os.Remove(tmpPath)
|
_ = os.Remove(tmpPath)
|
||||||
return err
|
return err
|
||||||
@@ -213,7 +217,7 @@ func (a *App) moveMessageMaildir(ctx context.Context, messageID, targetFolderID
|
|||||||
}
|
}
|
||||||
base := filepath.Join(strings.TrimSpace(a.cfg.MaildirRoot), mb.Domain, mb.LocalPart, "Maildir")
|
base := filepath.Join(strings.TrimSpace(a.cfg.MaildirRoot), mb.Domain, mb.LocalPart, "Maildir")
|
||||||
folderBase := maildirFolderPath(base, folderName)
|
folderBase := maildirFolderPath(base, folderName)
|
||||||
if err := ensureMaildirFolderDirs(folderBase); err != nil {
|
if err := ensureMaildirFolderDirs(base, folderBase); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
subdir := "cur"
|
subdir := "cur"
|
||||||
@@ -225,6 +229,9 @@ func (a *App) moveMessageMaildir(ctx context.Context, messageID, targetFolderID
|
|||||||
if err := os.Rename(state.RawPath, targetPath); err != nil {
|
if err := os.Rename(state.RawPath, targetPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := applyMaildirOwnership(targetPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if state.FolderID != "" && state.FolderID != targetFolderID {
|
if state.FolderID != "" && state.FolderID != targetFolderID {
|
||||||
if _, err := a.bumpFolderModSeq(ctx, state.FolderID); err != nil {
|
if _, err := a.bumpFolderModSeq(ctx, state.FolderID); err != nil {
|
||||||
@@ -318,6 +325,9 @@ func (a *App) updateMessageMaildirFlags(ctx context.Context, messageID string, r
|
|||||||
if err := os.Rename(state.RawPath, targetPath); err != nil {
|
if err := os.Rename(state.RawPath, targetPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := applyMaildirOwnership(targetPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
modSeq, err := a.bumpFolderModSeq(ctx, state.FolderID)
|
modSeq, err := a.bumpFolderModSeq(ctx, state.FolderID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -481,15 +491,33 @@ func (a *App) pathIsUnderMaildirRoot(path string) (bool, error) {
|
|||||||
return rel != "." && !strings.HasPrefix(rel, ".."+string(filepath.Separator)) && rel != "..", nil
|
return rel != "." && !strings.HasPrefix(rel, ".."+string(filepath.Separator)) && rel != "..", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureMaildirFolderDirs(folderBase string) error {
|
func ensureMaildirFolderDirs(base, folderBase string) error {
|
||||||
for _, sub := range []string{"tmp", "new", "cur"} {
|
for _, sub := range []string{"tmp", "new", "cur"} {
|
||||||
if err := os.MkdirAll(filepath.Join(folderBase, sub), 0o755); err != nil {
|
if err := os.MkdirAll(filepath.Join(folderBase, sub), 0o755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, dir := range maildirOwnershipDirs(base, folderBase) {
|
||||||
|
if err := applyMaildirOwnership(dir); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func maildirOwnershipDirs(base, folderBase string) []string {
|
||||||
|
dirs := []string{
|
||||||
|
filepath.Dir(filepath.Dir(base)),
|
||||||
|
filepath.Dir(base),
|
||||||
|
base,
|
||||||
|
}
|
||||||
|
if filepath.Clean(folderBase) != filepath.Clean(base) {
|
||||||
|
dirs = append(dirs, folderBase)
|
||||||
|
}
|
||||||
|
dirs = append(dirs, filepath.Join(folderBase, "tmp"), filepath.Join(folderBase, "new"), filepath.Join(folderBase, "cur"))
|
||||||
|
return dirs
|
||||||
|
}
|
||||||
|
|
||||||
func maildirFilename(messageID, headerMessageID string) string {
|
func maildirFilename(messageID, headerMessageID string) string {
|
||||||
base := strings.TrimSpace(headerMessageID)
|
base := strings.TrimSpace(headerMessageID)
|
||||||
if base == "" {
|
if base == "" {
|
||||||
|
|||||||
Reference in New Issue
Block a user