From 8a4d2e17fc42e2c010dfd616c3c6e1c701698d94 Mon Sep 17 00:00:00 2001
From: Akash M <38563661+AkashM398@users.noreply.github.com>
Date: Mon, 9 Mar 2026 13:54:49 +0530
Subject: [PATCH] fix: trim leading/trailing whitespaces from SMTP settings
input fields (#43530)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
## I have read the
[CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md)
file.
YES
## What kind of change does this PR introduce?
Bug fix
## What is the current behavior?
Currently, the SMTP Host input field in the Project Dashboard
(Authentication > Email > SMTP Settings) does not sanitize whitespace.
If a user accidentally pastes a hostname with leading or trailing spaces
(e.g., " smtp.resend.com "), the DNS lookup fails during the OTP
delivery process.
This results in the following error in the Auth logs:
```"dial tcp: lookup smtp.resend.com on 127.0.0.53:53: server misbehaving"```
Noticed, the other input fields of Sender details and Host, Username and Password under SMTP Provider settings take leading and trailing whitespaces as well.
## What is the new behavior?
Input sanitization has been applied across the SMTP configuration schema. The following fields now utilize .trim() to ensure data integrity:
- SMTP_HOST
- SMTP_ADMIN_EMAIL & SMTP_SENDER_NAME
- SMTP_USER
- SMTP_PASS
## Screenshots:
Before Fix:
After Fix:
This fixes the issue #43529
---------
Co-authored-by: Joshen Lim
---
.../interfaces/Auth/SmtpForm/SmtpForm.tsx | 78 +++++++++++--------
1 file changed, 45 insertions(+), 33 deletions(-)
diff --git a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx
index 90abb84ebbe..56a3d6d9ead 100644
--- a/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx
+++ b/apps/studio/components/interfaces/Auth/SmtpForm/SmtpForm.tsx
@@ -1,11 +1,5 @@
import { yupResolver } from '@hookform/resolvers/yup'
import { PermissionAction } from '@supabase/shared-types/out/constants'
-import { Eye, EyeOff } from 'lucide-react'
-import { useEffect, useState } from 'react'
-import { useForm } from 'react-hook-form'
-import { toast } from 'sonner'
-import * as yup from 'yup'
-
import { useParams } from 'common'
import AlertError from 'components/ui/AlertError'
import { InlineLink } from 'components/ui/InlineLink'
@@ -13,21 +7,27 @@ import NoPermission from 'components/ui/NoPermission'
import { useAuthConfigQuery } from 'data/auth/auth-config-query'
import { useAuthConfigUpdateMutation } from 'data/auth/auth-config-update-mutation'
import { useAsyncCheckPermissions } from 'hooks/misc/useCheckPermissions'
+import { Eye, EyeOff } from 'lucide-react'
+import { useEffect, useState } from 'react'
+import { useForm } from 'react-hook-form'
+import { toast } from 'sonner'
import {
Button,
Card,
CardContent,
CardFooter,
+ cn,
+ Form_Shadcn_,
FormControl_Shadcn_,
FormField_Shadcn_,
- Form_Shadcn_,
Input_Shadcn_,
PrePostTab,
Switch,
- cn,
} from 'ui'
import { Admonition, PageSection, PageSectionContent } from 'ui-patterns'
import { FormItemLayout } from 'ui-patterns/form/FormItemLayout/FormItemLayout'
+import * as yup from 'yup'
+
import { urlRegex } from '../Auth.constants'
import { defaultDisabledSmtpFormValues } from './SmtpForm.constants'
import { generateFormValues, isSmtpEnabled } from './SmtpForm.utils'
@@ -61,25 +61,34 @@ export const SmtpForm = () => {
)
const smtpSchema = yup.object({
- SMTP_ADMIN_EMAIL: yup.string().when('ENABLE_SMTP', {
- is: true,
- then: (schema) =>
- schema.email('Must be a valid email').required('Sender email address is required'),
- otherwise: (schema) => schema,
- }),
- SMTP_SENDER_NAME: yup.string().when('ENABLE_SMTP', {
- is: true,
- then: (schema) => schema.required('Sender name is required'),
- otherwise: (schema) => schema,
- }),
- SMTP_HOST: yup.string().when('ENABLE_SMTP', {
- is: true,
- then: (schema) =>
- schema
- .matches(urlRegex({ excludeSimpleDomains: false }), 'Must be a valid URL or IP address')
- .required('Host URL is required.'),
- otherwise: (schema) => schema,
- }),
+ SMTP_ADMIN_EMAIL: yup
+ .string()
+ .trim()
+ .when('ENABLE_SMTP', {
+ is: true,
+ then: (schema) =>
+ schema.email('Must be a valid email').required('Sender email address is required'),
+ otherwise: (schema) => schema,
+ }),
+ SMTP_SENDER_NAME: yup
+ .string()
+ .trim()
+ .when('ENABLE_SMTP', {
+ is: true,
+ then: (schema) => schema.required('Sender name is required'),
+ otherwise: (schema) => schema,
+ }),
+ SMTP_HOST: yup
+ .string()
+ .trim()
+ .when('ENABLE_SMTP', {
+ is: true,
+ then: (schema) =>
+ schema
+ .matches(urlRegex({ excludeSimpleDomains: false }), 'Must be a valid URL or IP address')
+ .required('Host URL is required.'),
+ otherwise: (schema) => schema,
+ }),
SMTP_PORT: yup.number().when('ENABLE_SMTP', {
is: true,
then: (schema) =>
@@ -98,12 +107,15 @@ export const SmtpForm = () => {
.max(32767, 'Must not be more than 32,767 an hour'),
otherwise: (schema) => schema,
}),
- SMTP_USER: yup.string().when('ENABLE_SMTP', {
- is: true,
- then: (schema) => schema.required('SMTP Username is required'),
- otherwise: (schema) => schema,
- }),
- SMTP_PASS: yup.string(),
+ SMTP_USER: yup
+ .string()
+ .trim()
+ .when('ENABLE_SMTP', {
+ is: true,
+ then: (schema) => schema.required('SMTP Username is required'),
+ otherwise: (schema) => schema,
+ }),
+ SMTP_PASS: yup.string().trim(),
ENABLE_SMTP: yup.boolean().required(),
})