Customize Email Handling

Customize Email Handling

Our default email flow can address the requirements of most applications. Sometimes, however, you may require more flexibility, such as when implementing:

  • localization

  • custom Redirect To URLs based on user or tenant

  • different email templates per application or tenant

The Auth0 Management API provides endpoints to help you manage your email flow to control when and how emails are sent. If necessary, you can also implement your own Custom Email endpoints and use the Auth0 Management API endpoints to help manage the rest of the flow.

Verification emails

A verification email should be sent to every user for which the email_verified property is false. Typically, these are users in database connections or users authenticating with social providers that do not validate email addresses upon new user registration.

Send verification email with Management API

The Send an email address verification email endpoint sends the user an email prompting them to verify their email address.


curl --request POST \
  --url 'https://YOUR_DOMAIN/api/v2/jobs/verification-email' \
  --header 'authorization: Bearer MGMT_API_ACCESS_TOKEN' \
  --header 'content-type: application/json' \
  --data '{ "user_id": "USER_ID_TO_SEND_VERIFY_EMAIL_TO", "client_id": "YOUR_APPLICATION_CLIENT_ID","identity": {"user_id": "5457edea1b8f22891a000004","provider": "google-oauth2"}, "organization_id": "YOUR_ORGANIZATION_ID" }'

Was this helpful?

/
var client = new RestClient("https://YOUR_DOMAIN/api/v2/jobs/verification-email");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "application/json");
request.AddHeader("authorization", "Bearer MGMT_API_ACCESS_TOKEN");
request.AddParameter("application/json", "{ \"user_id\": \"USER_ID_TO_SEND_VERIFY_EMAIL_TO\", \"client_id\": \"YOUR_APPLICATION_CLIENT_ID\",\"identity\": {\"user_id\": \"5457edea1b8f22891a000004\",\"provider\": \"google-oauth2\"}, \"organization_id\": \"YOUR_ORGANIZATION_ID\" }", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);

Was this helpful?

/
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io/ioutil"
)

func main() {

	url := "https://YOUR_DOMAIN/api/v2/jobs/verification-email"

	payload := strings.NewReader("{ \"user_id\": \"USER_ID_TO_SEND_VERIFY_EMAIL_TO\", \"client_id\": \"YOUR_APPLICATION_CLIENT_ID\",\"identity\": {\"user_id\": \"5457edea1b8f22891a000004\",\"provider\": \"google-oauth2\"}, \"organization_id\": \"YOUR_ORGANIZATION_ID\" }")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("content-type", "application/json")
	req.Header.Add("authorization", "Bearer MGMT_API_ACCESS_TOKEN")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := ioutil.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}

Was this helpful?

/
HttpResponse<String> response = Unirest.post("https://YOUR_DOMAIN/api/v2/jobs/verification-email")
  .header("content-type", "application/json")
  .header("authorization", "Bearer MGMT_API_ACCESS_TOKEN")
  .body("{ \"user_id\": \"USER_ID_TO_SEND_VERIFY_EMAIL_TO\", \"client_id\": \"YOUR_APPLICATION_CLIENT_ID\",\"identity\": {\"user_id\": \"5457edea1b8f22891a000004\",\"provider\": \"google-oauth2\"}, \"organization_id\": \"YOUR_ORGANIZATION_ID\" }")
  .asString();

Was this helpful?

/
var axios = require("axios").default;

var options = {
  method: 'POST',
  url: 'https://YOUR_DOMAIN/api/v2/jobs/verification-email',
  headers: {
    'content-type': 'application/json',
    authorization: 'Bearer MGMT_API_ACCESS_TOKEN'
  },
  data: {
    user_id: 'USER_ID_TO_SEND_VERIFY_EMAIL_TO',
    client_id: 'YOUR_APPLICATION_CLIENT_ID',
    identity: {user_id: '5457edea1b8f22891a000004', provider: 'google-oauth2'},
    organization_id: 'YOUR_ORGANIZATION_ID'
  }
};

axios.request(options).then(function (response) {
  console.log(response.data);
}).catch(function (error) {
  console.error(error);
});

Was this helpful?

/
#import <Foundation/Foundation.h>

NSDictionary *headers = @{ @"content-type": @"application/json",
                           @"authorization": @"Bearer MGMT_API_ACCESS_TOKEN" };
NSDictionary *parameters = @{ @"user_id": @"USER_ID_TO_SEND_VERIFY_EMAIL_TO",
                              @"client_id": @"YOUR_APPLICATION_CLIENT_ID",
                              @"identity": @{ @"user_id": @"5457edea1b8f22891a000004", @"provider": @"google-oauth2" },
                              @"organization_id": @"YOUR_ORGANIZATION_ID" };

NSData *postData = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:nil];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"https://YOUR_DOMAIN/api/v2/jobs/verification-email"]
                                                       cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                   timeoutInterval:10.0];
[request setHTTPMethod:@"POST"];
[request setAllHTTPHeaderFields:headers];
[request setHTTPBody:postData];

NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
                                            completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                                if (error) {
                                                    NSLog(@"%@", error);
                                                } else {
                                                    NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
                                                    NSLog(@"%@", httpResponse);
                                                }
                                            }];
[dataTask resume];

Was this helpful?

/
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => "https://YOUR_DOMAIN/api/v2/jobs/verification-email",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "{ \"user_id\": \"USER_ID_TO_SEND_VERIFY_EMAIL_TO\", \"client_id\": \"YOUR_APPLICATION_CLIENT_ID\",\"identity\": {\"user_id\": \"5457edea1b8f22891a000004\",\"provider\": \"google-oauth2\"}, \"organization_id\": \"YOUR_ORGANIZATION_ID\" }",
  CURLOPT_HTTPHEADER => [
    "authorization: Bearer MGMT_API_ACCESS_TOKEN",
    "content-type: application/json"
  ],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
  echo "cURL Error #:" . $err;
} else {
  echo $response;
}

