fix: allow clearing optional SMTP and email template sender fields

Optional fields (senderEmail, replyToEmail, senderName, replyToName,
username, password) could not be cleared once set. The frontend used
|| undefined which silently dropped empty strings, so the backend
never received "" and the old value persisted on reload.

smtp/+page.svelte:
- Use ?? undefined instead of || undefined so empty strings are sent
- Fix isButtonDisabled deepEqual comparison: normalize types on both
  sides (?? '' for strings, ?? null for port, normalizeSecure() for
  secure) to avoid false positives from null/undefined mismatches
- Derive project from data.project so it stays reactive after
  invalidate() — fixes button not disabling after save without reload
- Remove second $effect that cleared fields on disable, which fought
  the first effect and kept the button permanently enabled

emailTemplate.svelte:
- Use ?? undefined instead of || undefined for sender/reply fields
- Add disabled={!isSmtpEnabled} to replyToEmail and replyToName,
  matching the existing behaviour of senderName and senderEmail
This commit is contained in:
harsh mahajan
2026-05-19 16:13:54 +05:30
parent eaf7927a08
commit d1806f5fb6
2 changed files with 48 additions and 56 deletions
@@ -63,10 +63,10 @@
locale,
subject: $emailTemplate.subject || undefined,
message: $emailTemplate.message || undefined,
senderName: $emailTemplate.senderName || undefined,
senderEmail: $emailTemplate.senderEmail || undefined,
replyToEmail: $emailTemplate.replyToEmail || undefined,
replyToName: $emailTemplate.replyToName || undefined
senderName: $emailTemplate.senderName ?? undefined,
senderEmail: $emailTemplate.senderEmail ?? undefined,
replyToEmail: $emailTemplate.replyToEmail ?? undefined,
replyToName: $emailTemplate.replyToName ?? undefined
});
$baseEmailTemplate = {
@@ -114,13 +114,15 @@
bind:value={$emailTemplate.replyToEmail}
id="replyToEmail"
label="Reply to email"
placeholder="noreply@appwrite.io" />
placeholder="noreply@appwrite.io"
disabled={!isSmtpEnabled} />
<InputText
bind:value={$emailTemplate.replyToName}
id="replyToName"
label="Reply to name"
placeholder="Enter reply to name" />
placeholder="Enter reply to name"
disabled={!isSmtpEnabled} />
{#if children}
<p class="text">
@@ -21,7 +21,7 @@
const { data }: PageProps = $props();
const { project } = data;
const project = $derived(data.project);
let enabled: boolean = $state(false);
@@ -44,31 +44,35 @@
{ value: '', label: 'None' }
];
function normalizeSecure(v: string): string {
return v === 'tls' || v === 'ssl' ? v : '';
}
const isButtonDisabled = $derived.by(() => {
return deepEqual(
{
enabled,
senderName,
senderEmail,
replyToEmail,
replyToName,
host,
port: port ?? '',
username,
password,
senderName: senderName ?? '',
senderEmail: senderEmail ?? '',
replyToEmail: replyToEmail ?? '',
replyToName: replyToName ?? '',
host: host ?? '',
port: port ?? null,
username: username ?? '',
password: password ?? '',
secure
},
{
enabled: project.smtpEnabled,
senderName: project.smtpSenderName,
senderEmail: project.smtpSenderEmail,
replyToEmail: project.smtpReplyToEmail,
replyToName: project.smtpReplyToName,
host: project.smtpHost,
port: project.smtpPort,
username: project.smtpUsername,
password: project.smtpPassword,
secure: project.smtpSecure
enabled: project.smtpEnabled ?? false,
senderName: project.smtpSenderName ?? '',
senderEmail: project.smtpSenderEmail ?? '',
replyToEmail: project.smtpReplyToEmail ?? '',
replyToName: project.smtpReplyToName ?? '',
host: project.smtpHost ?? '',
port: project.smtpPort ?? null,
username: project.smtpUsername ?? '',
password: project.smtpPassword ?? '',
secure: normalizeSecure(project.smtpSecure ?? '')
}
);
});
@@ -77,14 +81,14 @@
try {
await sdk.forProject(project.region, project.$id).project.updateSMTP({
enabled,
senderName: senderName || undefined,
senderEmail: senderEmail || undefined,
replyToEmail: replyToEmail || undefined,
replyToName: replyToName || undefined,
host: host || undefined,
port: port || undefined,
username: username || undefined,
password: password || undefined,
senderName: senderName ?? undefined,
senderEmail: senderEmail ?? undefined,
replyToEmail: replyToEmail ?? undefined,
replyToName: replyToName ?? undefined,
host: host ?? undefined,
port: port ?? undefined,
username: username ?? undefined,
password: password ?? undefined,
secure: secure ? (secure as ProjectSMTPSecure) : undefined
});
@@ -105,29 +109,15 @@
$effect(() => {
enabled = project.smtpEnabled ?? false;
senderName = project.smtpSenderName;
senderEmail = project.smtpSenderEmail;
replyToEmail = project.smtpReplyToEmail;
replyToName = project.smtpReplyToName;
host = project.smtpHost;
port = project.smtpPort;
username = project.smtpUsername;
password = project.smtpPassword;
secure = project.smtpSecure === 'tls' ? 'tls' : project.smtpSecure === 'ssl' ? 'ssl' : '';
});
$effect(() => {
if (!enabled) {
senderName = '';
senderEmail = '';
replyToEmail = '';
replyToName = '';
host = '';
port = null;
username = '';
password = '';
secure = '';
}
senderName = project.smtpSenderName ?? '';
senderEmail = project.smtpSenderEmail ?? '';
replyToEmail = project.smtpReplyToEmail ?? '';
replyToName = project.smtpReplyToName ?? '';
host = project.smtpHost ?? '';
port = project.smtpPort ?? null;
username = project.smtpUsername ?? '';
password = project.smtpPassword ?? '';
secure = normalizeSecure(project.smtpSecure ?? '');
});
</script>