Build Your Own WiseStamp Replacement: Brand Email Signatures on Every Device with Microsoft 365
How we replaced a paid signature service with a PowerShell-set mailbox signature, an event-based Outlook add-in and a mail-flow rule. The steps, the code, and the three places we lost time.
Every small business hits the same moment. The team is emailing customers and partners from three or four devices, and every message signs off differently. One phone still says "Get Outlook for iOS." One desktop has a logo from two rebrands ago.
The fix everyone reaches for is a subscription service like WiseStamp or Exclaimer. Those work, but they charge per user, per month, forever, for something Microsoft 365 already knows how to do. This is how we built the same thing ourselves in a day, what actually made it work, and the three places we lost time so you don't have to.
This is a technical how-to for a Microsoft 365 tenant. You'll need Global Administrator rights, a place to host a few static files over HTTPS, and about an hour of hands-on time, plus up to a day of waiting for Microsoft to roll out the add-in.
What the paid products actually do
Strip away the editor and the analytics, and a signature service is three mechanisms glued together.
- A mailbox signature. Exchange Online stores a signature on each mailbox. Outlook on the web and the new Outlook for Windows read it directly, and you can write it from PowerShell.
- An Outlook add-in. A small, admin-deployed add-in runs the moment a compose window opens and inserts the signature. This is the piece that reaches classic Outlook, Mac, and the phone apps.
- A mail-flow rule. Exchange appends a signature to outbound mail on the server, so a message sent from Apple Mail or a Gmail app still leaves the company signed.
Each layer covers a gap in the others, and each has a catch. We ended up using all three. Here they are in the order we recommend building them, which isn't the order we built them.
Step 1: Design one signature and generate the rest
Email clients are hostile to layout. Word-based Outlook ignores most modern CSS, Gmail strips style blocks, and dark mode inverts colors you didn't expect it to. A signature that survives all of that follows a few rules:
- Build it with nested tables and inline styles only. No flexbox, no grid, no external stylesheet.
- Host images on a public HTTPS URL and size them at two or three times their display size so they stay sharp on retina screens. Transparent PNGs sit correctly on both light and dark backgrounds.
- Declare a font stack that ends in a system font. Your brand face will render for almost nobody, so the layout has to look right in Segoe UI, Helvetica and Arial.
- Keep the whole block under about 520 pixels wide so it fits a phone screen.
- Put each label and its value in separate table cells. Our first version used a styled span for the "M", "E" and "W" labels, and Outlook on the web quietly turned each one into its own line. Cells never break.
- Include a unique marker string, such as
sig-marker-v1, somewhere in the signature's text. The mail-flow rule in step 4 uses it to tell whether a message already carries a signature. Keep it visually unobtrusive, and test that the rule really sees it before you rely on it.
Rather than hand-editing HTML for each person, keep one template and a small roster file (name, title, mobile, email, LinkedIn) and generate each person's block from it. Ours is a 90-line Node script. Changing a title becomes a one-line edit and one command, which is the part of WiseStamp people actually pay for.
Step 2: Set the mailbox signature from PowerShell
This layer covers Outlook on the web and the new Outlook for Windows, which share settings, and it's the one you can get working in ten minutes. Install the Exchange Online module and connect:
Install-Module ExchangeOnlineManagement -Scope CurrentUser
Connect-ExchangeOnline -Device
Then, for each mailbox, write the HTML and turn on automatic insertion:
$html = Get-Content -Raw .\trey.html
$text = Get-Content -Raw .\trey.txt
Set-MailboxMessageConfiguration -Identity [email protected] `
-SignatureHtml $html -SignatureText $text -SignatureName 'Company' `
-AutoAddSignature $true -AutoAddSignatureOnReply $true
Gotcha 1: roaming signatures
Here's the first place we lost time. Outlook's roaming signatures feature, rolled out from 2022, stores signatures in the cloud per user. While it's on, the signature parameters of that command simply don't apply. Nothing errors; the signature just never appears. Microsoft's own documentation for the cmdlet points to the fix, an organization-level switch:
Set-OrganizationConfig -PostponeRoamingSignaturesUntilLater $true
After that, refresh Outlook on the web and the signature is there, already selected for new messages and replies. As the name suggests, Microsoft treats this as a postponement rather than a permanent setting, so check it again if signatures stop appearing after a future change.
The switch affects only Outlook on the web and the new Outlook for Windows. Classic Outlook and the phone apps keep their own local signatures regardless, which is why the next layer exists.
Step 3: Deploy an event-based Outlook add-in
Outlook add-ins can register for an event that fires when a new message, reply or forward opens (OnNewMessageCompose). The handler is a few dozen lines of JavaScript: read the sender's address, fetch that person's signature from your hosted roster, and call Office.context.mailbox.item.body.setSignatureAsync. Microsoft publishes a working sample called outlook-set-signature that's a fine starting point. You host the manifest, the script and a couple of icons on any HTTPS site; ours live in a folder on our own domain.
Four things about the manifest that are easy to get wrong:
- Use the add-in only (XML) manifest if you want the phones covered. Add-ins built on the newer unified manifest don't run on Outlook for Mac or mobile, and the mobile apps need their own launch-event entry in the manifest.
- It needs both a JavaScript runtime override, because classic Outlook on Windows runs event handlers in a JavaScript-only runtime, and an HTML page that loads the same script for every other client.
- Give it at least one visible command, such as an "Insert signature" button on the compose ribbon. An add-in with only a background event doesn't show anywhere in the apps list, so nobody can tell whether it's installed.
- If your site sends
X-Frame-Options: DENY, exempt the add-in's folder. Outlook loads those pages inside its own frames.
Gotcha 2: where you deploy it
Here's the second place we lost time. Exchange has an older organization app store, reachable from PowerShell with New-App -OrganizationApp, and it will happily install an add-in that way. But event-based add-ins only launch automatically when an administrator deploys them from the Microsoft 365 admin center: Settings, Integrated apps, Upload custom apps, app type Office Add-in, then upload the manifest file. Microsoft's documentation says this in one line, and there's no simple scripted equivalent, so a person has to click through it.
Assign it to the entire organization and give Microsoft time: new deployments can take up to 24 hours to reach every mailbox. Plan for one more thing: once an event-based add-in is admin-deployed, every later change to its manifest needs an administrator to accept the update in the admin center before people can use it again.
Once it lands, the add-in inserts the signature above your reply text in Outlook on the web, the new and classic Outlook for Windows, the new Outlook for Mac, and the Outlook apps for iOS and Android. That's the behavior people mean when they say "like WiseStamp."
Step 4: Add the server-side fallback
Mail that never touches Outlook still leaves your domain: a reply from Apple Mail, or a message from a phone's built-in mail app. A mail-flow rule catches those. It appends an HTML disclaimer to outbound external mail, and the disclaimer can use directory placeholders, so one rule serves everyone:
New-TransportRule -Name 'Signature fallback' `
-FromScope InOrganization -SentToScope NotInOrganization `
-ExceptIfSubjectOrBodyContainsWords 'sig-marker-v1' `
-ApplyHtmlDisclaimerLocation Append `
-ApplyHtmlDisclaimerText (Get-Content -Raw .\rule.html) `
-ApplyHtmlDisclaimerFallbackAction Wrap
Inside rule.html, write %%DisplayName%%, %%Title%%, %%MobileNumber%% and %%Email%% where the person's details go. Exchange fills them from the user's directory profile at send time, which means titles and phone numbers have to be on the Microsoft 365 user accounts. That's good discipline anyway.
The exception clause uses the marker from step 1. If the add-in or the mailbox signature already put a signature in the message, the rule leaves it alone. Without that, people get two.
The rule has one limit worth knowing: it can only append at the very bottom of the message, below any quoted thread, and the sender doesn't see it while typing. That's why it's the fallback and not the primary.
Shared mailboxes
A support@ or info@ shared mailbox takes a mailbox signature exactly like a person does, so run the step 2 command against it with a team version of the template (name "Company Support", no mobile line). Give the shared mailbox a display name and a title in the directory as well, so the fallback rule fills its placeholders sensibly when someone sends as it from a phone.
Gotcha 3: local signatures on the phone
Outlook for iOS and Android ship with a default signature, and any signature typed into the app stays there. Until the add-in arrives, a message from the phone shows the local one plus the server-appended one. Clear the local signature in the app's settings on every device, once.
What it costs, and what it doesn't do
Hosting three small files and two images on a site you already run is effectively free, and there's no per-user charge. What you give up compared to a paid product is the point-and-click editor, campaign banners that rotate on a schedule, and click analytics. If nobody at your company was going to use those, you've just saved the subscription.
Our next step is a small admin page where anyone with the right role can edit the roster and republish. That would close the last gap with the paid tools without the per-seat bill.
If the mechanics of a Microsoft 365 tenant aren't how you want to spend a Saturday, the fully managed products remain a reasonable buy. But the machinery underneath them is yours already, and it's less mysterious than the pricing pages suggest.
Outgrown your technology?
Tell me what's going on. I read every message personally and usually reply within a day.