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:
redlineoandClaude Sonnet 5 committed 2026-07-24 09:51:52 +03:00
1 parent 7f0e0fdb23
commit 264ed74095
20 files changed
+756 -67

No files matched your search

@@ -12,7 +12,7 @@
<OutputType>Library</OutputType>
<RootNamespace>BulkArchiveMailer.AddIn</RootNamespace>
<AssemblyName>BulkArchiveMailer.AddIn</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{BAA0C2D2-18E2-41B9-852F-F413020CAA33};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<LangVersion>7.3</LangVersion>
@@ -25,19 +25,47 @@
<VSTOFrameworkVer40>true</VSTOFrameworkVer40>
<!--
Signing is deliberately OFF: this is an internal tool, sideloaded by
hand (see docs/BUILD.md) rather than published/ClickOnce/GPO
deployed, so there is no certificate to manage here. On first load
Outlook will show an "unable to verify publisher" style prompt for
the unsigned manifest - that's expected; docs/BUILD.md covers how to
either accept it or add a Trusted Location. Turning signing on for a
wider rollout is documented there as a follow-up, not implemented
here - a judgment call, since fabricating a certificate in an
environment with no Visual Studio/dotnet SDK to actually sign
anything would just be decoration.
Same MSBuild properties Visual Studio's Publish → Options dialog
writes here - without them ClickOnce falls back to the bare
assembly name ("BulkArchiveMailer.AddIn", from TargetName - see
Microsoft.VisualStudio.Tools.Office.targets'
"<ProductName Condition=... >$(TargetName)</ProductName>") both in
the install dialog and in Settings → Apps, which reads as
unfinished/unbranded to an operator installing this for the first
time. Property name is ProductName, NOT Product - Product is not a
recognized ClickOnce/VSTO manifest property and is silently ignored,
confirmed by grepping the generated .vsto after a real -t:Publish
(see deploy/publish-clickonce.ps1).
-->
<ProductName>BulkArchiveMailer — массовая рассылка архивов</ProductName>
<PublisherName>ssh-access-tui</PublisherName>
<!--
Corrected after the first real build against actual VSTO/MSBuild
tooling: unlike a plain ClickOnce EXE, a VSTO Office add-in's
"VisualStudioForApplicationsBuild" build step (Microsoft.VisualStudio.
Tools.Office.targets) unconditionally generates and signs a ClickOnce
application/deployment manifest even for local Debug builds -
SignManifests=false makes VerifyClickOnceSigningSettings fail the
build outright ("Cannot build because the ClickOnce manifest signing
option is not selected"). There is no way to opt out of this for an
Application-type VSTO project, so a throwaway self-signed "test"
certificate (BulkArchiveMailer.AddIn_TemporaryKey.pfx, no password,
not from a trusted CA) is checked into this folder purely to satisfy
that requirement - the same thing VS itself generates automatically
the first time you tick "Sign the ClickOnce manifests" in the
project's Signing property page. It does NOT make the add-in
"trusted": Outlook still shows an "unable to verify publisher"-style
prompt on first load because the certificate isn't from a trusted
root, same as before this fix - docs/BUILD.md still covers how to
accept that prompt or add a Trusted Location. Assembly strong-name
signing (SignAssembly) is a separate, unrelated concept and stays
off - nothing requires it.
-->
<SignAssembly>false</SignAssembly>
<SignManifests>false</SignManifests>
<SignManifests>true</SignManifests>
<ManifestKeyFile>BulkArchiveMailer.AddIn_TemporaryKey.pfx</ManifestKeyFile>
<ManifestCertificateThumbprint>9A9AF6F0E6EF09093910BD0FA2CCFFEC81F00E25</ManifestCertificateThumbprint>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@@ -95,6 +123,19 @@
<Reference Include="Microsoft.Office.Tools.Outlook, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
<!--
Microsoft.Office.Tools.Outlook.dll only exposes the OutlookAddIn
*interface* (FormRegion-related members). The real concrete base
class ThisAddIn derives from, Microsoft.Office.Tools.Outlook.
OutlookAddInBase, lives in this "Utilities" assembly instead - same
as the built-in "Outlook VSTO Add-in" project template, which also
references it with Private=True (runtime-only helper, not part of
the public design-time surface).
-->
<Reference Include="Microsoft.Office.Tools.Outlook.v4.0.Utilities, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.Office.Tools.v4.0.Framework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
</Reference>
@@ -111,6 +152,7 @@
<ItemGroup>
<Compile Include="Globals.cs" />
<Compile Include="MailSender.cs" />
<Compile Include="OutlookAccounts.cs" />
<Compile Include="RibbonController.cs" />
<Compile Include="SignatureReader.cs" />
<Compile Include="ThisAddIn.cs" />
@@ -136,6 +178,15 @@
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<!--
Test certificate for ClickOnce manifest signing only (see SignManifests
comment above) - no password. VSTO's ManageCertificateStore build task
picks up *.pfx files listed here and imports them into the current
user's certificate store (CurrentUser\My) if a certificate matching
ManifestCertificateThumbprint isn't already present, so a fresh clone
builds without any manual "import the cert" step.
-->
<None Include="BulkArchiveMailer.AddIn_TemporaryKey.pfx" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\OfficeTools\Microsoft.VisualStudio.Tools.Office.targets" Condition="'$(VSToolsPath)' != ''" />