Closed kangmingtay closed 2 years ago
@kangmingtay Thanks for getting this onto the backlog. I've put some context and ideas below.
We (@WorkniceHR) are using the POST /admin/generate_link
endpoint (via the gotrue-js client) to populate links in custom emails we send out when inviting users, resetting passwords, confirming account creation etc. The templates for these emails are part of our codebase (not configuration) so that we can fully personalise them with the user's name, organisation, branding etc.
The one scenario where we can't send out fully custom emails is when a user updates their email address and need to confirm their old and new addresses. We'd like to be able to use the POST /admin/generate_link
endpoint (or similar) for this too instead of relying on configured email templates.
The confirmation emails are currently sent out as a side-effect of editing the user. If we're generating our own link and sending them ourselves we don't won't confirmations email getting sent automatically.
This change seems fairly straightforward. Either a config variable can be added (something like MAILER_DISABLE_AUTO_CONFIRM_ON_EMAIL_CHANGE
) or an options
field can be added to the PUT /user
endpoint:
# PUT /user
{
"email": "new-email@example.com",
"options": {
"sendConfirmationEmails": false,
}
}
I think I prefer the addition of an option
field as it feels closer to the existing API design.
The exisiting POST /admin/generate_link
endpoint doesn't lend itself naturally to this use. The biggest difference seems to be the need to generate multiple links (one to confirm the old address and one for the new address). I'm not familiar enough with GoTrue to understand all the trade-offs, but intuitively it feels like a separate PUT /user/email
endpoint for changing email addresses makes sense (and can be backwards compatible).
For anyone who's keen on attempting this, else we'll get to fixing / adding this soon:
type=email_change
for the POST /admin/generate_link
endpoint to allow developers to generate their own email change links
a. Need to include the secure option where 2 links are generated (one for the old email, and one for the new email)PUT /user/email
should accept a query param (shouldSendEmail
) to allow disabling sending of email confirmation links if the email is updated. (Note that this doesn't imply that the user should be automatically confirmed - it just prevents gotrue from sending out the email confirmation link and (1) needs to be carried out else the user's new email will remain unconfirmed) For anyone who's keen on attempting this, else we'll get to fixing / adding this soon:
- Need an additional
type=email_change
for thePOST /admin/generate_link
endpoint to allow developers to generate their own email change links a. Need to include the secure option where 2 links are generated (one for the old email, and one for the new email)PUT /user/email
should accept a query param (shouldSendEmail
) to allow disabling sending of email confirmation links if the email is updated. (Note that this doesn't imply that the user should be automatically confirmed - it just prevents gotrue from sending out the email confirmation link and (1) needs to be carried out else the user's new email will remain unconfirmed)
I opened a PR(#365) for this issue, but that is not exactly like this, but I will modify again.
PR is ready for review
For anyone who's keen on attempting this, else we'll get to fixing / adding this soon:
- Need an additional
type=email_change
for thePOST /admin/generate_link
endpoint to allow developers to generate their own email change links a. Need to include the secure option where 2 links are generated (one for the old email, and one for the new email)PUT /user/email
should accept a query param (shouldSendEmail
) to allow disabling sending of email confirmation links if the email is updated. (Note that this doesn't imply that the user should be automatically confirmed - it just prevents gotrue from sending out the email confirmation link and (1) needs to be carried out else the user's new email will remain unconfirmed)I opened a PR(#365) for this issue, but that is not exactly like this, but I will modify again.
Hey support for this was added in #560.
@haydn not sure if this is the right place for this but what is the email provider / setup that you are using to do this? I would love to do the same.
Hey @ForgeSolutions-JBrenner, no problem!
It's a Next.js app hosted on Vercel. We're using Postmark for email delivery and MJML to generate the email HTML.
Here's what an "invite" email looks like with this setup:
const InviteEmail = ({
accountName,
accountLogo,
recipientName,
acceptUrl,
color = "#90116e",
}: Props) => (
<Mjml>
<MjmlHead>
<MjmlTitle>{`You've been invited to ${accountName}`}</MjmlTitle>
<MjmlAttributes>
<MjmlButton
backgroundColor={color}
borderRadius={6}
padding={20}
/>
<MjmlText align="center" />
</MjmlAttributes>
</MjmlHead>
<MjmlBody>
<MjmlSection>
<MjmlColumn>
{accountLogo ? (
<MjmlImage
src={accountLogo}
width={360}
alt={accountName}
href="https://worknice.com"
/>
) : null}
<MjmlText>
<h1>
You've been invited to
<br />
{accountName}
</h1>
</MjmlText>
<MjmlText>
<p>
Hi {recipientName}, {accountName} uses Worknice to manage its HR. You've been
invited to create an account.
</p>
</MjmlText>
<MjmlButton href={acceptUrl}>Create Your Account</MjmlButton>
</MjmlColumn>
</MjmlSection>
</MjmlBody>
</Mjml>
);
Sending an invite email is along these lines:
import { ServerClient } from "postmark";
import { createClient } from "@supabase/supabase-js";
import { render } from "mjml-react";
const postmark = new ServerClient(POSTMARK_TOKEN);
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
const email = "jane.doe@example.com";
await supabase.auth.api.createUser({ email });
const { data: linkData } = await supabase.auth.api.generateLink(
"invite",
email
);
const { html } = render(
<InviteEmail
accountName="Example"
accountLogo="https://www.placecage.com/360/270"
recipientName="Jane Doe"
acceptUrl={`${BASE_URL}/accept-invite#otp=${
linkData.email_otp
}&email=${encodeURIComponent(email)}`}
/>,
{ validationLevel: "strict" }
);
await postmark.sendEmail({
From: "noreply@worknice.com",
To: email,
Subject: "You've been invited to Example",
HtmlBody: html,
MessageStream: "outbound",
});
Verifying the OTP once the user has followed the link in the email is like this:
await supabase.auth.api.verifyOTP({
email,
token: otp,
type: "invite",
});
(NB: This is using supabase-js
v1, I'm assuming the API has changed a bit in v2.)
@haydn Thank you so much for this! You are the absolute best 🤓
Discussed in https://github.com/supabase/supabase/discussions/5125