Budibase/budibase · error · Error
IMAP host is blocked or could not be resolved safely
Error message
IMAP host is blocked or could not be resolved safely
What it means
getClient checks the configured IMAP host against an SSRF blacklist before connecting. If the host is blacklisted (or cannot be safely resolved, e.g. it maps to internal/private addresses), the connection is refused with this error to protect the server from SSRF attacks.
Source
Thrown at packages/server/src/automations/email/utils/getClient.ts:106
}
if (!inputs.password) {
throw new Error("IMAP password is required")
}
return {
user: inputs.username,
pass: inputs.password,
}
}
export const getClient = async (inputs: EmailTriggerInputs) => {
if (!inputs) {
throw new Error("Email trigger inputs are required")
}
if (await blacklist.isBlacklisted(inputs.host)) {
throw new Error("IMAP host is blocked or could not be resolved safely")
}
const client = new ImapFlow({
host: inputs.host,
port: inputs.port,
secure: inputs.secure,
auth: await getAuthConfig(inputs),
// imap flow has its own pino instance enabled by default and is very very chatty!
logger: false,
})
return client
}
View on GitHub (pinned to a81a902e9a)
Solutions
- Use a public, routable IMAP hostname (e.g. imap.example.com) instead of an internal/private address
- Verify DNS resolution of the host from the server environment
- Check the blacklist implementation to confirm whether the host is intentionally blocked and request an allowlist if legitimate
- Correct typos in the host field of the trigger config
Example fix
// before
{ "host": "192.168.1.10" } // private IP blocked by SSRF guard
// after
{ "host": "imap.example.com" } Defensive patterns
Strategy: validation
Validate before calling
import { isIP } from "net"
const host = inputs.host
if (!host || host === "localhost" || /^(10\.|127\.|192\.168\.|169\.254\.|172\.(1[6-9]|2\d|3[01])\.)/.test(host)) {
throw new Error("Use a public IMAP hostname")
} Type guard
function isPublicHost(host: string): boolean {
return typeof host === "string" && host.length > 0 &&
!/^localhost$/i.test(host) &&
!/^(10\.|127\.|192\.168\.|169\.254\.|172\.(1[6-9]|2\d|3[01])\.)/.test(host)
} Try / catch
try {
const client = await getClient(inputs)
} catch (err) {
if (err.message.includes("blocked or could not be resolved safely")) {
// surface a config error to the user: host is private/unresolvable
}
throw err
} Prevention
- Only use public, DNS-resolvable IMAP hostnames
- Don't point automations at internal services in hardened environments
- Confirm DNS works in the deployment before configuring the trigger
When it happens
Trigger: inputs.host resolves to a blacklisted entry (internal IPs, localhost, metadata endpoints) or the blacklist resolver cannot safely resolve the hostname at automation runtime.
Common situations: Pointing the email trigger at an internal mail server on a deployment with SSRF protections; hostnames that fail DNS resolution; typo'd host values resolving to private ranges; hardened environments blocking private network egress.
Related errors
- Only HTTP(S) URLs are allowed.
- URL is blocked or could not be resolved safely.
- Only HTTP(S) URLs are allowed for query import
- REST query path must remain on the datasource origin
- Error getting account by tenantId ${tenantId}
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/00ac4ffee5883288.
Report an issue: GitHub.