When a user on your customer's app resets their password, the email that lands in their inbox is part of your customer's brand, or it should be. Out of the box, those messages go through Appwrite's shared sender and carry Appwrite's default templates, which quietly breaks the white-label illusion the moment a user reads the "from" line. The Project API lets you route a project's mail through the customer's own SMTP server and rewrite every template, so verification, recovery, and invitation emails come from the customer's domain and read in their voice.
This guide:
- Points a project at the customer's SMTP server.
- Confirms that mail is reaching the inbox.
- Rebrands a template in the customer's voice.
Required scopes
The SMTP calls need the project.write scope, and the template calls need the templates.write scope.
Configure custom SMTP
Set up the client, then hand the project the customer's SMTP credentials and the sender identity their recipients should see in the inbox. The password is write-only, so it is stored securely and never comes back in a response.
import { Client, Project, ProjectSMTPSecure } from 'node-appwrite';
const client = new Client()
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
.setProject('<PROJECT_ID>')
.setKey('<YOUR_API_KEY>');
const project = new Project(client);
const result = await project.updateSMTP({
host: 'smtp.example.com',
port: 587,
username: '<USERNAME>', // optional
password: '<PASSWORD>', // optional
senderEmail: 'email@example.com',
senderName: '<SENDER_NAME>', // optional
replyToEmail: 'email@example.com', // optional
replyToName: '<REPLY_TO_NAME>', // optional
secure: ProjectSMTPSecure.Tls, // optional
enabled: true
});
Enabling SMTP validates the connection
The moment you enable custom SMTP, Appwrite tries to connect to the host you gave it, so the server has to be reachable with those exact credentials or the call fails. Custom SMTP is also the prerequisite for everything below: you cannot customize email templates until it is enabled.
Send a test email
Do not wait for a real password reset to find out the configuration is wrong. Send yourself a test message, which goes out through the SMTP settings you just saved, and a message arriving in the inbox confirms the whole path end to end.
const result = await project.createSMTPTest({
emails: ['email@example.com']
});
Customize a template
With mail flowing through the customer's server, rebrand the messages themselves. Set the subject, body, and sender for a template in a given locale, and repeat per locale to localize. This example rewrites the verification email.
const result = await project.updateEmailTemplate({
templateId: ProjectEmailTemplateId.Verification,
locale: ProjectEmailTemplateLocale.En, // optional
subject: '<SUBJECT>', // optional
message: '<MESSAGE>', // optional
senderName: '<SENDER_NAME>', // optional
senderEmail: 'email@example.com', // optional
replyToEmail: 'email@example.com', // optional
replyToName: '<REPLY_TO_NAME>' // optional
});
The template ID is one of verification, magicSession, recovery, invitation, mfaChallenge, sessionAlert, or otpSession.
Read templates back
Read a template back to check the copy that is live, which is worth doing whenever you let a customer edit their own templates through your dashboard.
const result = await project.getEmailTemplate({
templateId: ProjectEmailTemplateId.Verification,
locale: ProjectEmailTemplateLocale.En // optional
});
Or list the project's templates to see everything you have overridden in one call.
const result = await project.listEmailTemplates({
queries: [], // optional
total: false // optional
});
Next steps
With SMTP and templates driven from code, every customer's project sends mail that carries their brand rather than yours. From here:
- Provision a project's baseline so branding the emails is one step in onboarding.
- Read the SMTP and Email templates references for every field you can set.