Administrator guide: Ascripto and Microsoft 365
Last reviewed 19 October 2026
For the Global Administrator, Exchange Administrator or IT provider who has been asked to connect Microsoft 365 or to change mail flow, and for anyone evaluating what Ascripto does to a message.
The Entra application
One multi-tenant application registration, Ascripto, publisher domain ascripto.com. A customer sees one enterprise application in the Microsoft Entra admin center.
| Permission | Type | Asked when | Used for |
|---|---|---|---|
openid, profile, email | delegated | sign-in | who is signing in; identity keyed on the account’s object id and tenant id, never the email |
Microsoft Graph User.Read.All | application | Connect Microsoft 365 (admin consent) | the directory reader: users, with delta queries for changes |
Microsoft Graph Domain.Read.All | application | the same consent | the organisation’s verified domains: the proof that a domain routed through the relay is yours |
Office 365 Exchange Online Exchange.Manage (Manage Exchange As Signed-in User) | delegated | Set it up for me only | letting Ascripto create the connectors and the rule on that one occasion |
Group.Read.All is not asked for; nothing reads groups. Application permissions are authenticated by certificate, not a client secret.
Who can consent. Admin consent for the directory needs a Global Administrator or Privileged Role Administrator; Ascripto checks the sign-in’s directory roles before sending anyone to Microsoft’s consent screen, and tells a non-administrator who can do it instead. Set it up for me needs a Global Administrator or Exchange Administrator; Exchange applies its own role-based access control as well.
Publisher verification is in progress (Partner Center enrolment started 2026-10-15). Until it completes, Microsoft’s consent screen shows unverified, and a non-administrator cannot consent even to sign in without an administrator’s approval. Start with an administrator.
Directory sync
Changes are read every minute (Microsoft Graph’s delta query) and the whole directory once a day, or now from Settings → Connections. Unlicensed users appear and cost nothing. A user who disappears goes to Ascripto’s recycle bin (7 days by default, settable to a year) and returns as the same record if seen again.
Mail flow: the loop-back relay
Microsoft Graph cannot manage Outlook signatures, Exchange Web Services is being disabled in phases from October 2026 to April 2027, and transport-rule disclaimers cannot carry images or sit under the latest reply. Ascripto therefore signs in transit:
sender ─▶ Exchange Online ──(outbound connector)──▶ Ascripto relay
│ inserts the signature
Exchange Online ◀──(inbound connector)─────┘
│
└─▶ delivers to the recipient as it does today
The message leaves your tenant and comes straight back. Consequences worth stating to whoever owns your mail:
- MX records, inbound mail and SPF are untouched. The last hop to the recipient is Exchange Online’s own IP, so SPF and DMARC evaluate exactly as before.
- Outgoing only, and only for the domains you add in Settings → Delivery, which must be verified in your tenant (Ascripto reads them from Graph).
- Both legs are SMTP on port 25 with TLS required. Ascripto is identified to your tenant by certificate, never by IP, so a change on Ascripto’s side never needs a change in your tenant.
- Relay hosts:
eu1.relay.ascripto.com(primary) andeu2.relay.ascripto.com(standby), both under the*.relay.ascripto.comcertificate. Hosted on Microsoft Azure in Germany West Central.
What the setup creates
Both routes (Set it up for me and the script) create the same three objects from the same description, and both are idempotent: an existing object is updated, not duplicated.
Inbound connector Ascripto inbound: type on-premises, enabled, RequireTls, accepting mail whose TLS client certificate is *.relay.ascripto.com, for any sender domain (RestrictDomainsToCertificate false), CloudServicesMailEnabled so Exchange treats the returning message as its own and keeps the original headers.
Outbound connector Ascripto outbound: type on-premises, enabled, scoped to the transport rule (IsTransportRuleScoped), smart hosts eu1.relay.ascripto.com and eu2.relay.ascripto.com, TlsSettings DomainValidation with TlsDomain *.relay.ascripto.com, UseMxRecord false, RouteAllMessagesViaOnPremises false.
Mail flow rule Ascripto signatures, priority 0, mode Enforce, RuleErrorAction Ignore:
| Condition / exception | Value | Why |
|---|---|---|
| sender’s address domain is | your routed domains, matched on the envelope | only your domains' mail |
| sender is | inside the organisation | never relay inbound or external mail |
except if the header X-Ascripto-Relayed matches | . | the relay adds this header; without the exception the message would loop |
| except if the sender address matches | <> and Return-Path contains <> | bounces have no signature |
| except if the message type is | Calendaring | invitations are left alone |
| action | route via Ascripto outbound |
The script (relay-setup.ps1, shown step by step on the Delivery page) installs the ExchangeOnlineManagement module if missing, runs Connect-ExchangeOnline, then Get- / Set- or New- each object and Enable-TransportRule. It runs in Windows PowerShell 5.1 or PowerShell 7. Set it up for me runs the same cmdlets through Exchange’s admin endpoint with a delegated token that lives in the request’s memory for about an hour and is never written anywhere: not the database, not a cookie, not a log.
The check
Ascripto cannot read your Exchange configuration. The check script runs Get-InboundConnector, Get-OutboundConnector and Get-TransportRule for the three names and writes ascripto-check.json; uploading it on the Delivery page compares each setting with what the setup sets and lists any difference by name and value. The file is compared and discarded. The domain row’s mail-flow probe is the other half: Last mail 2 minutes ago · 14 in the last 24 hours, or No mail from it has reached Ascripto in N days.
What the relay does to a message
Per recipient (the relay handles one recipient per transaction, so a message to three people is three deliveries back):
- Route. The sender’s domain is looked up in the relay’s local copy of your routes to find which Exchange Online host to hand the message back to. An unknown domain is refused with a temporary (4xx) error, never guessed, so a propagation gap costs a delay and not a misrouted message. Exchange retries.
- Decide whether to sign. Left exactly as received, and logged as Not signed with the reason: S/MIME-encrypted or digitally signed mail; calendar messages; bounces; a sender who is not a person in your directory with a signature (a distribution list, a redirected message); a message too large to sign; and the rare message classic Outlook sends as rich text only (
winmail.dat) that cannot be placed safely. - Insert. The signature’s HTML and plain text are placed under the new text and above any quoted earlier messages, in both the HTML and plain-text parts. Images are embedded as inline MIME parts, deduplicated by content so a thread does not accumulate a copy of the logo per reply. Where the message carries the sender’s own Outlook signature (Outlook’s
<div id="Signature">block), that block is replaced rather than doubled. Ascripto’s own signature is wrapped as<div data-ascripto-sig="1">so a re-send or a loop finds it and does not add a second. - Mark and return.
X-Ascripto-Relayedis added and the message is handed back to your tenant over TLS.
Signing never depends on Ascripto’s control plane. Signatures are published to the relay hosts as a bundle and read from local disk; the relay keeps signing if the web app or database is down.
Fail modes
| Situation | Default behaviour | Alternative |
|---|---|---|
| Signing cannot happen (the relay’s signer is busy, unreachable or has no bundle for your workspace yet) | fail-open: the message is sent on without a signature and logged as Sent without a signature | fail-closed, per workspace on request: the message is deferred for Exchange Online to retry, for organisations whose signature carries a legally required disclaimer |
| Routing cannot be resolved | always fail-closed (temporary refusal; Exchange queues and retries) | none; a wrong guess would hand your mail to another tenant |
| Workspace suspended for non-payment | mail passes through unsigned for 7 days, then is refused temporarily; Exchange Online queues and eventually returns it to the sender unless the routing is removed | pay, or switch the rule off |
| Workspace suspended for a terms breach | refused temporarily at once | remove the routing |
The message log
Settings → Delivery → Message log: every message through the relay, newest first, for the last 10 days, searchable by sender, recipient or Message-ID, updated every few minutes. Per recipient: Signature inserted or Not signed: reason, and Left the relay, accepted by Microsoft / Waiting: Microsoft asked the relay to try again / Refused by Microsoft; the sender gets a bounce, with the SMTP code and attempt count. The subject and content of mail are never stored, so they cannot be searched. The trace holds envelope addresses, Message-ID, time, size and outcome.
What recipients and senders see
- The signature is not in the compose window or in Sent Items, because it is inserted after Send. There is no “Sent Items update” today.
- Every client is covered, including Outlook mobile and Apple Mail, because nothing depends on the client.
- Authentication: Exchange Online delivers the returned message with SPF-aligned DMARC (its own IP sends it). It does not DKIM-sign a message that came back through a connector, which is the same as other relay products. A copy later forwarded by a recipient may therefore fail DMARC. Coming: DKIM by delegation, where you add two CNAMEs (
ascripto1._domainkeyandascripto2._domainkey) pointing at Ascripto and the relay signs on the way back.
Removing Ascripto
Order matters, because removing a domain in Ascripto makes the relay hold that domain’s mail at once.
- In Exchange Online, switch the rule off first:
Disable-TransportRule -Identity 'Ascripto signatures' -Confirm:$false(the Delivery page shows this line when you remove the last domain). - In Ascripto, Settings → Delivery → Remove each domain.
- Delete the rule and the connectors:
Remove-TransportRule 'Ascripto signatures',Remove-OutboundConnector 'Ascripto outbound',Remove-InboundConnector 'Ascripto inbound'. - In the Microsoft Entra admin center → Entra ID → Enterprise apps → Ascripto → Permissions → Admin consent → revoke the permissions, or delete the enterprise application, which removes every grant.
To remove one domain and keep the rest: remove it in Ascripto, then run the setup again straight away; the regenerated rule no longer names it. Until you do, Exchange keeps sending that domain’s mail to Ascripto and it waits; nothing is lost.
Seats and data
A seat on Microsoft 365 is anyone the relay signed at least one message for in the month. Shared mailboxes and senders without a signature cost nothing.
Data handling (storage region, retention, staff access, the DPA) is the same as for Google Workspace and is set out in that guide. Specific to the relay: message content is handled in transit and not stored; the message log is kept 10 days.