Generalize mail templates from a fixed pair to an operator-managed list
ArchiveKind was a hardcoded two-value enum (ssh_access/config_update),
wired through FilenameParser's regex, MailTemplateSet's two fixed
slots, and SettingsForm's two fixed tabs. Operators wanted arbitrary
custom templates (own file-name suffix, subject, body) without a code
change per new archive kind ssh-access-tui might start producing.
Replaced with MailTemplateDefinition (DisplayName/FileSuffix/Subject/
BodyHtml) in an open-ended list: FilenameParser now accepts any
"{login}_{suffix}.7z" and ArchiveScanner matches the suffix against
the configured list; SendJob.Kind/SendLogEntry.Kind became plain
strings; SettingsForm gained a template list (+/- buttons, editor
panel) replacing the two static tabs. ssh_access/config_update are now
just the two default entries in that list, not special-cased.
Handles the two backward-compat edges that matter for a tool already
in real use: old config.json's object-shaped "templates" migrates to
the new list shape transparently on first load (DataContractJsonSerializer
turned out to silently produce an empty list rather than throw on the
old shape, so detection is structural, not exception-based), and old
send-log.csv rows with PascalCase Kind values (SshAccess/ConfigUpdate)
still dedupe correctly against the new snake_case suffixes.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cb3b273741
commit
804b9610ca
16 files changed
+904
-288
No files matched your search
+127
-109
@@ -16,8 +16,7 @@ namespace BulkArchiveMailer.AddIn.UI
|
||||
|
||||
private System.Windows.Forms.TabControl tabControl;
|
||||
private System.Windows.Forms.TabPage tabGeneral;
|
||||
private System.Windows.Forms.TabPage tabSshAccess;
|
||||
private System.Windows.Forms.TabPage tabConfigUpdate;
|
||||
private System.Windows.Forms.TabPage tabTemplates;
|
||||
|
||||
private System.Windows.Forms.Label lblArchiveFolder;
|
||||
private System.Windows.Forms.TextBox txtArchiveFolder;
|
||||
@@ -36,17 +35,20 @@ namespace BulkArchiveMailer.AddIn.UI
|
||||
private System.Windows.Forms.Label lblFromAccount;
|
||||
private System.Windows.Forms.ComboBox cboFromAccount;
|
||||
|
||||
private System.Windows.Forms.Label lblSshSubject;
|
||||
private System.Windows.Forms.TextBox txtSshSubject;
|
||||
private System.Windows.Forms.Label lblSshBody;
|
||||
private System.Windows.Forms.TextBox txtSshBody;
|
||||
private System.Windows.Forms.Label lblSshHint;
|
||||
private System.Windows.Forms.ListBox lstTemplates;
|
||||
private System.Windows.Forms.Button btnAddTemplate;
|
||||
private System.Windows.Forms.Button btnRemoveTemplate;
|
||||
|
||||
private System.Windows.Forms.Label lblCfgSubject;
|
||||
private System.Windows.Forms.TextBox txtCfgSubject;
|
||||
private System.Windows.Forms.Label lblCfgBody;
|
||||
private System.Windows.Forms.TextBox txtCfgBody;
|
||||
private System.Windows.Forms.Label lblCfgHint;
|
||||
private System.Windows.Forms.Label lblTplDisplayName;
|
||||
private System.Windows.Forms.TextBox txtTplDisplayName;
|
||||
private System.Windows.Forms.Label lblTplFileSuffix;
|
||||
private System.Windows.Forms.TextBox txtTplFileSuffix;
|
||||
private System.Windows.Forms.Label lblTplFileSuffixHint;
|
||||
private System.Windows.Forms.Label lblTplSubject;
|
||||
private System.Windows.Forms.TextBox txtTplSubject;
|
||||
private System.Windows.Forms.Label lblTplBody;
|
||||
private System.Windows.Forms.TextBox txtTplBody;
|
||||
private System.Windows.Forms.Label lblTplHint;
|
||||
|
||||
private System.Windows.Forms.Button btnSave;
|
||||
private System.Windows.Forms.Button btnCancel;
|
||||
@@ -56,8 +58,7 @@ namespace BulkArchiveMailer.AddIn.UI
|
||||
{
|
||||
this.tabControl = new System.Windows.Forms.TabControl();
|
||||
this.tabGeneral = new System.Windows.Forms.TabPage();
|
||||
this.tabSshAccess = new System.Windows.Forms.TabPage();
|
||||
this.tabConfigUpdate = new System.Windows.Forms.TabPage();
|
||||
this.tabTemplates = new System.Windows.Forms.TabPage();
|
||||
|
||||
this.lblArchiveFolder = new System.Windows.Forms.Label();
|
||||
this.txtArchiveFolder = new System.Windows.Forms.TextBox();
|
||||
@@ -76,17 +77,20 @@ namespace BulkArchiveMailer.AddIn.UI
|
||||
this.lblFromAccount = new System.Windows.Forms.Label();
|
||||
this.cboFromAccount = new System.Windows.Forms.ComboBox();
|
||||
|
||||
this.lblSshSubject = new System.Windows.Forms.Label();
|
||||
this.txtSshSubject = new System.Windows.Forms.TextBox();
|
||||
this.lblSshBody = new System.Windows.Forms.Label();
|
||||
this.txtSshBody = new System.Windows.Forms.TextBox();
|
||||
this.lblSshHint = new System.Windows.Forms.Label();
|
||||
this.lstTemplates = new System.Windows.Forms.ListBox();
|
||||
this.btnAddTemplate = new System.Windows.Forms.Button();
|
||||
this.btnRemoveTemplate = new System.Windows.Forms.Button();
|
||||
|
||||
this.lblCfgSubject = new System.Windows.Forms.Label();
|
||||
this.txtCfgSubject = new System.Windows.Forms.TextBox();
|
||||
this.lblCfgBody = new System.Windows.Forms.Label();
|
||||
this.txtCfgBody = new System.Windows.Forms.TextBox();
|
||||
this.lblCfgHint = new System.Windows.Forms.Label();
|
||||
this.lblTplDisplayName = new System.Windows.Forms.Label();
|
||||
this.txtTplDisplayName = new System.Windows.Forms.TextBox();
|
||||
this.lblTplFileSuffix = new System.Windows.Forms.Label();
|
||||
this.txtTplFileSuffix = new System.Windows.Forms.TextBox();
|
||||
this.lblTplFileSuffixHint = new System.Windows.Forms.Label();
|
||||
this.lblTplSubject = new System.Windows.Forms.Label();
|
||||
this.txtTplSubject = new System.Windows.Forms.TextBox();
|
||||
this.lblTplBody = new System.Windows.Forms.Label();
|
||||
this.txtTplBody = new System.Windows.Forms.TextBox();
|
||||
this.lblTplHint = new System.Windows.Forms.Label();
|
||||
|
||||
this.btnSave = new System.Windows.Forms.Button();
|
||||
this.btnCancel = new System.Windows.Forms.Button();
|
||||
@@ -94,8 +98,7 @@ namespace BulkArchiveMailer.AddIn.UI
|
||||
|
||||
this.tabControl.SuspendLayout();
|
||||
this.tabGeneral.SuspendLayout();
|
||||
this.tabSshAccess.SuspendLayout();
|
||||
this.tabConfigUpdate.SuspendLayout();
|
||||
this.tabTemplates.SuspendLayout();
|
||||
this.SuspendLayout();
|
||||
|
||||
//
|
||||
@@ -108,8 +111,7 @@ namespace BulkArchiveMailer.AddIn.UI
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
this.tabControl.TabPages.AddRange(new System.Windows.Forms.TabPage[] {
|
||||
this.tabGeneral,
|
||||
this.tabSshAccess,
|
||||
this.tabConfigUpdate});
|
||||
this.tabTemplates});
|
||||
|
||||
//
|
||||
// tabGeneral
|
||||
@@ -195,97 +197,115 @@ namespace BulkArchiveMailer.AddIn.UI
|
||||
this.cboFromAccount.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
|
||||
//
|
||||
// tabSshAccess
|
||||
// tabTemplates
|
||||
//
|
||||
this.tabSshAccess.Text = "Шаблон: новый доступ";
|
||||
this.tabSshAccess.Padding = new System.Windows.Forms.Padding(12);
|
||||
this.tabSshAccess.UseVisualStyleBackColor = true;
|
||||
this.tabSshAccess.Controls.Add(this.lblSshSubject);
|
||||
this.tabSshAccess.Controls.Add(this.txtSshSubject);
|
||||
this.tabSshAccess.Controls.Add(this.lblSshBody);
|
||||
this.tabSshAccess.Controls.Add(this.txtSshBody);
|
||||
this.tabSshAccess.Controls.Add(this.lblSshHint);
|
||||
this.tabTemplates.Text = "Шаблоны";
|
||||
this.tabTemplates.Padding = new System.Windows.Forms.Padding(12);
|
||||
this.tabTemplates.UseVisualStyleBackColor = true;
|
||||
this.tabTemplates.Controls.Add(this.lstTemplates);
|
||||
this.tabTemplates.Controls.Add(this.btnAddTemplate);
|
||||
this.tabTemplates.Controls.Add(this.btnRemoveTemplate);
|
||||
this.tabTemplates.Controls.Add(this.lblTplDisplayName);
|
||||
this.tabTemplates.Controls.Add(this.txtTplDisplayName);
|
||||
this.tabTemplates.Controls.Add(this.lblTplFileSuffix);
|
||||
this.tabTemplates.Controls.Add(this.txtTplFileSuffix);
|
||||
this.tabTemplates.Controls.Add(this.lblTplFileSuffixHint);
|
||||
this.tabTemplates.Controls.Add(this.lblTplSubject);
|
||||
this.tabTemplates.Controls.Add(this.txtTplSubject);
|
||||
this.tabTemplates.Controls.Add(this.lblTplBody);
|
||||
this.tabTemplates.Controls.Add(this.txtTplBody);
|
||||
this.tabTemplates.Controls.Add(this.lblTplHint);
|
||||
|
||||
// lblSshSubject
|
||||
this.lblSshSubject.Location = new System.Drawing.Point(15, 20);
|
||||
this.lblSshSubject.Size = new System.Drawing.Size(200, 20);
|
||||
this.lblSshSubject.Text = "Тема письма:";
|
||||
// lstTemplates
|
||||
this.lstTemplates.Location = new System.Drawing.Point(15, 20);
|
||||
this.lstTemplates.Size = new System.Drawing.Size(190, 329);
|
||||
this.lstTemplates.IntegralHeight = false;
|
||||
this.lstTemplates.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.lstTemplates.SelectedIndexChanged += new System.EventHandler(this.lstTemplates_SelectedIndexChanged);
|
||||
|
||||
// txtSshSubject
|
||||
this.txtSshSubject.Location = new System.Drawing.Point(15, 43);
|
||||
this.txtSshSubject.Size = new System.Drawing.Size(610, 23);
|
||||
// btnAddTemplate
|
||||
this.btnAddTemplate.Location = new System.Drawing.Point(15, 355);
|
||||
this.btnAddTemplate.Size = new System.Drawing.Size(90, 27);
|
||||
this.btnAddTemplate.Text = "+ Добавить";
|
||||
this.btnAddTemplate.UseVisualStyleBackColor = true;
|
||||
this.btnAddTemplate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnAddTemplate.Click += new System.EventHandler(this.btnAddTemplate_Click);
|
||||
|
||||
// lblSshBody
|
||||
this.lblSshBody.Location = new System.Drawing.Point(15, 78);
|
||||
this.lblSshBody.Size = new System.Drawing.Size(200, 20);
|
||||
this.lblSshBody.Text = "Тело письма (HTML):";
|
||||
// btnRemoveTemplate
|
||||
this.btnRemoveTemplate.Location = new System.Drawing.Point(115, 355);
|
||||
this.btnRemoveTemplate.Size = new System.Drawing.Size(90, 27);
|
||||
this.btnRemoveTemplate.Text = "Удалить";
|
||||
this.btnRemoveTemplate.UseVisualStyleBackColor = true;
|
||||
this.btnRemoveTemplate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnRemoveTemplate.Click += new System.EventHandler(this.btnRemoveTemplate_Click);
|
||||
|
||||
// txtSshBody
|
||||
this.txtSshBody.Location = new System.Drawing.Point(15, 101);
|
||||
this.txtSshBody.Size = new System.Drawing.Size(610, 300);
|
||||
this.txtSshBody.Multiline = true;
|
||||
this.txtSshBody.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtSshBody.AcceptsReturn = true;
|
||||
this.txtSshBody.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
// lblTplDisplayName
|
||||
this.lblTplDisplayName.Location = new System.Drawing.Point(220, 20);
|
||||
this.lblTplDisplayName.Size = new System.Drawing.Size(200, 20);
|
||||
this.lblTplDisplayName.Text = "Название:";
|
||||
|
||||
// txtTplDisplayName
|
||||
this.txtTplDisplayName.Location = new System.Drawing.Point(220, 43);
|
||||
this.txtTplDisplayName.Size = new System.Drawing.Size(410, 23);
|
||||
this.txtTplDisplayName.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right));
|
||||
this.txtTplDisplayName.Leave += new System.EventHandler(this.txtTplDisplayName_Leave);
|
||||
|
||||
// lblTplFileSuffix
|
||||
this.lblTplFileSuffix.Location = new System.Drawing.Point(220, 78);
|
||||
this.lblTplFileSuffix.Size = new System.Drawing.Size(200, 20);
|
||||
this.lblTplFileSuffix.Text = "Суффикс файла:";
|
||||
|
||||
// txtTplFileSuffix
|
||||
this.txtTplFileSuffix.Location = new System.Drawing.Point(220, 101);
|
||||
this.txtTplFileSuffix.Size = new System.Drawing.Size(200, 23);
|
||||
|
||||
// lblTplFileSuffixHint
|
||||
this.lblTplFileSuffixHint.Location = new System.Drawing.Point(220, 127);
|
||||
this.lblTplFileSuffixHint.Size = new System.Drawing.Size(410, 20);
|
||||
this.lblTplFileSuffixHint.Text = "Файл: {login}_<суффикс>.7z";
|
||||
this.lblTplFileSuffixHint.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
|
||||
// lblTplSubject
|
||||
this.lblTplSubject.Location = new System.Drawing.Point(220, 160);
|
||||
this.lblTplSubject.Size = new System.Drawing.Size(200, 20);
|
||||
this.lblTplSubject.Text = "Тема письма:";
|
||||
|
||||
// txtTplSubject
|
||||
this.txtTplSubject.Location = new System.Drawing.Point(220, 183);
|
||||
this.txtTplSubject.Size = new System.Drawing.Size(410, 23);
|
||||
this.txtTplSubject.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right));
|
||||
|
||||
// lblTplBody
|
||||
this.lblTplBody.Location = new System.Drawing.Point(220, 218);
|
||||
this.lblTplBody.Size = new System.Drawing.Size(200, 20);
|
||||
this.lblTplBody.Text = "Тело письма (HTML):";
|
||||
|
||||
// txtTplBody
|
||||
this.txtTplBody.Location = new System.Drawing.Point(220, 241);
|
||||
this.txtTplBody.Size = new System.Drawing.Size(410, 160);
|
||||
this.txtTplBody.Multiline = true;
|
||||
this.txtTplBody.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtTplBody.AcceptsReturn = true;
|
||||
this.txtTplBody.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
|
||||
// lblSshHint
|
||||
this.lblSshHint.Location = new System.Drawing.Point(15, 408);
|
||||
this.lblSshHint.Size = new System.Drawing.Size(610, 20);
|
||||
this.lblSshHint.Text = "Доступные плейсхолдеры: {Login}, {Email}, {Date}";
|
||||
this.lblSshHint.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.lblSshHint.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
|
||||
//
|
||||
// tabConfigUpdate
|
||||
//
|
||||
this.tabConfigUpdate.Text = "Шаблон: обновление конфига";
|
||||
this.tabConfigUpdate.Padding = new System.Windows.Forms.Padding(12);
|
||||
this.tabConfigUpdate.UseVisualStyleBackColor = true;
|
||||
this.tabConfigUpdate.Controls.Add(this.lblCfgSubject);
|
||||
this.tabConfigUpdate.Controls.Add(this.txtCfgSubject);
|
||||
this.tabConfigUpdate.Controls.Add(this.lblCfgBody);
|
||||
this.tabConfigUpdate.Controls.Add(this.txtCfgBody);
|
||||
this.tabConfigUpdate.Controls.Add(this.lblCfgHint);
|
||||
|
||||
// lblCfgSubject
|
||||
this.lblCfgSubject.Location = new System.Drawing.Point(15, 20);
|
||||
this.lblCfgSubject.Size = new System.Drawing.Size(200, 20);
|
||||
this.lblCfgSubject.Text = "Тема письма:";
|
||||
|
||||
// txtCfgSubject
|
||||
this.txtCfgSubject.Location = new System.Drawing.Point(15, 43);
|
||||
this.txtCfgSubject.Size = new System.Drawing.Size(610, 23);
|
||||
|
||||
// lblCfgBody
|
||||
this.lblCfgBody.Location = new System.Drawing.Point(15, 78);
|
||||
this.lblCfgBody.Size = new System.Drawing.Size(200, 20);
|
||||
this.lblCfgBody.Text = "Тело письма (HTML):";
|
||||
|
||||
// txtCfgBody
|
||||
this.txtCfgBody.Location = new System.Drawing.Point(15, 101);
|
||||
this.txtCfgBody.Size = new System.Drawing.Size(610, 300);
|
||||
this.txtCfgBody.Multiline = true;
|
||||
this.txtCfgBody.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
|
||||
this.txtCfgBody.AcceptsReturn = true;
|
||||
this.txtCfgBody.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
||||
| System.Windows.Forms.AnchorStyles.Left)
|
||||
| System.Windows.Forms.AnchorStyles.Right)));
|
||||
|
||||
// lblCfgHint
|
||||
this.lblCfgHint.Location = new System.Drawing.Point(15, 408);
|
||||
this.lblCfgHint.Size = new System.Drawing.Size(610, 20);
|
||||
this.lblCfgHint.Text = "Доступные плейсхолдеры: {Login}, {Email}, {Date}";
|
||||
this.lblCfgHint.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.lblCfgHint.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
// lblTplHint
|
||||
this.lblTplHint.Location = new System.Drawing.Point(220, 408);
|
||||
this.lblTplHint.Size = new System.Drawing.Size(410, 20);
|
||||
this.lblTplHint.Text = "Доступные плейсхолдеры: {Login}, {Email}, {Date}";
|
||||
this.lblTplHint.ForeColor = System.Drawing.SystemColors.GrayText;
|
||||
this.lblTplHint.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
|
||||
//
|
||||
// btnSave / btnCancel / btnResetDefaults
|
||||
//
|
||||
this.btnResetDefaults.Location = new System.Drawing.Point(12, 494);
|
||||
this.btnResetDefaults.Size = new System.Drawing.Size(220, 30);
|
||||
this.btnResetDefaults.Text = "Сбросить домен/шаблоны по умолчанию";
|
||||
this.btnResetDefaults.Text = "Сбросить шаблоны по умолчанию";
|
||||
this.btnResetDefaults.UseVisualStyleBackColor = true;
|
||||
this.btnResetDefaults.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
|
||||
this.btnResetDefaults.Click += new System.EventHandler(this.btnResetDefaults_Click);
|
||||
@@ -326,10 +346,8 @@ namespace BulkArchiveMailer.AddIn.UI
|
||||
this.tabControl.ResumeLayout(false);
|
||||
this.tabGeneral.ResumeLayout(false);
|
||||
this.tabGeneral.PerformLayout();
|
||||
this.tabSshAccess.ResumeLayout(false);
|
||||
this.tabSshAccess.PerformLayout();
|
||||
this.tabConfigUpdate.ResumeLayout(false);
|
||||
this.tabConfigUpdate.PerformLayout();
|
||||
this.tabTemplates.ResumeLayout(false);
|
||||
this.tabTemplates.PerformLayout();
|
||||
this.ResumeLayout(false);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user