{"record":{"id":"c12e3a901ccb7bc6","repo":"TryGhost/Ghost","slug":"please-verify-your-email-settings","errorCode":null,"errorMessage":"Please verify your email settings","messagePattern":"Please verify your email settings","errorType":"http","errorClass":"EmailError","httpStatus":null,"severity":"error","filePath":"apps/admin-x-framework/src/utils/api/handle-response.ts","lineNumber":37,"sourceCode":"            throw new APIError(response, await response.text());\n        }\n\n        const data = await response.json() as ErrorResponse;\n\n        if (response.status === 403 && data.errors?.[0]?.message === 'Authorization failed') {\n            throw new UnauthorizedError(response, data);\n        } else if (data.errors?.[0]?.type === 'VersionMismatchError') {\n            throw new VersionMismatchError(response, data);\n        } else if (data.errors?.[0]?.type === 'ValidationError') {\n            throw new ValidationError(response, data);\n        } else if (data.errors?.[0]?.type === 'NoPermissionError') {\n            throw new ValidationError(response, data);\n        } else if (data.errors?.[0]?.type === 'ThemeValidationError') {\n            throw new ThemeValidationError(response, data);\n        } else if (data.errors?.[0]?.type === 'HostLimitError') {\n            throw new HostLimitError(response, data);\n        } else if (data.errors?.[0]?.type === 'EmailError') {\n            throw new EmailError(response, data);\n        } else {\n            throw new JSONError(response, data);\n        }\n    } else if (response.status === 204) {\n        return;\n    } else if (response.headers.get('content-type')?.includes('text/csv')) {\n        return await response.text();\n    } else {\n        return await response.json();\n    }\n};\n\nexport default handleResponse;\n","sourceCodeStart":19,"sourceCodeEnd":51,"githubUrl":"https://github.com/TryGhost/Ghost/blob/47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe/apps/admin-x-framework/src/utils/api/handle-response.ts#L19-L51","documentation":"EmailError, thrown by handleResponse when errors[0].type === 'EmailError'. It signals that an email-sending operation failed because of misconfigured or unavailable mail transport (Mailgun, SMTP, etc.). The specific transport error detail is in error.data.","triggerScenarios":"Triggering a send — staff invite emails, member signup confirmation, newsletter publishing, magic-link login — while the mail service is misconfigured, has bad credentials, or is unreachable. Ghost returns {errors:[{type:'EmailError', ...}]} with the transport's error.","commonSituations":"Mailgun API key/region mismatch; SMTP host/port/encryption wrong; email from-address not verified; mail provider rate-limit or outage; DNS (SPF/DKIM) issues surfacing as transport errors.","solutions":["Open Ghost Admin → Settings → Labs / config and verify the mail transport settings (Mailgun key+domain or SMTP host/port/user/pass).","Send a test email from the admin to confirm the transport works end-to-end.","Inspect error.data for the underlying transport message (auth failure, connection refused, etc.) and fix that specific cause."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"import {EmailError} from '@tryghost/admin-x-framework/utils/errors';\nfunction isEmailError(e: unknown): e is EmailError {\n    return e instanceof EmailError;\n}","tryCatchPattern":"import {EmailError} from '@tryghost/admin-x-framework/utils/errors';\ntry {\n    await api.users.invite({email});\n} catch (e) {\n    if (e instanceof EmailError) {\n        notify('Email sending failed. Check your mail settings in Labs.');\n        // e.data?.errors?.[0]?.message has the transport-specific error\n    } else throw e;\n}","preventionTips":["Verify the mail transport (Mailgun key+domain or SMTP host/port/credentials) in Settings → Labs.","Send a test email from the admin after changing mail config to confirm it works.","Inspect error.data for the underlying transport error (auth, connection, rate-limit) before assuming a Ghost bug."],"tags":["email","mailgun","smtp","config","transport"],"backgroundTag":null,"analyzedSha":"47d8b0e2ad2fd4757d3bc45f46c3ac165ff8a1fe","analyzedAt":"2026-08-13T01:25:26.651Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}