{"record":{"id":"2378be55372ac68d","repo":"theonedev/onedev","slug":"user-principal-name-needs-to-be-specified-to-gener","errorCode":null,"errorMessage":"User principal name needs to be specified to generate refresh token","messagePattern":"User principal name needs to be specified to generate refresh token","errorType":"exception","errorClass":"ExplicitException","httpStatus":null,"severity":"error","filePath":"server-plugin/server-plugin-mail-office365/src/main/java/io/onedev/server/plugin/mail/office365/Office365Connector.java","lineNumber":172,"sourceCode":"\tprivate static String getTokenEndpoint(String tenantId) {\n\t\treturn String.format(\"https://login.microsoftonline.com/%s/oauth2/v2.0/token\", tenantId);\n\t}\n\n\t@SuppressWarnings(\"unused\")\n\tprivate static RefreshToken.Callback getRefreshTokenCallback() {\n\t\tString tenantId = (String) EditContext.get().getInputValue(\"tenantId\");\n\t\tif (tenantId == null)\n\t\t\tthrow new ExplicitException(\"Directory (tenant) ID needs to be specified to generate refresh token\");\n\t\tString clientId = (String) EditContext.get().getInputValue(\"clientId\");\n\t\tif (clientId == null)\n\t\t\tthrow new ExplicitException(\"Application (client) ID needs to be specified to generate refresh token\");\n\t\tString clientSecret = (String) EditContext.get().getInputValue(\"clientSecret\");\n\t\tif (clientSecret == null)\n\t\t\tthrow new ExplicitException(\"Client secret needs to be specified to generate refresh token\");\n\n\t\tString userPrincipalName = (String) EditContext.get().getInputValue(\"userPrincipalName\");\n\t\tif (userPrincipalName == null)\n\t\t\tthrow new ExplicitException(\"User principal name needs to be specified to generate refresh token\");\n\n\t\tCollection<String> scopes = Lists.newArrayList(\n\t\t\t\t\"https://outlook.office.com/SMTP.Send\",\n\t\t\t\t\"https://outlook.office.com/IMAP.AccessAsUser.All\",\n\t\t\t\t\"offline_access\");\n\n\t\tString authorizeEndpoint = String.format(\n\t\t\t\t\"https://login.microsoftonline.com/%s/oauth2/v2.0/authorize\", tenantId);\n\t\tString tokenEndpoint = getTokenEndpoint(tenantId);\n\n\t\treturn new RefreshToken.Callback() {\n\n\t\t\t@Override\n\t\t\tpublic String getAuthorizeEndpoint() {\n\t\t\t\treturn authorizeEndpoint;\n\t\t\t}\n\n\t\t\t@Override","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/theonedev/onedev/blob/d44925c47c37992c828ea673a5f9620539bc3ff2/server-plugin/server-plugin-mail-office365/src/main/java/io/onedev/server/plugin/mail/office365/Office365Connector.java#L154-L190","documentation":"Office365Connector's refresh-token callback finally validates the userPrincipalName input — the mailbox's UPN (usually the email address). Without it, the refresh token cannot be scoped to the sending mailbox, so an ExplicitException is thrown.","triggerScenarios":"Generating a refresh token with tenantId, clientId, and clientSecret filled but 'User principal name' empty in the Office365 connector form.","commonSituations":"User forgets the mailbox field after entering app credentials; confusion between display name and UPN; shared mailbox used but UPN omitted.","solutions":["Enter the user principal name (full email address of the mailbox that will send mail) in the form.","Ensure the UPN belongs to a licensed mailbox in the same tenant as the app registration.","Complete every required field, then re-run generate refresh token."],"exampleFix":"// before\nuserPrincipalName = null;\n// after\nuserPrincipalName = \"build-notifications@contoso.com\";","handlingStrategy":"validation","validationCode":"if (!userPrincipalName || userPrincipalName.trim() === \"\") throw new Error(\"Fill User principal name before generating refresh token\");","typeGuard":null,"tryCatchPattern":"try {\n    generateRefreshToken();\n} catch (ExplicitException e) {\n    alert(\"Complete the connector form first: \" + e.getMessage());\n}","preventionTips":["Use the full UPN (email address) of a licensed mailbox in the tenant.","For shared mailboxes, confirm the UPN used is authorized for SMTP.Send.","Complete the entire form before generating the token."],"tags":["office365","azure-ad","oauth","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"d44925c47c37992c828ea673a5f9620539bc3ff2","analyzedAt":"2026-09-06T07:18:27.995Z","contentChangedAt":"2026-09-06T07:18:27.995Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}