Your sender reputation is invisible until it breaks. Then password resets land in spam, activation emails vanish, and support tickets flood in asking "where's my email?"
Most teams only check deliverability after it's already damaged. By then, you're fighting an uphill battle: Gmail has flagged your domain, Outlook is throttling your sends, and you're burning through engaged users trying to recover.
The three reputation signals that actually matter
Sender reputation isn't one number. It's a composite score based on three core signals that Gmail, Outlook, and Yahoo track independently:
- Engagement rate — Opens, clicks, replies vs. deletes without reading
- Complaint rate — Spam reports and unsubscribes
- Technical hygiene — Bounce rate, authentication alignment, sending patterns
Each provider weighs these differently. Gmail prioritizes engagement. Outlook is stricter on complaints. Yahoo penalizes inconsistent sending patterns. You need to monitor all three.
Free monitoring tools you should set up today
You don't need expensive third-party tools to catch reputation issues early. These free provider tools give you 90% of what you need:
Gmail Postmaster Tools (critical)
Google's free dashboard shows your domain and IP reputation, spam rate, authentication status, and encryption compliance—directly from Gmail's internal scoring.
# Setup steps:
1. Go to https://postmaster.google.com
2. Add your sending domain (e.g., notifications.yoursaas.com)
3. Add the verification TXT record to DNS
4. Wait 24-48h for data to populate
# What to monitor weekly:
- Domain reputation (keep it "High")
- IP reputation (should match domain)
- Spam rate (keep below 0.10%)
- Feedback loop complaintsMicrosoft SNDS (Outlook/Hotmail)
Microsoft's Smart Network Data Services tracks your IP reputation for Outlook.com and Hotmail. Shows message quality, trap hits, and complaint rates.
# Setup:
1. Visit https://sendersupport.olc.protection.outlook.com/snds/
2. Register your sending IP addresses
3. Review color-coded reputation data
# Color codes:
- Green: Good standing (ship it)
- Yellow: Caution (investigate spike in complaints)
- Red: Poor reputation (immediate action required)
- No data: Not enough volume (increase sends or wait)Feedback loops (FBLs)
Feedback loops let ESPs notify you when users mark your emails as spam. Most transactional providers (Resend, Postmark, SendGrid) automatically handle FBL registration and suppress complainers.
If you're sending via your own SMTP server, register manually:
- AOL/Yahoo:
https://senders.yahooinc.com/complaint-feedback-loop/ - Outlook.com: Uses JMRP (Junk Mail Reporting Program) via SNDS
- Gmail: No public FBL; use Postmaster Tools instead
The five metrics to track weekly
Raw dashboards don't help unless you know what to look for. Track these five metrics weekly (or daily during high-volume periods):
1. Bounce rate (hard + soft)
Target: Below 2% total, below 1% hard bounces
Hard bounces (permanent failures) directly hurt sender reputation. Soft bounces (temporary issues) are less harmful but can signal list hygiene problems if they're chronic.
import { db } from "@/lib/db";
export async function trackBounceRate(period: "day" | "week" | "month") {
const stats = await db.emailLog.aggregate({
where: {
sentAt: { gte: getPeriodStart(period) },
},
_count: {
id: true,
bounced: { where: { bounced: true } },
hardBounce: { where: { bounceType: "hard" } },
},
});
const total = stats._count.id;
const bounced = stats._count.bounced;
const hardBounced = stats._count.hardBounce;
const bounceRate = (bounced / total) * 100;
const hardBounceRate = (hardBounced / total) * 100;
// Alert if thresholds exceeded
if (bounceRate > 2.0) {
await alertSlack({
message: `⚠️ Bounce rate spike: ${bounceRate.toFixed(2)}%`,
channel: "#deliverability-alerts",
});
}
return { total, bounced, hardBounced, bounceRate, hardBounceRate };
}
function getPeriodStart(period: "day" | "week" | "month"): Date {
const now = new Date();
switch (period) {
case "day":
return new Date(now.setHours(0, 0, 0, 0));
case "week":
return new Date(now.setDate(now.getDate() - 7));
case "month":
return new Date(now.setMonth(now.getMonth() - 1));
}
}2. Complaint rate (spam reports)
Target: Below 0.1% (1 complaint per 1,000 sends)
Complaint rates above 0.1% trigger deliverability penalties. Above 0.3%, you're at risk of being blocklisted by major ESPs.
3. Engagement rate (opens + clicks)
Target: 20%+ for transactional, 15%+ for marketing
Low engagement tells Gmail and Outlook that your emails aren't valuable. Even with perfect authentication, chronically low engagement pushes you toward the spam folder.
export async function trackEngagementRate(days = 7) {
const stats = await db.emailLog.aggregate({
where: {
sentAt: { gte: new Date(Date.now() - days * 24 * 60 * 60 * 1000) },
delivered: true,
},
_count: {
id: true,
opened: { where: { opened: true } },
clicked: { where: { clicked: true } },
},
});
const delivered = stats._count.id;
const opened = stats._count.opened;
const clicked = stats._count.clicked;
const openRate = (opened / delivered) * 100;
const clickRate = (clicked / delivered) * 100;
const engagementRate = ((opened + clicked) / delivered) * 100;
// Alert on low engagement
if (engagementRate < 15 && delivered > 100) {
await alertSlack({
message: `📉 Low engagement: ${engagementRate.toFixed(1)}% (last ${days}d)`,
channel: "#deliverability-alerts",
});
}
return { delivered, opened, clicked, openRate, clickRate, engagementRate };
}4. Authentication pass rate
Target: 100% SPF + DKIM pass, 100% DMARC alignment
Even occasional authentication failures erode trust. Use Gmail Postmaster Tools to verify alignment, and monitor DMARC reports for failures.
5. Inbox placement rate (seed testing)
Target: 95%+ inbox (not spam/promotions)
Seed testing sends your emails to monitored accounts across Gmail, Outlook, Yahoo, and Apple Mail, then checks where they land (inbox, spam, or promotions tab).
Free tools: GlockApps (limited free tier), Mail-Tester (single-send checks)
Paid tools: Litmus Email Analytics, 250ok (better for high-volume senders)
How to recover from reputation damage
Caught a reputation drop early? Here's the 4-step recovery playbook:
Step 1: Stop the bleeding
- Pause non-critical sends (newsletters, marketing)
- Keep only high-priority transactional emails (resets, verification)
- Suppress recent complainers and hard bounces immediately
- Review last 7 days of sends for pattern changes (new template? list import?)
Step 2: Audit list hygiene
import { db } from "@/lib/db";
export async function auditListHygiene() {
// Find high-risk recipients
const highRisk = await db.recipient.findMany({
where: {
OR: [
// Never opened in last 90 days
{ lastOpenedAt: { lt: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000) } },
// Hard bounced recently
{ hardBounced: true },
// Complained
{ complained: true },
// Multiple soft bounces
{ softBounceCount: { gte: 3 } },
],
},
});
console.log(`Found ${highRisk.length} high-risk recipients`);
// Suppress or delete
await db.recipient.updateMany({
where: { id: { in: highRisk.map((r) => r.id) } },
data: { suppressed: true, suppressedReason: "hygiene_audit" },
});
return highRisk;
}Step 3: Re-warm gradually
Don't blast your full list the moment metrics recover. Use a gradual warm-up schedule:
- Week 1: High-engagement recipients only (opened in last 30 days)
- Week 2: Add medium-engagement (opened in last 60 days)
- Week 3: Slowly reintroduce dormant users (60-90 days)
- Week 4+: Resume normal sending if reputation stable
Step 4: Monitor obsessively
During recovery, check metrics daily:
- Gmail Postmaster domain reputation (must stay "High")
- Bounce rate (should drop below 1% within 3-5 days)
- Complaint rate (watch for new reports; investigate each one)
- Engagement rate (should increase as you target engaged users)
Set up automated monitoring (10 min)
Manual checks don't scale. Automate reputation monitoring with a simple cron job and Slack alerts:
import { NextResponse } from "next/server";
import { trackBounceRate } from "@/lib/monitoring/bounce-tracker";
import { trackEngagementRate } from "@/lib/monitoring/engagement-tracker";
import { alertSlack } from "@/lib/alerts";
export async function GET(req: Request) {
// Verify cron secret
const authHeader = req.headers.get("authorization");
if (authHeader !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response("Unauthorized", { status: 401 });
}
const bounceStats = await trackBounceRate("day");
const engagementStats = await trackEngagementRate(7);
// Build daily report
const report = {
date: new Date().toISOString().split("T")[0],
bounceRate: bounceStats.bounceRate.toFixed(2),
hardBounceRate: bounceStats.hardBounceRate.toFixed(2),
engagementRate: engagementStats.engagementRate.toFixed(1),
openRate: engagementStats.openRate.toFixed(1),
clickRate: engagementStats.clickRate.toFixed(1),
};
// Alert if thresholds breached
const alerts = [];
if (bounceStats.bounceRate > 2.0) {
alerts.push(`⚠️ Bounce rate: ${report.bounceRate}%`);
}
if (engagementStats.engagementRate < 15 && engagementStats.delivered > 100) {
alerts.push(`📉 Engagement rate: ${report.engagementRate}%`);
}
if (alerts.length > 0) {
await alertSlack({
message: `Deliverability Alert\n${alerts.join("\n")}`,
channel: "#deliverability-alerts",
});
}
return NextResponse.json({ report, alerts });
}
// Deploy to Vercel Cron:
// Add to vercel.json:
// {
// "crons": [{
// "path": "/api/cron/deliverability-check",
// "schedule": "0 9 * * *"
// }]
// }Prevention checklist (bookmark this)
Most reputation damage is preventable. Run this checklist monthly:
- Authentication: Verify SPF, DKIM, DMARC passing at 100%
- Bounce handling: Auto-suppress hard bounces immediately
- Engagement pruning: Suppress users inactive 90+ days
- Complaint monitoring: Review every spam report; identify patterns
- Sending consistency: Avoid sudden volume spikes (>50% increase)
- List-Unsubscribe header: Present on all bulk/marketing emails
- Content quality: Avoid spam trigger words, broken links, HTML errors
- Seed testing: Monthly inbox placement checks across providers
Want production-ready templates that follow deliverability best practices out of the box? Check out our transactional email templates for Next.js — built with proper authentication, engagement-optimized copy, and tested across all major email clients.