Admin user management, password reset by email, and the Ultimo Email name
Branding: the page titles and app name are now "Ultimo Email". Admin panel (now two columns with a divider): - Users: search by login or by a mail account's address or name (results only, nothing listed until something is typed). A user opens a window to change their quota, block/unblock them, or delete them; block and delete ask for confirmation, and an admin cannot do either to their own account. - Blocking (users.blocked_at, migration 0019) refuses sign-in with a clear message and revokes every session; a new user.signed_out event sends the user's open tabs to the sign-in screen at once. Any "not signed in" answer now does the same, not only /auth/me. Deleting removes mail accounts (sync stops), plugin rows (cleared inside the user's RLS context, since plugin tables have no FK to users), blobs, the search index, sessions and the user. - Outgoing system mail (migration 0020): SMTP server, port, security, login, password (vault-encrypted, never sent back), From address and the public address reset links point to, plus a "Send test" that reports the server's error. Password reset: - "Forgot password?" on the sign-in page asks for the user name and always answers "If this account exists you will receive an email to your recovery email address"; the mail goes out after the response, so neither the reply nor its timing reveals an account, and it is capped at 3 per hour. - The emailed link (token in the URL fragment, single use, 30 minutes) opens a page to set a new password. With 2-step verification on, the code is checked before anything changes; five wrong codes burn the link. - Settings > Profile: the recovery email can be added, changed or removed, confirmed with the current password, which must be typed — autofill and paste are refused (TypedPasswordInput). Also adds frontend/icons/ultimo-logo-bimi.svg, an SVG Tiny PS version of the logo for a BIMI record. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+72
-2
@@ -3,7 +3,7 @@
|
||||
// Interpolate with {name} placeholders.
|
||||
|
||||
export const en = {
|
||||
"common.appName": "Webmail",
|
||||
"common.appName": "Ultimo Email",
|
||||
"common.loading": "Loading…",
|
||||
"common.cancel": "Cancel",
|
||||
"common.save": "Save",
|
||||
@@ -34,6 +34,26 @@ export const en = {
|
||||
"auth.create": "Create account",
|
||||
"auth.creating": "Creating…",
|
||||
"auth.noAccount": "No account?",
|
||||
"auth.forgotPassword": "Forgot password?",
|
||||
"auth.forgotTitle": "Reset your password",
|
||||
"auth.forgotHint":
|
||||
"Enter your user name. We'll email a link for choosing a new password to the recovery email address of the account.",
|
||||
"auth.changePassword": "Change password",
|
||||
"auth.sending": "Sending…",
|
||||
"auth.forgotSent": "If this account exists you will receive an email to your recovery email address.",
|
||||
"auth.backToSignIn": "Back to sign in",
|
||||
"auth.resetTitle": "Choose a new password",
|
||||
"auth.newPassword": "New password",
|
||||
"auth.repeatPassword": "Repeat the new password",
|
||||
"auth.passwordsDiffer": "The two passwords are different.",
|
||||
"auth.passwordTooShort": "Use at least 8 characters.",
|
||||
"auth.resetTotpPrompt":
|
||||
"This account uses 2-step verification. Enter the 6-digit code from your authenticator app to finish.",
|
||||
"auth.confirm": "Confirm",
|
||||
"auth.resetDone": "Your password has been changed. You have been signed out everywhere — sign in with the new password.",
|
||||
"auth.resetInvalid":
|
||||
"This link is invalid, was already used, or has expired. Request a new one to change your password.",
|
||||
"auth.requestNewLink": "Request a new link",
|
||||
"auth.haveAccount": "Already have an account?",
|
||||
"auth.register": "Register",
|
||||
"auth.checking": "Checking…",
|
||||
@@ -327,6 +347,15 @@ export const en = {
|
||||
"settings.appearance": "Appearance",
|
||||
"settings.handle": "Handle",
|
||||
"settings.recoveryEmail": "Recovery email",
|
||||
"settings.recoveryEmailHint":
|
||||
"If you forget your password, a link to choose a new one is sent here.",
|
||||
"settings.recoveryEmailNew": "Recovery email address",
|
||||
"settings.recoveryEmailRemoveHint": "Leave empty to remove it.",
|
||||
"settings.currentPassword": "Current password",
|
||||
"settings.typePassword": "Type your password — for this confirmation it can't be filled in or pasted.",
|
||||
"settings.change": "Change",
|
||||
"settings.add": "Add",
|
||||
"settings.saving": "Saving…",
|
||||
"settings.twoFactor": "Two-factor authentication",
|
||||
"settings.twoFactorOn": "2FA is enabled.",
|
||||
"settings.twoFactorOff": "2FA is not enabled.",
|
||||
@@ -412,7 +441,7 @@ export const en = {
|
||||
"settings.alsoFile": "Also mark the message as read and file it",
|
||||
"settings.integrations": "Integrations",
|
||||
|
||||
"admin.title": "Webmail administration",
|
||||
"admin.title": "Ultimo Email administration",
|
||||
"admin.signInTitle": "Administrator sign-in",
|
||||
"admin.signInHint": "Sign in with an administrator account to manage this server.",
|
||||
"admin.signOut": "Sign out",
|
||||
@@ -432,6 +461,47 @@ export const en = {
|
||||
"admin.saving": "Saving…",
|
||||
"admin.saved": "Saved",
|
||||
"admin.quotaInvalid": "Enter a size greater than 0.",
|
||||
"admin.mail": "Outgoing system mail",
|
||||
"admin.mailHelp":
|
||||
"The mail account the server sends password-reset links from. Without it, “Forgot password?” sends nothing.",
|
||||
"admin.mailOn": "Set up — password-reset links can be sent.",
|
||||
"admin.mailOff": "Not set up — password-reset links cannot be sent yet.",
|
||||
"admin.smtpHost": "SMTP server",
|
||||
"admin.smtpPort": "Port",
|
||||
"admin.smtpSecurity": "Security",
|
||||
"admin.smtpStarttls": "STARTTLS",
|
||||
"admin.smtpSsl": "SSL/TLS",
|
||||
"admin.smtpNone": "None",
|
||||
"admin.smtpUsername": "Login",
|
||||
"admin.smtpPassword": "Password",
|
||||
"admin.smtpPasswordKept": "(stored — leave empty to keep)",
|
||||
"admin.smtpPasswordRemove": "Remove the stored password",
|
||||
"admin.smtpFrom": "From address",
|
||||
"admin.publicUrl": "Public address of this server",
|
||||
"admin.publicUrlHint": "Where users open Ultimo Email, e.g. https://mail.example.com — reset links point here.",
|
||||
"admin.testTo": "Send a test email to",
|
||||
"admin.sendTest": "Send test",
|
||||
"admin.testSent": "Test email sent.",
|
||||
"admin.users": "Users",
|
||||
"admin.userSearch": "Search by login, email address or name…",
|
||||
"admin.noUsers": "No users match.",
|
||||
"admin.you": "you",
|
||||
"admin.adminBadge": "admin",
|
||||
"admin.blockedBadge": "blocked",
|
||||
"admin.usage": "{used} of {quota}",
|
||||
"admin.noMailAccounts": "No mail accounts connected",
|
||||
"admin.userQuota": "Quota",
|
||||
"admin.blockedSince": "Blocked since {date}. This user cannot sign in.",
|
||||
"admin.block": "Block account",
|
||||
"admin.unblock": "Unblock account",
|
||||
"admin.blockConfirm":
|
||||
"Block {handle}? They are signed out everywhere and cannot sign in until you unblock them. Their mail and data are kept.",
|
||||
"admin.deleteUser": "Delete account",
|
||||
"admin.deleteConfirm":
|
||||
"Permanently delete {handle} and all of their mail, contacts, calendars and settings? This can't be undone.",
|
||||
"admin.selfNote": "This is your own account: it cannot be blocked or deleted from here.",
|
||||
"admin.cancel": "Cancel",
|
||||
"admin.close": "Close",
|
||||
"settings.jitsi": "Jitsi Meet",
|
||||
"settings.jitsiHint":
|
||||
"Server used to generate video-call links for calendar events. Leave empty to use the public https://meet.jit.si/ server.",
|
||||
|
||||
Reference in New Issue
Block a user