# Write verification emails Gmail can copy
URL: https://samva.dev/blog/write-verification-emails-gmail-can-copy
> Write a verification email with one code at the top of the text and HTML. Gmail's Copy code button is a reported app behavior, not a published sender rule.
- Published: 2026-10-16
- Author: [Saatvik Arya](https://samva.dev/authors/saatvik-arya)



Gmail on Android and iOS can show a Copy code button with a verification email, so the recipient can copy the code without selecting it by hand. Reports from September 2026 describe that button in the Gmail app. They do not describe a header the sender must set, and Google has not published a sender specification that makes the button appear.

Write the email for the person who has to use the code. Put one code in the first lines of the plain-text part and the HTML, name the action, and state the expiry your server enforces. An address confirmation can start from the [email verification template](/templates/email-verification). A code-only sign-in can start from the [one-time passcode template](/templates/one-time-passcode). Edit either one in the AI email editor, then send it through the email API.

## What the Copy code button is [#what-the-copy-code-button-is]

[9to5Google reported on September 19, 2026](https://9to5google.com/2026/09/19/gmail-copy-code/) that Gmail for Android version 2026.09.07.x and Gmail for iOS version 6.0.260907 show a pill under the subject. The pill includes the code, and tapping it copies the code to the clipboard. [The Verge, on September 21, 2026](https://www.theverge.com/tech/998084/gmail-copy-code-shortcut-2fa), described the same shortcut and said it was absent on the web.

Those are press reports, checked again on October 16, 2026. They are not a Google help document, and they do not list a message format that guarantees the button. A verification email still has to work when the button is missing: the recipient opens the message and reads the code.

## Put one code where a person looks first [#put-one-code-where-a-person-looks-first]

A useful code email answers three questions before the recipient scrolls.

| Question                   | Where to answer it                                    |
| -------------------------- | ----------------------------------------------------- |
| What is the code?          | The first lines of the plain-text part and the HTML   |
| What is it for?            | The subject, and the sentence under the code          |
| When does it stop working? | That same sentence, in the words your server enforces |

**One code.** A login link and a fallback code are two credentials. If you send both, say so, and accept both on the server for the same address and the same request. A second number beside the code, such as an order id or a support phone number, gives a person and a mailbox two candidates. Move those details below the code, or leave them out.

**Text, then HTML.** Send a plain-text part and an HTML part, with the same code in both. The text part is what many clients use for the inbox preview. The code is characters in that text. An image of the digits disappears in plain text and cannot be selected.

**Name the action.** "Your sign-in code" and "Confirm this email address" are different requests. A sign-in code should not silently double as an address confirmation or a password reset. The subject can name the action without repeating the code. A subject that contains the code also puts it on lock screens and in notifications. Prefer the body unless you have a reason to accept that exposure.

**Match the expiry.** Write "This code stops working 10 minutes after it was sent" only when the server invalidates it on that schedule. The [one-time passcode template](/templates/one-time-passcode) takes the expiry as input because the template does not read the clock.

**Say what to do if they did not ask.** Tell the recipient they can ignore the email and should not share the code. Give them a help address that works when they are signed out.

A mailbox that looks for a code has less to guess when the message contains one obvious code and little else that looks like one. That is a writing choice. It is not a published Gmail rule.

On the form that accepts the code, set the input's `autocomplete` to `one-time-code`, the [HTML autofill token](https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-autocomplete-one-time-code) for a one-time code. That attribute lives on your page. It is separate from the email.

## Send the email [#send-the-email]

Samva's email send takes the recipient, the subject, and the text and HTML. Pass an idempotency key for the challenge, not the code. Repeating the same key with the same body replays the original send. Reusing the key for a different body is a conflict.

```ts
import { createClient } from "samva";

const samva = createClient({ apiKey: process.env.SAMVA_API_KEY! });

// Replace 483921 with the code your server just issued. Do not reuse a preview value.
const code = "483921";
const challengeId = "chal_9f2c41b8";

await samva.email.send(
  {
    to: "ada@example.com",
    subject: "Your sign-in code",
    text: [
      code,
      "",
      "Use this code to sign in.",
      "This code stops working 10 minutes after it was sent.",
      "If you did not try to sign in, you can ignore this email.",
    ].join("\n"),
    html: [
      `<p style="font-size:28px;letter-spacing:0.08em">${code}</p>`,
      "<p>Use this code to sign in.</p>",
      "<p>This code stops working 10 minutes after it was sent.</p>",
      "<p>If you did not try to sign in, you can ignore this email.</p>",
    ].join(""),
  },
  { idempotencyKey: `sign-in-${challengeId}` },
);
```

The same call is `POST /v1/messages` with `channel` set to `email`. The [send guide](/docs/channels/email/send-an-email) shows the SDK, curl, and template forms. To send a published template, pass `templateId` or `templateSlug` with `templateData`, and omit the inline subject and body. That send renders the template's current publication, so a later publish changes the next send without a deploy.

The TypeScript SDK, the REST API, the CLI, and any MCP client that supports OAuth can make that send. [Better Auth](/docs/integrations/better-auth) can pass its verification and email OTP callbacks through the same API.

## OTP-Token is an emerging header [#otp-token-is-an-emerging-header]

An individual Internet-Draft, [draft-goto-otp-token-01](https://datatracker.ietf.org/doc/draft-goto-otp-token/) (Sam Goto and Mike West, September 21, 2026, expires March 25, 2027), proposes a machine-readable header so a mailbox can hand the code to the site that asked for it, and withhold it from a different site.

The draft's example is:

```text
OTP-Token: "123456"; origin="https://example.com"
```

Read on October 16, 2026, the draft says the header appears at most once. The code is a quoted string. An `origin` parameter is required: the ASCII form of a canonical web origin, lowercase, default ports omitted, and not the opaque origin `null`. Unknown parameters are ignored. The draft says it is work in progress. The IETF has not adopted it, and the draft says citing it as anything other than work in progress is inappropriate. Its security notes leave DKIM coverage of the header as an open question.

A Samva email send carries the subject and the text and HTML you pass. The payload has no field for a custom email header, so `OTP-Token` is not part of that request. The email you can ship is the one in the sections above.

## The server still owns the code [#the-server-still-owns-the-code]

The template displays the value you supply. Your application generates the code, binds it to the account and the purpose, limits attempts, and enforces expiry and one-time use. A delivered event means the receiving mail server accepted the email. It does not mark an address verified, and it does not create a session.

Keep the code out of URLs and query strings. Those end up in logs and referrer headers. Preserve leading zeroes: treat the code as a string, not a number.

If a resend issues a new code, say so on the entry screen, and test a delayed copy of the older email. The [email verification template](/templates/email-verification) page covers the link-and-code case, including what to do when the recipient did not request the email.

[Start sending](/signup) when the message is the one you want a person to open.
