{"record":{"id":"e34962ad71e3f342","repo":"flowable/flowable-engine","slug":"no-smtp-host-is-configured-for-the-mail-server-for-e34962","errorCode":null,"errorMessage":"no SMTP host is configured for the mail server for tenant ${tenantId}","messagePattern":"no SMTP host is configured for the mail server for tenant (.+?)","errorType":"exception","errorClass":"FlowableException","httpStatus":null,"severity":"error","filePath":"modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java","lineNumber":1487,"sourceCode":"        }\n\n        Collection<String> tenantIds = new HashSet<>(mailSessionsJndi.keySet());\n        tenantIds.addAll(mailServers.keySet());\n\n        if (!tenantIds.isEmpty()) {\n            MailServerInfo defaultMailServer = getDefaultMailServer();\n            for (String tenantId : tenantIds) {\n                if (mailClients.containsKey(tenantId)) {\n                    continue;\n                }\n                String sessionJndi = mailSessionsJndi.get(tenantId);\n                MailServerInfo tenantMailServer = mailServers.get(tenantId);\n                if (sessionJndi != null) {\n                    mailClients.put(tenantId, FlowableMailClientCreator.createSessionClient(sessionJndi, tenantMailServer, defaultMailServer));\n                } else if (tenantMailServer != null) {\n                    String host = tenantMailServer.getMailServerHost();\n                    if (host == null) {\n                        throw new FlowableException(\"no SMTP host is configured for the mail server for tenant \" + tenantId);\n                    }\n                    mailClients.put(tenantId, FlowableMailClientCreator.createHostClient(host, tenantMailServer, defaultMailServer));\n                }\n            }\n        }\n    }\n\n    protected void initBusinessCalendarManager() {\n        if (businessCalendarManager == null) {\n            MapBusinessCalendarManager mapBusinessCalendarManager = new MapBusinessCalendarManager();\n            mapBusinessCalendarManager.addBusinessCalendar(DurationBusinessCalendar.NAME, new DurationBusinessCalendar(this.clock));\n            mapBusinessCalendarManager.addBusinessCalendar(DueDateBusinessCalendar.NAME, new DueDateBusinessCalendar(this.clock));\n            mapBusinessCalendarManager.addBusinessCalendar(CycleBusinessCalendar.NAME, new CycleBusinessCalendar(this.clock));\n\n            businessCalendarManager = mapBusinessCalendarManager;\n        }\n    }\n","sourceCodeStart":1469,"sourceCodeEnd":1505,"githubUrl":"https://github.com/flowable/flowable-engine/blob/d6d39ce1c69ff244f2d9dc6af756a9b95e865586/modules/flowable5-engine/src/main/java/org/activiti/engine/impl/cfg/ProcessEngineConfigurationImpl.java#L1469-L1505","documentation":"When initializing per-tenant mail clients, Flowable iterates the configured tenant mail servers and builds a client for each. If a tenant's MailServerInfo has a null host (and no JNDI session applies), the engine cannot create an SMTP client for that tenant and throws this FlowableException naming the tenantId.","triggerScenarios":"Calling buildProcessEngine() with mailServers populated (via setMailServers/addMailServer) where the MailServerInfo for a specific tenantId has mailServerHost == null and no mail session JNDI is configured for that tenant.","commonSituations":"Multi-tenant deployments where one tenant's entry was added with only user/password/port but no host; a tenant properties map missing the host key; programmatic config that copies defaults but leaves host null.","solutions":["Set the host for the offending tenant: config.addMailServer(tenantId, new MailServerInfo(... host=\"smtp.tenant.com\" ...)) or setMailServerHost equivalent per tenant","Configure a JNDI mail session for the tenant via mailSessionsJndi so host lookup is bypassed","Audit the tenant mail server map before building the engine and log/fail fast on entries missing a host","Fall back to the default mail server by removing the incomplete tenant entry if the tenant should use default SMTP settings"],"exampleFix":"// before\nMailServerInfo info = new MailServerInfo();\ninfo.setMailServerUser(\"user\");\nconfig.addMailServer(\"tenantA\", info);\n// after\nMailServerInfo info = new MailServerInfo();\ninfo.setMailServerHost(\"smtp.tenant-a.com\");\ninfo.setMailServerUser(\"user\");\nconfig.addMailServer(\"tenantA\", info);","handlingStrategy":"validation","validationCode":"for (Map.Entry<String, MailServerInfo> e : config.getMailServers().entrySet()) {\n    MailServerInfo info = e.getValue();\n    if (info == null || info.getMailServerHost() == null || info.getMailServerHost().isEmpty()) {\n        throw new IllegalStateException(\"Mail server host missing for tenant \" + e.getKey());\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate every tenant MailServerInfo has a host right after building the tenant config map","Centralize tenant mail config construction so defaults (including host) are always applied","Cover tenant mail configuration with a startup smoke test in multi-tenant environments","Fall back deliberately: decide whether incomplete tenants should inherit the default mail server instead of being registered with a null host"],"tags":["configuration","smtp","mail","multi-tenant"],"backgroundTag":"missing-required-config-field","analyzedSha":"d6d39ce1c69ff244f2d9dc6af756a9b95e865586","analyzedAt":"2026-09-11T06:41:19.413Z","contentChangedAt":"2026-09-11T06:41:19.413Z","schemaVersion":2},"datasetVersion":"2026-09-18T11:17:12.947Z"}