Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ preview:
cd docs && quarto preview

test:
pytest nbmail/tests nbmail/mjml/tests --cov-report=xml
pytest nbmail/tests nbmail/mjml/tests nbmail/compose/tests --cov-report=xml

test-update:
pytest nbmail/tests nbmail/mjml/tests --snapshot-update
pytest nbmail/tests nbmail/mjml/tests nbmail/compose/tests --snapshot-update

generate-mjml-tags:
python3 nbmail/mjml/scripts/generate_tags.py
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ from nbmail import (
)

# Read a Quarto email JSON file
email_struct = quarto_json_to_email("email.json")
email = quarto_json_to_email("email.json")

# Preview the email as HTML
email_struct.write_preview_email("preview.html")
email.write_preview_email("preview.html")

# Send the email via Gmail
send_email_with_gmail("your_email@gmail.com", "your_password", email_struct)
send_email_with_gmail("your_email@gmail.com", "your_password", email)
```

## Features
Expand Down
16 changes: 16 additions & 0 deletions docs/_quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,22 @@ quartodoc:
contents:
- write_email_message_to_file

- title: Templated Authoring
desc: >
Write responsive emails with the Blastula template
package: nbmail
contents:
- compose.compose_email
- compose.create_blocks
- compose.block_text
- compose.block_title
- compose.block_spacer
- compose.block_image
- compose.block_plot
- compose.md
- compose.add_cta_button
- compose.add_readable_time

- title: MJML Authoring
desc: >
Write responsive emails with MJML
Expand Down
70 changes: 70 additions & 0 deletions nbmail/compose/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# nbmail.compose

The `compose` module provides a high-level, Pythonic API for building HTML emails using simple building blocks. It's designed for data science workflows where you need to create professional-looking emails without writing raw HTML or MJML.

## Quick Start

```python
from nbmail.compose import compose_email, block_text, block_title, create_blocks

# Simple email
email = compose_email(
body=block_text("Hello world!")
)

# Email with multiple blocks
email = compose_email(
title="Weekly Report",
body=create_blocks(
block_text("Welcome to this week's update!"),
block_text("Here's what's new...")
)
)
```

## Architecture

The compose module is built on three main concepts:

1. **Blocks** - Individual content units (text, images, plots, spacers, markdown)
2. **BlockList** - Collections of blocks that can be rendered together
3. **compose_email()** - The main entry point that converts blocks to MJML and then to Email objects

### Why Blocks?

Blocks provide a simple, composable abstraction over MJML's more complex tag structure. They encapsulate common email patterns (text sections, images, spacers) in an easy-to-use API.

### MJML Under the Hood

Blocks compile to MJML tags internally. MJML provides:
- Responsive design by default
- Cross-client compatibility
- Semantic structure (sections, columns, etc.)

### Inline Attachments

Local images are read as bytes and stored in `Email.inline_attachments` as base64 strings. During sending, these are converted to CID references in the MIME structure.

### Jupyter Display Support

Blocks and BlockLists implement `_repr_html_()` for rich display in notebooks:

```python
# In a Jupyter notebook:
block = block_text("Preview me!")
block # Automatically renders as HTML
```

## Dependencies

**Required:**
- `markdown` - For Markdown processing in text blocks

**Optional:**
- `plotnine` - For `block_plot()` functionality



## API Reference

Complete API documentation is available in the [nbmail reference docs](https://posit-dev.github.io/nbmail/reference/).
20 changes: 20 additions & 0 deletions nbmail/compose/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from .compose import compose_email, create_blocks
from .blocks import block_text, block_title, block_spacer, block_image, block_plot
from .inline_utils import (
md,
add_cta_button,
add_readable_time,
)

__all__ = (
"compose_email",
"create_blocks",
"block_text",
"block_title",
"block_spacer",
"block_image",
"block_plot",
"md",
"add_cta_button",
"add_readable_time",
)
Loading