Fix first real VSTO build, add sender account selection, polish deploy
First live build against real Visual Studio/VSTO tooling surfaced two issues in the hand-written AddIn scaffold: ThisAddIn derived from the wrong base type (OutlookAddIn is an interface, not the concrete OutlookAddInBase class), and VSTO Application projects cannot build without a signed ClickOnce manifest, so SignManifests is now on with a throwaway self-signed test certificate. Both Core/Core.Tests/AddIn now build clean and Core.Tests passes. Also: mail always sent from Outlook's default account with no way to pick a different one (e.g. a shared mailbox) - added a "From account" setting (Session.Accounts dropdown in SettingsForm, SendUsingAccount in MailSender). And added deploy/ with both a local ClickOnce publish script (real install/uninstall via Windows Apps, no manual registry editing) and a manual registry sideload fallback for scripted rollouts. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7f0e0fdb23
commit
264ed74095
20 files changed
+756
-67
No files matched your search
@@ -0,0 +1,73 @@
|
||||
using System.Reflection;
|
||||
using BulkArchiveMailer.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace BulkArchiveMailer.Core.Tests
|
||||
{
|
||||
/// <summary>
|
||||
/// Covers the one AppSettingsData behavior that's easy to silently
|
||||
/// break when adding a field: loading a config.json written before
|
||||
/// FromAccountSmtpAddress existed must not throw, and a non-empty
|
||||
/// value must round-trip once the operator picks a "from" account in
|
||||
/// SettingsForm.
|
||||
///
|
||||
/// Note the old-JSON case asserts null, not "": DataContractJsonSerializer
|
||||
/// builds the target via FormatterServices.GetUninitializedObject,
|
||||
/// which skips this property's "" initializer entirely for any member
|
||||
/// absent from the source JSON, leaving the CLR default (null) - see
|
||||
/// the long comment on AppSettingsData.FromAccountSmtpAddress. Every
|
||||
/// call site (MailSender, SettingsForm) already treats null the same
|
||||
/// as "" for this reason.
|
||||
///
|
||||
/// Goes through AppSettings' private Serialize/Deserialize via
|
||||
/// reflection rather than Load()/Save(), so this test never touches
|
||||
/// the real %APPDATA%\BulkArchiveMailer\config.json on the machine
|
||||
/// running it.
|
||||
/// </summary>
|
||||
public class AppSettingsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Deserialize_OldJsonWithoutFromAccountField_DoesNotThrowAndTreatsAsUnset()
|
||||
{
|
||||
const string oldJson = @"{
|
||||
""archiveFolder"": ""C:\\archives"",
|
||||
""emailDomain"": ""redlab.lo"",
|
||||
""testModeDefault"": true,
|
||||
""signatureHtmlPath"": """"
|
||||
}";
|
||||
|
||||
var settings = InvokeDeserialize(oldJson);
|
||||
|
||||
Assert.True(string.IsNullOrEmpty(settings.FromAccountSmtpAddress));
|
||||
Assert.Equal("redlab.lo", settings.EmailDomain);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SerializeThenDeserialize_RoundTripsFromAccountSmtpAddress()
|
||||
{
|
||||
var data = new AppSettingsData
|
||||
{
|
||||
ArchiveFolder = "C:\\archives",
|
||||
EmailDomain = "redlab.lo",
|
||||
FromAccountSmtpAddress = "svc-mailer@redlab.lo",
|
||||
};
|
||||
|
||||
var json = InvokeSerialize(data);
|
||||
var roundTripped = InvokeDeserialize(json);
|
||||
|
||||
Assert.Equal("svc-mailer@redlab.lo", roundTripped.FromAccountSmtpAddress);
|
||||
}
|
||||
|
||||
private static AppSettingsData InvokeDeserialize(string json)
|
||||
{
|
||||
var method = typeof(AppSettings).GetMethod("Deserialize", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
return (AppSettingsData)method.Invoke(null, new object[] { json });
|
||||
}
|
||||
|
||||
private static string InvokeSerialize(AppSettingsData data)
|
||||
{
|
||||
var method = typeof(AppSettings).GetMethod("Serialize", BindingFlags.NonPublic | BindingFlags.Static);
|
||||
return (string)method.Invoke(null, new object[] { data });
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user