{"record":{"id":"019a689d5153c515","repo":"Budibase/budibase","slug":"imap-password-is-required-when-connection-details","errorCode":null,"errorMessage":"IMAP password is required when connection details change","messagePattern":"IMAP password is required when connection details change","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/automation.ts","lineNumber":265,"sourceCode":"  const trigger = automation.definition.trigger\n  if (!trigger) {\n    throw new HTTPError(\"No trigger found for automation\", 400)\n  }\n  if (!isEmailTrigger(trigger)) {\n    throw new HTTPError(\"Automation trigger is not an email trigger\", 400)\n  }\n  if (!trigger.inputs.password) {\n    throw new HTTPError(\"IMAP password is required\", 400)\n  }\n\n  const stored = trigger.inputs\n  const connectionMatches =\n    emailInputs.host === stored.host &&\n    emailInputs.port === stored.port &&\n    emailInputs.username === stored.username &&\n    emailInputs.secure === stored.secure\n  if (!connectionMatches) {\n    throw new HTTPError(\n      \"IMAP password is required when connection details change\",\n      400\n    )\n  }\n\n  return {\n    ...emailInputs,\n    password: stored.password,\n  }\n}\n\nexport async function testEmailConnection(\n  ctx: UserCtx<TestEmailConnectionRequest, TestEmailConnectionResponse>\n) {\n  try {\n    await testConnection(await hydrateEmailConnectionPassword(ctx.request.body))\n    ctx.body = { valid: true }\n  } catch (err: any) {","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/automation.ts#L247-L283","documentation":"When testing with a masked (saved) password, the supplied connection details (host, port, username, secure) must exactly match what is stored on the automation's trigger, otherwise the saved password would be used against a different server. If any detail differs, HTTP 400 is thrown.","triggerScenarios":"testEmailConnection with a masked password where host, port, username, or secure differs from the values saved on the automation's email trigger inputs.","commonSituations":"User changed host/port/username in the test form but left the masked password field; migrating the automation to a new mail server; copy-pasting connection settings from another source.","solutions":["Revert the changed host/port/username/secure fields to match the saved automation, or","Enter the real plaintext password alongside the new connection details so hydration isn't needed","Update the saved automation's trigger inputs first, then test with the masked password"],"exampleFix":"// before\ntest({ automationId, emailInputs: { host: 'new.mail.com', port: 993, username: 'user', secure: true, password: '####' } })\n// after\ntest({ automationId, emailInputs: { host: 'new.mail.com', port: 993, username: 'user', secure: true, password: 'real-password' } })","handlingStrategy":"validation","validationCode":"const stored = automation.definition?.trigger?.inputs\nif (isMaskedPassword(emailInputs.password) && stored &&\n  (emailInputs.host !== stored.host || emailInputs.port !== stored.port ||\n   emailInputs.username !== stored.username || emailInputs.secure !== stored.secure)) {\n  throw new Error('Connection details changed; supply the real password')\n}","typeGuard":null,"tryCatchPattern":"try {\n  await testEmailConnection({ emailInputs, automationId })\n} catch (e) {\n  if (e.status === 400 && e.message.includes('connection details change')) {\n    // require the user to enter the real password for the new settings\n  }\n}","preventionTips":["When any of host/port/username/secure changes, always prompt for the plaintext password","Pre-fill the test form from the saved trigger inputs to avoid silent mismatches","Diff submitted inputs against stored trigger inputs before submitting masked-password tests"],"tags":["automation","imap","validation","password"],"backgroundTag":"input-validation-failed","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}