7.1 KiB
Glaztech — Email Delivery Investigation & Transport Rules
User
- User: Mike Swanson (mike)
- Machine: GURU-5070
- Role: admin
Session Summary
Steve Eastman (Glaztech) reported that emails from two vendor contacts — hartsglass@centurytel.net and olemons@eastexglass.com — were showing "Deliver" in MailProtector but not arriving at SHVSALES@glaztech.com. The emails were not appearing in M365 Quarantine either, which was the key diagnostic clue.
Investigation via Exchange Online message trace and connector inspection revealed the root cause: both sender domains (centurytel.net and eastexglass.com) publish DMARC policy p=reject. Glaztech's inbound connector ("Inbound Spam Filter") has Enhanced Filtering enabled with EFSkipIPs set to the three MailProtector IPs (162.248.93.233, 162.248.93.81, 65.113.52.82), but SCLMinusOne is null — meaning EOP does not trust MailProtector's verdict and re-evaluates all mail. With Enhanced Filtering, EOP looks past the MailProtector relay to the original sender's authentication. Both sender domains fail DMARC, producing hard 550 5.7.509 NDR rejections in Exchange Online before messages ever reach the mailbox or quarantine.
Additional rejected senders were identified from the email thread Steve forwarded: SSales@arkglass.com, bossier@glassservices.com, and an unnamed contact at aaaglassinc.com (Donald Arnold). DNS inspection of glassservices.com found a broken SPF record (v=spf1 -all — no authorized senders), meaning their emails will be rejected by all mail providers regardless of any Glaztech-side fix.
The fix applied was two SCL=-1 transport rules in the Glaztech Exchange Online tenant. Transport rules evaluate before the anti-spam pipeline (including DMARC enforcement) in EOP, so setting SCL=-1 bypasses the DMARC rejection for these specific senders. Rules were created via the Exchange Operator service principal using POST /adminapi/beta/{tenant}/InvokeCommand with New-TransportRule cmdlet (direct REST resource endpoints 404 in this tenant).
Key Decisions
- SCL=-1 transport rule over connector trust — Setting
SCLMinusOne: trueon the connector would trust MailProtector's verdict for ALL inbound mail, which is too broad. Targeted transport rules scoped to specific senders are the more surgical fix. - Two rules instead of one — The aaaglassinc.com sender was handled by domain (
SenderDomainIs) rather than specific address since the contact email was not known. The other four were handled by exact address (From). Separate rules keep the logic clean. - glassservices.com SPF not fixable on our side — Their
v=spf1 -allwill cause rejection everywhere. The appropriate action is notifying Steve so he can tell the glassservices.com vendor their IT needs to fix the SPF record. Our SCL=-1 rule still coversbossier@glassservices.comas a workaround. - No Syncro ticket created — This was handled reactively via email thread; no ticket was opened during the session. Consider creating one retroactively if billing for this work.
Problems Encountered
- Direct REST resource endpoints 404:
/adminapi/beta/{tenant}/TransportRulereturns 404. Fixed by using theInvokeCommandpattern:POST /adminapi/beta/{tenant}/InvokeCommandwith{"CmdletInput": {"CmdletName": "New-TransportRule", "Parameters": {...}}}. - Transport rule name 66-char limit exceeded: Initial rule name "SCL Bypass - hartsglass@centurytel.net and olemons@eastexglass.com" was 66 chars; EXO enforces a 64-char max. Fixed by shortening to "SCL Bypass - hartsglass + olemons (SHVSALES)" (44 chars).
- Initial misdiagnosis: First assumed emails were landing in Junk/spam folder (SCL scoring). Steve's follow-up with full message trace revealed actual cause was hard DMARC
550 5.7.509NDR — the SCL=-1 fix still resolves this correctly since transport rules run before DMARC enforcement in the EXO pipeline.
Configuration Changes
Two transport rules created in Glaztech M365 tenant (82931e3c-de7a-4f74-87f7-fe714be1f160):
| Rule GUID | Name | Condition | Action |
|---|---|---|---|
| 482c714a-8780-4c62-ae0a-0b6da9ca9d52 | SCL Bypass - hartsglass + olemons (SHVSALES) | From: hartsglass@centurytel.net, olemons@eastexglass.com, SSales@arkglass.com, bossier@glassservices.com | SetSCL: -1 |
| 7e0c01a8-ec22-43fe-b600-796c0f295aa5 | SCL Bypass - aaaglassinc.com (SHVSALES) | SenderDomainIs: aaaglassinc.com | SetSCL: -1 |
Both rules: State = Enabled.
Credentials & Secrets
- Exchange Operator Service Principal
- App ID: b43e7342-5b4b-492f-890f-bb5a4f7f40e9
- Secret: Ct28Q~fKYUu.RvkMaGNAV1YeK6h-HBewCTPnwa.Y
- Vault:
msp-tools/computerguru-exchange-operator.sops.yaml
- Glaztech Tenant ID: 82931e3c-de7a-4f74-87f7-fe714be1f160
Infrastructure & Servers
- Glaztech M365 tenant: 82931e3c-de7a-4f74-87f7-fe714be1f160
- MailProtector IPs (EFSkipIPs on inbound connector): 162.248.93.233, 162.248.93.81, 65.113.52.82
- EXO InvokeCommand endpoint:
https://outlook.office365.com/adminapi/beta/{tenant}/InvokeCommand - Token endpoint:
https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
Commands & Outputs
# Auth token
POST https://login.microsoftonline.com/82931e3c-.../oauth2/v2.0/token
scope=https://outlook.office365.com/.default
# Check connector Enhanced Filtering state
POST /adminapi/beta/{tenant}/InvokeCommand
{"CmdletInput":{"CmdletName":"Get-InboundConnector","Parameters":{"Identity":"Inbound Spam Filter"}}}
# → EFSkipIPs: [162.248.93.233, 162.248.93.81, 65.113.52.82], SCLMinusOne: null
# Create rule 1 (specific addresses)
{"CmdletInput":{"CmdletName":"New-TransportRule","Parameters":{
"Name":"SCL Bypass - hartsglass + olemons (SHVSALES)",
"From":["hartsglass@centurytel.net","olemons@eastexglass.com","SSales@arkglass.com","bossier@glassservices.com"],
"SetSCL":-1,"Enabled":true}}}
# → GUID: 482c714a-8780-4c62-ae0a-0b6da9ca9d52
# Create rule 2 (domain)
{"CmdletInput":{"CmdletName":"New-TransportRule","Parameters":{
"Name":"SCL Bypass - aaaglassinc.com (SHVSALES)",
"SenderDomainIs":["aaaglassinc.com"],
"SetSCL":-1,"Enabled":true}}}
# → GUID: 7e0c01a8-ec22-43fe-b600-796c0f295aa5
Pending / Incomplete Tasks
- Notify Steve about glassservices.com SPF:
bossier@glassservices.comwill be rejected by all mail providers (SPFv=spf1 -all). Steve should tell the vendor their IT needs to fix the SPF record. Our SCL bypass is a workaround only. - Harts Glass resend: The original rejected emails need to be resent by the sender. Our rule is now live but previously rejected messages are NDRed and will not auto-retry.
- Syncro ticket: No ticket opened for this work. Create retroactively if billing.
Reference Information
- DMARC root cause:
centurytel.net→p=reject;eastexglass.com→p=reject - NDR code:
550 5.7.509(DMARC failure under Enhanced Filtering) - Transport rule GUIDs: 482c714a (addresses), 7e0c01a8 (aaaglassinc.com domain)
- EXO InvokeCommand pattern: Required because direct
/TransportRuleREST endpoint 404s in this tenant