---
title: Configuring your own HTTP Email
---

import { Code } from "@/components/Code"

# HTTP Email

We have a few built-in HTTP Email providers like [Resend](/getting-started/providers/resend), [SendGrid](/getting-started/providers/sendgrid) and [Postmark](/getting-started/providers/postmark), sometimes you may want to use your own HTTP endpoint to send emails.

To do this, we can write our own provider with a custom [`sendVerificationRequest`](/reference/core/providers/email#sendverificationrequest) method. Don't forget, an `email` type provider **requires** a database adapter.

<Code>
<Code.Next>

```ts filename="./auth.ts"
import NextAuth from "next-auth"
import { sendVerificationRequest } from "./lib/authSendRequest"

export const { handlers, auth } = NextAuth({
  adapter,
  providers: [
    {
      id: "http-email",
      name: "Email",
      type: "email",
      maxAge: 60 * 60 * 24, // Email link will expire in 24 hours
      sendVerificationRequest,
    },
  ],
})
```

</Code.Next>
<Code.Qwik>
  
```ts filename="/src/routes/plugin@auth.ts"
import { QwikAuth$ } from "@auth/qwik"
import { sendVerificationRequest } from "../lib/authSendRequest"

export const { onRequest, useSession, useSignIn, useSignOut } = QwikAuth$(
  () => ({
    providers: [
      {
        id: "http-email",
        name: "Email",
        type: "email",
        maxAge: 60 * 60 * 24, // Email link will expire in 24 hours
        sendVerificationRequest,
      },
    ],
  })
)
```

</Code.Qwik>
<Code.Svelte>

```ts filename="./src/auth.ts"
import SvelteKitAuth from "@auth/sveltekit"
import { sendVerificationRequest } from "../lib/authSendRequest"

export const { handle, auth } = SvelteKitAuth({
  adapter,
  providers: [
    {
      id: "http-email",
      name: "Email",
      type: "email",
      maxAge: 60 * 60 * 24, // Email link will expire in 24 hours
      sendVerificationRequest,
    },
  ],
})
```

</Code.Svelte>
<Code.Express>

```ts filename="./src/routes/auth.route.ts"
import { ExpressAuth } from "@auth/express"
import { sendVerificationRequest } from "../lib/authSendRequest"
import express from "express"

const app = express()

app.set("trust proxy", true)
app.use(
  "/auth/*",
  ExpressAuth({
    adapter,
    providers: [
      {
        id: "http-email",
        name: "Email",
        type: "email",
        maxAge: 60 * 60 * 24, // Email link will expire in 24 hours
        sendVerificationRequest,
      },
    ],
  })
)
```

</Code.Express>
</Code>

After we've setup the initial configuration, you've got to write `sendVerificationRequest` function. Below is a simple version which just sends a text email with a link to the user.

```ts filename="./lib/authSendRequest.ts"
export async function sendVerificationRequest({ identifier: email, url }) {
  // Call the cloud Email provider API for sending emails
  const response = await fetch("https://api.sendgrid.com/v3/mail/send", {
    // The body format will vary depending on provider, please see their documentation
    body: JSON.stringify({
      personalizations: [{ to: [{ email }] }],
      from: { email: "noreply@company.com" },
      subject: "Sign in to Your page",
      content: [
        {
          type: "text/plain",
          value: `Please click here to authenticate - ${url}`,
        },
      ],
    }),
    headers: {
      // Authentication will also vary from provider to provider, please see their docs.
      Authorization: `Bearer ${process.env.SENDGRID_API}`,
      "Content-Type": "application/json",
    },
    method: "POST",
  })

  if (!response.ok) {
    const { errors } = await response.json()
    throw new Error(JSON.stringify(errors))
  }
}
```

A more advanced `sendVerificationRequest` can be seen below, this is a version of the builtin function.

```ts filename="./lib/authSendRequest.ts"
export async function sendVerificationRequest(params) {
  const { identifier: to, provider, url, theme } = params
  const { host } = new URL(url)
  const res = await fetch("https://api.resend.com/emails", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${provider.apiKey}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      from: provider.from,
      to,
      subject: `Sign in to ${host}`,
      html: html({ url, host, theme }),
      text: text({ url, host }),
    }),
  })

  if (!res.ok)
    throw new Error("Resend error: " + JSON.stringify(await res.json()))
}

function html(params: { url: string; host: string; theme: Theme }) {
  const { url, host, theme } = params

  const escapedHost = host.replace(/\./g, "&#8203;.")

  const brandColor = theme.brandColor || "#346df1"
  const color = {
    background: "#f9f9f9",
    text: "#444",
    mainBackground: "#fff",
    buttonBackground: brandColor,
    buttonBorder: brandColor,
    buttonText: theme.buttonText || "#fff",
  }

  return `
<body style="background: ${color.background};">
  <table width="100%" border="0" cellspacing="20" cellpadding="0"
    style="background: ${color.mainBackground}; max-width: 600px; margin: auto; border-radius: 10px;">
    <tr>
      <td align="center"
        style="padding: 10px 0px; font-size: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
        Sign in to <strong>${escapedHost}</strong>
      </td>
    </tr>
    <tr>
      <td align="center" style="padding: 20px 0;">
        <table border="0" cellspacing="0" cellpadding="0">
          <tr>
            <td align="center" style="border-radius: 5px;" bgcolor="${color.buttonBackground}"><a href="${url}"
                target="_blank"
                style="font-size: 18px; font-family: Helvetica, Arial, sans-serif; color: ${color.buttonText}; text-decoration: none; border-radius: 5px; padding: 10px 20px; border: 1px solid ${color.buttonBorder}; display: inline-block; font-weight: bold;">Sign
                in</a></td>
          </tr>
        </table>
      </td>
    </tr>
    <tr>
      <td align="center"
        style="padding: 0px 0px 10px 0px; font-size: 16px; line-height: 22px; font-family: Helvetica, Arial, sans-serif; color: ${color.text};">
        If you did not request this email you can safely ignore it.
      </td>
    </tr>
  </table>
</body>
`
}
```

To sign in via this custom provider, you would refer to it by the id in when you are calling the sign-in method, for example: `signIn('http-email', { email: 'user@company.com' })`.
