feat(PROJ-56d): archivmail import um --tenant Flag erweitert
archivmail import --dir/--file ordnete importierte Mails bisher immer ohne Mandant zu (Save(..., nil) fest verdrahtet). Neuer --tenant <id> Flag übergibt die Tenant-ID an Store.Save() und an idxMgr.ForTenant(), sodass Mail sowohl in der DB als auch im richtigen Tenant-Suchindex landet — und automatisch die Retention-Regeln des Tenants greifen (applyRetention nutzt bereits die übergebene tenantID). Relevant für den geplanten Watch-Folder-Import pro Mandant. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
b3ff8e6cf9
commit
69c120a268
@@ -33,6 +33,7 @@ func runImport(args []string) {
|
||||
recursive := fs.Bool("recursive", false, "recurse into subdirectories (with --dir)")
|
||||
dryRun := fs.Bool("dry-run", false, "simulate import without saving")
|
||||
jsonOut := fs.Bool("json", false, "machine-readable JSON output")
|
||||
tenantFlag := fs.Int64("tenant", 0, "tenant ID to assign imported mails to (0 = none/global)")
|
||||
|
||||
fs.Usage = func() {
|
||||
fmt.Fprintln(os.Stderr, "Usage: archivmail import [flags]")
|
||||
@@ -161,6 +162,12 @@ func runImport(args []string) {
|
||||
}
|
||||
}
|
||||
|
||||
var tenantID *int64
|
||||
if *tenantFlag > 0 {
|
||||
tid := *tenantFlag
|
||||
tenantID = &tid
|
||||
}
|
||||
|
||||
imported := 0
|
||||
skipped := 0
|
||||
errors := 0
|
||||
@@ -186,7 +193,7 @@ func runImport(args []string) {
|
||||
|
||||
for _, msg := range messages {
|
||||
total++
|
||||
result := importMessage(mailStore, idxMgr, msg, *dryRun)
|
||||
result := importMessage(mailStore, idxMgr, msg, *dryRun, tenantID)
|
||||
switch result {
|
||||
case "imported":
|
||||
imported++
|
||||
@@ -226,7 +233,10 @@ func runImport(args []string) {
|
||||
}
|
||||
|
||||
// importMessage stores and indexes a single raw message. Returns "imported", "skipped", or "error".
|
||||
func importMessage(mailStore *storage.Store, idxMgr index.TenantIndexer, raw []byte, dryRun bool) string {
|
||||
// tenantID, when non-nil, assigns the imported mail to that tenant (both in
|
||||
// storage and in the tenant-specific search index) instead of the
|
||||
// global/tenant-less context.
|
||||
func importMessage(mailStore *storage.Store, idxMgr index.TenantIndexer, raw []byte, dryRun bool, tenantID *int64) string {
|
||||
pm, err := mailparser.Parse(raw)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "warning: parse failed: %v\n", err)
|
||||
@@ -237,7 +247,7 @@ func importMessage(mailStore *storage.Store, idxMgr index.TenantIndexer, raw []b
|
||||
return "imported"
|
||||
}
|
||||
|
||||
id, err := mailStore.Save(context.Background(), raw, pm.Date, nil)
|
||||
id, err := mailStore.Save(context.Background(), raw, pm.Date, tenantID)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "warning: save failed: %v\n", err)
|
||||
return "error"
|
||||
@@ -259,9 +269,10 @@ func importMessage(mailStore *storage.Store, idxMgr index.TenantIndexer, raw []b
|
||||
HasAttachment: len(pm.Attachments) > 0,
|
||||
Date: pm.Date,
|
||||
Size: int64(len(raw)),
|
||||
TenantID: tenantID,
|
||||
}
|
||||
|
||||
if err := idxMgr.ForTenant(nil).IndexSync(doc); err != nil {
|
||||
if err := idxMgr.ForTenant(tenantID).IndexSync(doc); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "warning: index failed for %s: %v\n", id, err)
|
||||
return "error"
|
||||
}
|
||||
@@ -299,6 +310,7 @@ archivmail import [flags]
|
||||
--file Einzelne EML- oder MBOX-Datei
|
||||
--dir Verzeichnis mit EML/MBOX-Dateien
|
||||
--recursive Unterverzeichnisse einschließen (mit --dir)
|
||||
--tenant Mandanten-ID für importierte Mails (0 = keine/global)
|
||||
--dry-run Simulation ohne Speichern
|
||||
--json Maschinenlesbare JSON-Ausgabe
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ func runPilerexportMethod(mailStore *storage.Store, idx index.TenantIndexer, bin
|
||||
return nil
|
||||
}
|
||||
total++
|
||||
result := importMessage(mailStore, idx, raw, dryRun)
|
||||
result := importMessage(mailStore, idx, raw, dryRun, nil)
|
||||
switch result {
|
||||
case "imported":
|
||||
imported++
|
||||
@@ -312,7 +312,7 @@ func runDirectMethod(mailStore *storage.Store, idx index.TenantIndexer, storeDir
|
||||
}
|
||||
|
||||
total++
|
||||
result := importMessage(mailStore, idx, emailRaw, dryRun)
|
||||
result := importMessage(mailStore, idx, emailRaw, dryRun, nil)
|
||||
switch result {
|
||||
case "imported":
|
||||
imported++
|
||||
|
||||
Reference in New Issue
Block a user