{"record":{"id":"00ac4ffee5883288","repo":"Budibase/budibase","slug":"imap-host-is-blocked-or-could-not-be-resolved-safe","errorCode":null,"errorMessage":"IMAP host is blocked or could not be resolved safely","messagePattern":"IMAP host is blocked or could not be resolved safely","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/server/src/automations/email/utils/getClient.ts","lineNumber":106,"sourceCode":"  }\n\n  if (!inputs.password) {\n    throw new Error(\"IMAP password is required\")\n  }\n\n  return {\n    user: inputs.username,\n    pass: inputs.password,\n  }\n}\n\nexport const getClient = async (inputs: EmailTriggerInputs) => {\n  if (!inputs) {\n    throw new Error(\"Email trigger inputs are required\")\n  }\n\n  if (await blacklist.isBlacklisted(inputs.host)) {\n    throw new Error(\"IMAP host is blocked or could not be resolved safely\")\n  }\n\n  const client = new ImapFlow({\n    host: inputs.host,\n    port: inputs.port,\n    secure: inputs.secure,\n    auth: await getAuthConfig(inputs),\n    // imap flow has its own pino instance enabled by default and is very very chatty!\n    logger: false,\n  })\n\n  return client\n}\n","sourceCodeStart":88,"sourceCodeEnd":120,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/automations/email/utils/getClient.ts#L88-L120","documentation":"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.","triggerScenarios":"inputs.host resolves to a blacklisted entry (internal IPs, localhost, metadata endpoints) or the blacklist resolver cannot safely resolve the hostname at automation runtime.","commonSituations":"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.","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"],"exampleFix":"// before\n{ \"host\": \"192.168.1.10\" } // private IP blocked by SSRF guard\n// after\n{ \"host\": \"imap.example.com\" }","handlingStrategy":"validation","validationCode":"import { isIP } from \"net\"\nconst host = inputs.host\nif (!host || host === \"localhost\" || /^(10\\.|127\\.|192\\.168\\.|169\\.254\\.|172\\.(1[6-9]|2\\d|3[01])\\.)/.test(host)) {\n  throw new Error(\"Use a public IMAP hostname\")\n}","typeGuard":"function isPublicHost(host: string): boolean {\n  return typeof host === \"string\" && host.length > 0 &&\n    !/^localhost$/i.test(host) &&\n    !/^(10\\.|127\\.|192\\.168\\.|169\\.254\\.|172\\.(1[6-9]|2\\d|3[01])\\.)/.test(host)\n}","tryCatchPattern":"try {\n  const client = await getClient(inputs)\n} catch (err) {\n  if (err.message.includes(\"blocked or could not be resolved safely\")) {\n    // surface a config error to the user: host is private/unresolvable\n  }\n  throw err\n}","preventionTips":["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"],"tags":["ssrf","security","network","imap","blacklist"],"backgroundTag":"ssrf-host-blocked","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}