# The EmailTemplates kit — mail that looks designed

> `Osysharp.EmailTemplates` ships the parts a designed mail is built from — a layout with its preview line, logo and a footer carrying the sender's address and an unsubscribe link, a headline, paragraphs, a button, a picture, a code to copy, and a receipt's lines and total. Each is an `[Email]` part in the app's own theme, so a mail written with them looks like the rest of the product. And the MAIL BLOCKS staff arrange in a mail's region — words, a heading, a picture, a button, a quote, small print.

<!-- id: ui-email-templates-kit · area: ui · stability: stable · html: https://osysharp.com/reference/ui/email-templates-kit/ -->

## Summary        {#summary}
A mail that looks designed has the same few pieces every time: the sender's name at the top, a clear headline, a paragraph or two,
the lines of a receipt with their amounts, one obvious button, and a footer saying who sent it. This kit is those
pieces, written as [[ui-email|`[Email]`]] parts in the app's own theme.

```osy syntax
// app.osy
use Osysharp.EmailTemplates@0;
```

## Signature      {#signature}
```osy syntax
EmailLayout(string brand, string? preview = null, string? logo = null, string? address = null,
            string? unsubscribe = null, string? footer = null) { … }
EmailHeading(string text)
EmailText(string text)
EmailNote(string text)
EmailButton(string label, string href)
EmailImage(string src, string alt, int width = 552, bool inline = false)
EmailCode(string code)
EmailDivider()
EmailTable() { … }                                   // EmailRow + EmailTotal inside
EmailRow(string label, string value, string? detail = null)
EmailTotal(string label, string value)

// The mail blocks — [Block] [Email] parts staff place in a mail's Region:
EmailWords(Markdown words)
EmailHeadline(string heading, Markdown words = "")
EmailPicture(Picture picture, string alt = "")
EmailAction(string label, PageLink link = "/")
EmailQuote(string quote, string who = "", Color ground = Colors.Muted)
EmailSmallPrint(Markdown words)
```

## Description    {#description}

### The frame: EmailLayout   {#layout}
`EmailLayout` is the outside of every mail: the sender's own page — the theme's background and its type — in a
600-pixel column, the width every client lays out well, with the brand at the top, the mail's content under it, and a
footer below a rule. A mail reads like one of the app's pages, not like one of its cards: a shop that is black type on
white sends black type on white, whatever colour its panels are.

