> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hexclave.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SendEmailOptions

> Reference for the SendEmailOptions type used with the sendEmail method.

export const MethodLayout = ({children}) => <div className="grid gap-4 md:grid-cols-2 md:items-start xl:gap-6">
    {children}
  </div>;

export const MethodContent = ({children}) => <div className="min-w-0 space-y-4">{children}</div>;

export const MethodAside = ({title, children}) => <div className="min-w-0 self-start space-y-4 rounded-2xl border border-zinc-950/10 bg-zinc-950/[0.02] p-4 dark:border-white/10 dark:bg-white/[0.03]">
    {title ? <p className="m-0 text-sm font-medium text-zinc-950 dark:text-white">{title}</p> : null}
    <div className="space-y-4">{children}</div>
  </div>;

export const CollapsibleTypesSection = ({type, property, signature, defaultOpen = false, deprecated = false, badge, children}) => {
  const id = `${String(type ?? "").toLowerCase().replace(/[^a-z0-9]/g, "")}${String(property ?? "").toLowerCase().replace(/[^a-z0-9]/g, "")}`;
  const [isOpen, setIsOpen] = useState(defaultOpen);
  useEffect(() => {
    if (typeof window === "undefined") {
      return undefined;
    }
    const syncWithHash = () => {
      if (window.location.hash === `#${id}`) {
        setIsOpen(true);
      }
    };
    syncWithHash();
    window.addEventListener("hashchange", syncWithHash);
    return () => window.removeEventListener("hashchange", syncWithHash);
  }, [id]);
  const label = signature ? `${property}(${signature})` : property;
  const fullLabel = type ? `${type}.${label}` : label;
  return <details id={id} open={isOpen} onToggle={event => setIsOpen(event.currentTarget.open)} className={`not-prose my-4 scroll-mt-24 overflow-hidden rounded-2xl border bg-white dark:bg-zinc-950 ${deprecated ? "border-orange-400/40 dark:border-orange-500/30" : "border-zinc-950/10 dark:border-white/10"}`}>
      <summary className="cursor-pointer list-none px-4 py-4 [&::-webkit-details-marker]:hidden">
        <div className="flex items-center gap-3">
          <code className={`text-[15px] font-medium ${deprecated ? "text-zinc-500 line-through decoration-zinc-400/60 dark:text-zinc-400 dark:decoration-zinc-500/60" : "text-zinc-950 dark:text-white"}`}>{fullLabel}</code>
          <span className="ml-auto flex items-center gap-2">
            {deprecated ? <Badge color="orange" size="sm" shape="pill">deprecated</Badge> : null}
            {badge ?? null}
            <span aria-hidden="true" className="text-sm text-zinc-500 transition-transform dark:text-zinc-400">
              {isOpen ? "▾" : "›"}
            </span>
          </span>
        </div>
      </summary>

      <div className="border-t border-zinc-950/10 px-4 py-5 dark:border-white/10">
        {children}
      </div>
    </details>;
};