Was this helpful?

/
import http.client

conn = http.client.HTTPSConnection("")

payload = "{ \"user_id\": \"USER_ID_TO_SEND_VERIFY_EMAIL_TO\", \"client_id\": \"YOUR_APPLICATION_CLIENT_ID\",\"identity\": {\"user_id\": \"5457edea1b8f22891a000004\",\"provider\": \"google-oauth2\"}, \"organization_id\": \"YOUR_ORGANIZATION_ID\" }"

headers = {
    'content-type': "application/json",
    'authorization': "Bearer MGMT_API_ACCESS_TOKEN"
    }

conn.request("POST", "/YOUR_DOMAIN/api/v2/jobs/verification-email", payload, headers)

res = conn.getresponse()
data = res.read()

print(data.decode("utf-8"))

Was this helpful?

/
require 'uri'
require 'net/http'
require 'openssl'

url = URI("https://YOUR_DOMAIN/api/v2/jobs/verification-email")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

request = Net::HTTP::Post.new(url)
request["content-type"] = 'application/json'
request["authorization"] = 'Bearer MGMT_API_ACCESS_TOKEN'
request.body = "{ \"user_id\": \"USER_ID_TO_SEND_VERIFY_EMAIL_TO\", \"client_id\": \"YOUR_APPLICATION_CLIENT_ID\",\"identity\": {\"user_id\": \"5457edea1b8f22891a000004\",\"provider\": \"google-oauth2\"}, \"organization_id\": \"YOUR_ORGANIZATION_ID\" }"

response = http.request(request)
puts response.read_body

Was this helpful?

/
import Foundation

let headers = [
  "content-type": "application/json",
  "authorization": "Bearer MGMT_API_ACCESS_TOKEN"
]
let parameters = [
  "user_id": "USER_ID_TO_SEND_VERIFY_EMAIL_TO",
  "client_id": "YOUR_APPLICATION_CLIENT_ID",
  "identity": [
    "user_id": "5457edea1b8f22891a000004",
    "provider": "google-oauth2"
  ],
  "organization_id": "YOUR_ORGANIZATION_ID"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://YOUR_DOMAIN/api/v2/jobs/verification-email")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()

Was this helpful?

/

Send verification email with Rules

Using Auth0 Rules, you can call your API when a user logs in for the first time with an email address that has not been verified. After calling your API, add a flag to the user's profile metadata that indicates that the verification email has been sent:

function (user, context, callback) {

  const request = require('request');

  user.user_metadata = user.user_metadata || {};
  if (user.email_verified || user.user_metadata.verification_email_sent) {
    return callback(null, user, context);
  }

  request.post({
    url: 'https://yourapi.yourcompany.com/mail/verification',
    json: {
      user: user,
      context: context,
      secretToken: configuration.MY_SECRET_TOKEN,
    },
    timeout: 5000
  }, function(err, response, body){
    if (err)
      return callback(new Error(err));

    // Email sent flag persisted in the user's profile.
    user.user_metadata.verification_email_sent = true;
    auth0.users.updateUserMetadata(user.user_id, user.user_metadata)
      .then(function() {
        callback(null, user, context);
      })
      .catch(function(err) {
        callback(err);
      });
    return callback(null, user, context);
  });
}

Was this helpful?

/

Require verified email for login

You can require users to verify their email before logging in with a rule:

function (user, context, callback) {
  if (!user.email_verified) {
    return callback(new UnauthorizedError('Please verify your email before logging in.'));
  } else {
    return callback(null, user, context);
  }
}

Was this helpful?

/

Custom redirects

A custom redirect is useful when you want to direct users to certain URLs based on user attributes or on the tenant. The Auth0 Management API provides a Create Email Verification Ticket endpoint that generates the verification link for each user. This endpoint allows you to specify the result_url to which users will be redirected after they have validated their email address by clicking the link in the verification email.

We recommend AllowList the URL in the Auth0 Dashboard. For details, see Add Addresses to AllowList.

Welcome emails

A welcome email is sent to users once they have verified their email address.

Send welcome email using your own API

Using a rule, you can call your API to send a welcome email only if the user's email address has been verified and the email has not been sent previously.

function (user, context, callback) {

  const request = require('request');

  if (!user.email_verified || user.welcome_email_sent) {
    return callback(null, user, context);
  }

  request.post({
    url: 'https://yourapi.yourcompany.com/mail/welcome',
    json: {
      user: user,
      context: context,
      secretToken: configuration.MY_SECRET_TOKEN,
    },
    timeout: 5000
  }, function(err, response, body){
    if (err)
      return callback(new Error(err));

    // Email sent flag persisted in the user's profile.
    user.app_metadata.welcome_email_sent = true;
    return callback(null, user, context);
  });
}

Was this helpful?

/

Change password confirmation emails

To handle password change requests, you will need to host a form to capture the user's new password, and post it to the Create Password Change Ticket endpoint in the new_password parameter. Calling this endpoint will generate a Change Password Confirmation link. With it, you can send the user an email containing the link. When the user clicks the link, they can update their password.

Alternatively, if you invoke the endpoint without specifying the new_password parameter, the link in the email will redirect the user to a page prompting them to set a new password.

Manage Email Flow Change Password Confirmation Email Flow Diagram

Learn more