- `brand` is the sender's name. It heads the mail unless there is a `logo`, which replaces it. A logo that is a file
  the app stores (`public/logo.png`) travels INSIDE the mail, so the brand shows even where a client blocks remote
  pictures; see [[ui-email#pictures]].
- `preview` is the line an inbox shows beside the subject. Without one, a client shows the mail's first words.
- `address` is where the sender is. A marketing mail must carry a postal address, and a receipt is better for one.
- `unsubscribe` is the address that stops this kind of mail. Give it for anything a reader signed up to, and never
  for a mail they cannot stop receiving, such as a receipt.
- `footer` is one more line of small print above the address, such as why the reader is getting this mail.

### The parts that go inside   {#parts}
| part | what it draws |
|---|---|
| `EmailHeading(text)` | the headline, in the theme's display face |
| `EmailText(text)` | a paragraph — a line break in the text is kept |
| `EmailNote(text)` | small print in the muted colour |
| `EmailButton(label, href)` | the one thing to do next — a button that is a link in every client, Outlook included |
| `EmailImage(src, alt, width, inline)` | a picture, 552 pixels wide unless told otherwise (the column's inner width) — by address, or with `inline: true` a file the app stores, carried inside the mail |
| `EmailCode(code)` | a code to type or read out — a gift code, a return code — large and spaced |
| `EmailDivider()` | a rule between two parts of the mail |
| `EmailTable() { … }` | a receipt's lines, under a rule — `EmailRow`s and an `EmailTotal` |
| `EmailRow(label, value, detail)` | one line: what it is, with an optional detail under it (a size), and what it costs |
| `EmailTotal(label, value)` | the line a receipt ends on, bold, under a rule |

### It wears your theme   {#theme}
Every colour, size, corner and face in the kit is a theme token: `Colors.Primary` for the button, `Colors.Bg` and
`Colors.OnBg` for the page and its type, `FontSize.Title` for the headline, `Font.Display` for its face. The renderer writes the **app's** value
for each, so an app that declares `theme Brand { Colors { Primary = "#C2410C"; } }` sends orange buttons without
touching the kit.

### A part of your own   {#your-own}
Each part is an ordinary `[Email]` component over the platform's email atoms, so a different one is written the same
way. `osy get EmailButton` copies the kit's into your app as a starting point.

### The mail blocks — what staff arrange   {#blocks}
A mail's words that staff own are a [[ui-email#region|region]] of blocks, arranged at the desk like a page's. The kit
ships the everyday ones; each is an `[Email]` part marked `[Block]`, in the app's theme, its words written with
`placeholders: true` so they are filled from whichever mail they are placed in:

| block | what staff fill in |
|---|---|
| `EmailWords` — **Words** | a paragraph in Markdown — what the mail says first |
| `EmailHeadline` — **Heading and words** | a heading, and a paragraph under it |
| `EmailPicture` — **Picture** | a photograph across the mail — one the app ships, or one uploaded — and what it shows |
| `EmailAction` — **Button** | what it says, and where it goes (a page of the app, or an address) |
| `EmailQuote` — **Quote** | what somebody said, who said it, and one of the theme's grounds to set it on |
| `EmailSmallPrint` — **Small print** | a quiet line at the foot of the mail |

```osy syntax
Region("welcome", allow: [EmailWords, EmailHeadline, EmailPicture, EmailAction, EmailQuote, EmailSmallPrint]) {
  EmailWords(words: "Welcome aboard, **{member.name}**.");
}
```

A region needs `use Osysharp.Blocks;` in the app — that is where what staff arrange is kept. An app that arranges
nothing uses the same components as ordinary parts, and needs nothing more: `EmailQuote("…", who: "…")` in a template
is a quote.

A save of words naming a placeholder the mail does not fill is refused by name (`Osysharp.Blocks`' `WordsProblem`),
and `PlaceholdersIn`, `UnknownPlaceholders` and `PlaceholderRefusal` — the same check over any words, a campaign's body
say — are there too.

## Examples       {#examples}

### A receipt, from the order it confirms   {#example-receipt}
```osy title="an order confirmation built from the kit's parts" test app=ui-email-templates-kit
app EmailKitExample {
  use Osysharp.EmailTemplates;
  model "model/**/*.osy";
}

using Osysharp.EmailTemplates;

entity Sale {
  [Required, MaxLength(40)] string Reference;
  [Required, MaxLength(120)] string Customer;
  [ForeignKey(Sale)] SaleLine[] Lines;
  security { allow read, create when IsAuthenticated; }
}

entity SaleLine {
  [Required] Sale Sale;
  [Required, MaxLength(120)] string Name;
  [MaxLength(60)] string? Size;
  int Quantity;
  decimal Price;
  security { allow read, create when IsAuthenticated; }
}

string Kronor(decimal amount) { return $"{amount:0.00} kr"; }

[Email]
component SaleReceipt(Sale sale) {
  subject => $"Your receipt {sale.Reference}";
  render {
    EmailLayout("Grounds & Grapes", preview: $"Thank you, {sale.Customer} — receipt {sale.Reference}",
                address: "Storgatan 1, 111 22 Stockholm") {
      EmailHeading($"Thank you, {sale.Customer}");
      EmailText("Your order is reserved and on its way to being packed.");
      EmailTable() {
        foreach (var line in sale.Lines) {
          EmailRow($"{line.Quantity} × {line.Name}", Kronor(line.Price * line.Quantity), detail: line.Size);
        }
        EmailTotal("Total", Kronor(sale.Lines.Sum(l => l.Price * l.Quantity)));
      }
      EmailButton("See your order", $"https://shop.example.com/orders/{sale.Reference}");
      EmailNote("Questions? Reply to this mail.");
    }
  }
}
```

## See also       {#see-also}
- [[Email] — mail rendered from data](https://osysharp.com/reference/ui/email/) — the `[Email]` render target: the atoms, what a mail may hold, the text twin, photographing one.
- [Blocks and regions — pages the staff arrange](https://osysharp.com/reference/ui/blocks/) and [The PageBuilder kit — the desk staff arrange the site at](https://osysharp.com/reference/ui/pages-kit/) — how a region's blocks are arranged, and the desk that shows the mail beside them.
- [theme tokens](https://osysharp.com/reference/ui/theming/) — the tokens the kit's colours and sizes come from, and how an app overrides them.