export const ClickableTableOfContents = ({title, code}) => {
  const lines = String(code ?? "").replace(/\r\n/g, "\n").split("\n");
  return <div className="not-prose my-6 overflow-hidden rounded-2xl border border-zinc-950/10 bg-zinc-950/[0.03] dark:border-white/10 dark:bg-white/[0.03]">
      {title ? <div className="border-b border-zinc-950/10 px-4 py-3 text-sm font-medium text-zinc-950/80 dark:border-white/10 dark:text-white/80">
          {title}
        </div> : null}

      <pre className="overflow-x-auto px-2 py-3 text-[13px] leading-6 text-zinc-900 dark:text-zinc-100">
        <code>
          {lines.map((line, index) => {
    if (line.trim().startsWith("// NEXT_LINE_PLATFORM")) {
      return null;
    }
    const match = line.match(/^(.*?)(?:\s*\/\/\s*\$stack-link-to:(#[a-zA-Z0-9_-]+))\s*$/);
    const href = match?.[2] ?? null;
    const text = match?.[1] ?? line;
    if (text.trim() === "") {
      return <span key={`blank-${index}`} className="block h-6" />;
    }
    const content = <span className="block whitespace-pre rounded-lg px-3 py-0.5">
                {text.replace(/\s+$/, "")}
              </span>;
    if (!href) {
      return <span key={`line-${index}`} className="block text-zinc-700 dark:text-zinc-300">
                  {content}
                </span>;
    }
    return <a key={`line-${index}`} href={href} className="block no-underline transition-colors hover:bg-zinc-950/[0.04] hover:text-zinc-950 dark:hover:bg-white/[0.05] dark:hover:text-white">
                {content}
              </a>;
  })}
        </code>
      </pre>
    </div>;
};

export const AsideSection = ({title, children}) => <div className="space-y-3">
    {title ? <p className="m-0 text-sm font-medium text-zinc-950 dark:text-white">{title}</p> : null}
    <div className="space-y-3">{children}</div>
  </div>;

export const EmailSection = props => <CollapsibleTypesSection badge={<Badge color="green" size="sm" shape="pill">
        sendEmailOptions
      </Badge>} {...props} />;

This is a detailed reference for email-related types in Hexclave. If you're looking for a more high-level overview, please refer to our [guide on the email system](/guides/apps/emails/overview).

# `SendEmailOptions`

Options for sending emails via the `sendEmail` method on `HexclaveServerApp`.

## Table of Contents

<ClickableTableOfContents
  title="SendEmailOptions Table of Contents"
  code={`type SendEmailOptions = {
// Recipients (one of the following):
userIds?: string[]; //$stack-link-to:#sendemailoptionsuserids
allUsers?: true; //$stack-link-to:#sendemailoptionsallusers

// Content (one of the following):
html?: string; //$stack-link-to:#sendemailoptionshtml
templateId?: string; //$stack-link-to:#sendemailoptionstemplateid
draftId?: string; //$stack-link-to:#sendemailoptionsdraftid

// Options:
themeId?: string | null | false; //$stack-link-to:#sendemailoptionsthemeid
subject?: string; //$stack-link-to:#sendemailoptionssubject
notificationCategoryName?: string; //$stack-link-to:#sendemailoptionsnotificationcategoryname
scheduledAt?: Date; //$stack-link-to:#sendemailoptionsscheduledat
variables?: Record<string, unknown>; //$stack-link-to:#sendemailoptionsvariables
};`}
/>

## Recipients

You must provide exactly one of `userIds` or `allUsers`.

<EmailSection type="sendEmailOptions" property="userIds" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      An array of user IDs that will receive the email. All users must exist in your Hexclave project. Cannot be used together with `allUsers`.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const userIds: string[]; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

<EmailSection type="sendEmailOptions" property="allUsers" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Set to `true` to send the email to all users in the project. Cannot be used together with `userIds`.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const allUsers: true; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

## Content

You must provide exactly one of `html`, `templateId`, or `draftId`.

<EmailSection type="sendEmailOptions" property="html" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Custom HTML content for the email. Cannot be used together with `templateId` or `draftId`.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const html: string; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

<EmailSection type="sendEmailOptions" property="templateId" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      ID of the email template to use. Cannot be used together with `html` or `draftId`.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const templateId: string; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

<EmailSection type="sendEmailOptions" property="draftId" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      ID of an email draft to send. Cannot be used together with `html` or `templateId`.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const draftId: string; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

## Options

<EmailSection type="sendEmailOptions" property="themeId" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      A string ID for a custom theme, `null` for no theme, or `false` to use the default theme.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const themeId: string | null | false | undefined; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

<EmailSection type="sendEmailOptions" property="subject" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Optional email subject line. If you use a template, this overrides the template's default subject.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const subject: string | undefined; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

<EmailSection type="sendEmailOptions" property="notificationCategoryName" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Optional notification category name for user preferences. Users can opt in or out of specific categories through their account settings.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const notificationCategoryName: string | undefined; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

<EmailSection type="sendEmailOptions" property="scheduledAt" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Optional date to schedule the email for. If not provided, the email is sent immediately.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const scheduledAt: Date | undefined; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

<EmailSection type="sendEmailOptions" property="variables" defaultOpen={false}>
  <MethodLayout>
    <MethodContent>
      Optional variables to substitute in the template. Only used when `templateId` is provided.
    </MethodContent>

    <MethodAside title="Type Definition">
      `typescript declare const variables: Record<string, unknown> | undefined; `
    </MethodAside>
  </MethodLayout>
</EmailSection>

## Usage

Choose a content method (`html`, `templateId`, or `draftId`) and a recipient method (`userIds` or `allUsers`):

<Tabs>
  <Tab title="Custom HTML">
    Provide custom HTML directly:

    ```typescript theme={null}
    await hexclaveServerApp.sendEmail({
      userIds: ["user-id-1"],
      subject: "Hello!",
      html: "<h1>Welcome</h1><p>Thanks for signing up!</p>",
    });
    ```
  </Tab>

  <Tab title="Template">
    Use a template with variable substitution:

    ```typescript theme={null}
    await hexclaveServerApp.sendEmail({
      userIds: ["user-id-1"],
      templateId: "welcome-template",
      variables: {
        userName: "John Doe",
        activationUrl: "https://app.com/activate/token123",
      },
    });
    ```
  </Tab>

  <Tab title="Draft">
    Send from a saved email draft:

    ```typescript theme={null}
    await hexclaveServerApp.sendEmail({
      allUsers: true,
      draftId: "my-draft-id",
    });
    ```
  </Tab>

  <Tab title="Scheduled">
    Schedule an email for later delivery:

    ```typescript theme={null}
    await hexclaveServerApp.sendEmail({
      userIds: ["user-id-1"],
      templateId: "weekly-digest",
      scheduledAt: new Date("2025-01-15T09:00:00Z"),
    });
    ```
  </Tab>
</Tabs>

<Note>
  The `notificationCategoryName`, `themeId`, `scheduledAt`, and `variables` properties work independently
  with any content method.
</Note>
