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
2 changes: 1 addition & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func NewRootCmd(f *cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "mailtrap",
Short: "CLI for the Mailtrap email platform",
Long: "A command-line interface for managing Mailtrap email sending, sandbox testing, contacts, and account settings.",
Long: "A command-line interface for managing Mailtrap email sending, sandboxes, contacts, and account settings.",
SilenceUsage: true,
SilenceErrors: true,
}
Expand Down
72 changes: 36 additions & 36 deletions docs/TEST_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ export MAILTRAP_API_TOKEN=your-token

Before running integration tests, ensure you have:
- A Mailtrap account with API access
- A verified **sending domain** for transactional/bulk send tests
- At least one **sandbox project** with an **inbox** for sandbox tests
- Note down your **inbox ID** for sandbox send tests
- A verified **domain** for transactional/bulk send tests
- At least one **project** with a **sandbox** for sandbox tests
- Note down your **sandbox ID** for sandbox send tests

### 3. Build the CLI

Expand Down Expand Up @@ -91,7 +91,7 @@ Tests are organized by endpoint group. Each test specifies:

## 2. Email Sending (Transactional/Bulk)

**Note:** Requires a verified sending domain.
**Note:** Requires a verified domain.

| # | Test | Command | Expected |
|---|------|---------|----------|
Expand All @@ -105,7 +105,7 @@ Tests are organized by endpoint group. Each test specifies:
| 2.8 | Send from template | `mailtrap send transactional --from you@yourdomain.com --to recipient@example.com --template-uuid <TEMPLATE_UUID> --template-variables '{"user_name":"John"}'` | Success; delivered email has the template's subject and `John` substituted. Repeat with `send bulk` |
| 2.9 | Template with subject | `mailtrap send transactional --from you@yourdomain.com --to recipient@example.com --template-uuid <TEMPLATE_UUID> --subject "X"` | Error: `--subject cannot be used with --template-uuid` |

## 3. Domains (Sending)
## 3. Domains

**Note:** The API returns `{"data": [...]}` — the CLI may need a fix to unwrap this.

Expand Down Expand Up @@ -226,16 +226,16 @@ Tests are organized by endpoint group. Each test specifies:

| # | Test | Command | Expected |
|---|------|---------|----------|
| 12.1 | List inboxes | `mailtrap sandboxes list` | Table with sandbox entries |
| 12.2 | Get inbox | `mailtrap sandboxes get --id <INBOX_ID>` | Single sandbox details |
| 12.3 | Create inbox | `mailtrap sandboxes create --project-id <PROJECT_ID> --name "test-sandbox"` | New inbox in output |
| 12.4 | Update inbox | `mailtrap sandboxes update --id <NEW_ID> --name "test-sandbox-updated"` | Updated name |
| 12.5 | Mark read | `mailtrap sandboxes mark-read --id <INBOX_ID>` | Success message |
| 12.1 | List sandboxes | `mailtrap sandboxes list` | Table with sandbox entries |
| 12.2 | Get sandbox | `mailtrap sandboxes get --id <SANDBOX_ID>` | Single sandbox details |
| 12.3 | Create sandbox | `mailtrap sandboxes create --project-id <PROJECT_ID> --name "test-sandbox"` | New sandbox in output |
| 12.4 | Update sandbox | `mailtrap sandboxes update --id <NEW_ID> --name "test-sandbox-updated"` | Updated name |
| 12.5 | Mark read | `mailtrap sandboxes mark-read --id <SANDBOX_ID>` | Success message |
| 12.6 | Reset credentials | `mailtrap sandboxes reset-credentials --id <NEW_ID>` | Success/new credentials |
| 12.7 | Toggle email username | `mailtrap sandboxes toggle-email-username --id <NEW_ID>` | Toggled response |
| 12.8 | Reset email username | `mailtrap sandboxes reset-email-username --id <NEW_ID>` | Reset response |
| 12.9 | Clean inbox | `mailtrap sandboxes clean --id <NEW_ID>` | Success message |
| 12.10 | Delete inbox | `mailtrap sandboxes delete --id <NEW_ID>` | Success message |
| 12.7 | Toggle email username | `mailtrap sandboxes toggle-email --id <NEW_ID>` | Toggled response |
| 12.8 | Reset email username | `mailtrap sandboxes reset-email --id <NEW_ID>` | Reset response |
| 12.9 | Clean sandbox | `mailtrap sandboxes clean --id <NEW_ID>` | Success message |
| 12.10 | Delete sandbox | `mailtrap sandboxes delete --id <NEW_ID>` | Success message |
| 12.11 | Get missing ID | `mailtrap sandboxes get` | Error: `--id is required` |

**Cleanup:** Delete test sandbox.
Expand All @@ -244,43 +244,43 @@ Tests are organized by endpoint group. Each test specifies:

| # | Test | Command | Expected |
|---|------|---------|----------|
| 13.1 | Send single | `mailtrap sandbox-send single --sandbox-id <INBOX_ID> --from test@example.com --to recipient@example.com --subject "Integration Test" --text "Hello from CLI"` | Success response with message ID |
| 13.2 | Send batch | `mailtrap sandbox-send batch --sandbox-id <INBOX_ID> --from test@example.com --to recipient@example.com --subject "Batch Test" --text "Batch hello"` | Success response |
| 13.1 | Send single | `mailtrap sandbox-send single --sandbox-id <SANDBOX_ID> --from test@example.com --to recipient@example.com --subject "Integration Test" --text "Hello from CLI"` | Success response with message ID |
| 13.2 | Send batch | `mailtrap sandbox-send batch --sandbox-id <SANDBOX_ID> --from test@example.com --to recipient@example.com --subject "Batch Test" --text "Batch hello"` | Success response |
| 13.3 | Missing flags | `mailtrap sandbox-send single` | Error: required flags |

**Verification:** After 13.1, run `mailtrap messages list --sandbox-id <INBOX_ID>` to confirm the message appears.
**Verification:** After 13.1, run `mailtrap messages list --sandbox-id <SANDBOX_ID>` to confirm the message appears.

## 14. Messages (Sandbox)

Prerequisite: Send a test email to the sandbox first (test 13.1).

| # | Test | Command | Expected |
|---|------|---------|----------|
| 14.1 | List messages | `mailtrap messages list --sandbox-id <INBOX_ID>` | Table with message entries |
| 14.2 | List messages (JSON) | `mailtrap messages list --sandbox-id <INBOX_ID> --output json` | Valid JSON array |
| 14.3 | Get message | `mailtrap messages get --sandbox-id <INBOX_ID> --id <MSG_ID>` | Single message details |
| 14.4 | Update message | `mailtrap messages update --sandbox-id <INBOX_ID> --id <MSG_ID> --is-read true` | Updated message |
| 14.5 | Spam score | `mailtrap messages spam-score --sandbox-id <INBOX_ID> --id <MSG_ID>` | Spam score data |
| 14.6 | HTML analysis | `mailtrap messages html-analysis --sandbox-id <INBOX_ID> --id <MSG_ID>` | Analysis data |
| 14.7 | Headers | `mailtrap messages headers --sandbox-id <INBOX_ID> --id <MSG_ID>` | Email headers |
| 14.8 | HTML body | `mailtrap messages html --sandbox-id <INBOX_ID> --id <MSG_ID>` | Raw HTML content |
| 14.9 | Text body | `mailtrap messages text --sandbox-id <INBOX_ID> --id <MSG_ID>` | Raw text content |
| 14.10 | Source | `mailtrap messages source --sandbox-id <INBOX_ID> --id <MSG_ID>` | Raw source |
| 14.11 | Raw | `mailtrap messages raw --sandbox-id <INBOX_ID> --id <MSG_ID>` | Raw message |
| 14.12 | EML | `mailtrap messages eml --sandbox-id <INBOX_ID> --id <MSG_ID>` | EML format |
| 14.13 | Forward | `mailtrap messages forward --sandbox-id <INBOX_ID> --id <MSG_ID> --email forward@example.com` | Success |
| 14.14 | Delete message | `mailtrap messages delete --sandbox-id <INBOX_ID> --id <MSG_ID>` | Success message |
| 14.1 | List messages | `mailtrap messages list --sandbox-id <SANDBOX_ID>` | Table with message entries |
| 14.2 | List messages (JSON) | `mailtrap messages list --sandbox-id <SANDBOX_ID> --output json` | Valid JSON array |
| 14.3 | Get message | `mailtrap messages get --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Single message details |
| 14.4 | Update message | `mailtrap messages update --sandbox-id <SANDBOX_ID> --id <MSG_ID> --is-read true` | Updated message |
| 14.5 | Spam score | `mailtrap messages spam-score --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Spam score data |
| 14.6 | HTML analysis | `mailtrap messages html-analysis --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Analysis data |
| 14.7 | Headers | `mailtrap messages headers --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Email headers |
| 14.8 | HTML body | `mailtrap messages html --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Raw HTML content |
| 14.9 | Text body | `mailtrap messages text --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Raw text content |
| 14.10 | Source | `mailtrap messages source --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Raw source |
| 14.11 | Raw | `mailtrap messages raw --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Raw message |
| 14.12 | EML | `mailtrap messages eml --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | EML format |
| 14.13 | Forward | `mailtrap messages forward --sandbox-id <SANDBOX_ID> --id <MSG_ID> --email forward@example.com` | Success |
| 14.14 | Delete message | `mailtrap messages delete --sandbox-id <SANDBOX_ID> --id <MSG_ID>` | Success message |
| 14.15 | Missing sandbox-id | `mailtrap messages list` | Error: `--sandbox-id is required` |
| 14.16 | Missing id | `mailtrap messages get --sandbox-id <INBOX_ID>` | Error: `--id is required` |
| 14.16 | Missing id | `mailtrap messages get --sandbox-id <SANDBOX_ID>` | Error: `--id is required` |

## 15. Attachments (Sandbox)

Prerequisite: Send an email with an attachment to the sandbox.

| # | Test | Command | Expected |
|---|------|---------|----------|
| 15.1 | List attachments | `mailtrap attachments list --sandbox-id <INBOX_ID> --message-id <MSG_ID>` | Table with attachments |
| 15.2 | Get attachment | `mailtrap attachments get --sandbox-id <INBOX_ID> --message-id <MSG_ID> --id <ATT_ID>` | Attachment details |
| 15.1 | List attachments | `mailtrap attachments list --sandbox-id <SANDBOX_ID> --message-id <MSG_ID>` | Table with attachments |
| 15.2 | Get attachment | `mailtrap attachments get --sandbox-id <SANDBOX_ID> --message-id <MSG_ID> --id <ATT_ID>` | Attachment details |
| 15.3 | Missing flags | `mailtrap attachments list` | Error: required flags |

## 16. Account Access
Expand Down Expand Up @@ -399,7 +399,7 @@ Run tests in dependency order so earlier tests create resources needed by later

1. **Accounts** (read-only, validates API access)
2. **Sending** (transactional/bulk — requires verified domain)
3. **Domains** (CRUD for sending domains)
3. **Domains** (CRUD)
4. **Templates** (CRUD)
5. **Suppressions** (list/delete)
6. **Stats** (requires start-date)
Expand All @@ -408,7 +408,7 @@ Run tests in dependency order so earlier tests create resources needed by later
9. **Contact Fields** (CRUD)
10. **Contacts** (CRUD)
11. **Projects** (CRUD — creates project for sandbox tests)
12. **Inboxes** (CRUD — creates sandbox for sandbox send/message tests)
12. **Sandboxes** (CRUD — creates a sandbox for sandbox send/message tests)
13. **Sandbox Send** (sends email to sandbox for message tests)
14. **Messages** (all subcommands on the sent message)
15. **Attachments** (requires message with attachment)
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/companyinfo/companyinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func companyInfoPath(domainID string) string {
func NewCmdCompanyInfo(f *cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "company-info",
Short: "Manage sending domain company info",
Short: "Manage domain company info",
}

cmd.AddCommand(NewCmdGet(f))
Expand Down
4 changes: 2 additions & 2 deletions internal/commands/companyinfo/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func NewCmdCreate(f *cmdutil.Factory) *cobra.Command {

cmd := &cobra.Command{
Use: "create",
Short: "Create company info for a sending domain",
Short: "Create company info for a domain",
RunE: func(cmd *cobra.Command, args []string) error {
required := []struct {
flag string
Expand Down Expand Up @@ -84,7 +84,7 @@ func NewCmdCreate(f *cmdutil.Factory) *cobra.Command {
},
}

cmd.Flags().StringVar(&domainID, "domain-id", "", "Sending domain ID (required)")
cmd.Flags().StringVar(&domainID, "domain-id", "", "Domain ID (required)")
cmd.Flags().StringVar(&name, "name", "", "Company or individual name (required)")
cmd.Flags().StringVar(&address, "address", "", "Street address (required)")
cmd.Flags().StringVar(&city, "city", "", "City (required)")
Expand Down
4 changes: 2 additions & 2 deletions internal/commands/companyinfo/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func NewCmdGet(f *cmdutil.Factory) *cobra.Command {

cmd := &cobra.Command{
Use: "get",
Short: "Get company info for a sending domain",
Short: "Get company info for a domain",
RunE: func(cmd *cobra.Command, args []string) error {
if err := cmdutil.RequireFlag("domain-id", domainID); err != nil {
return err
Expand All @@ -35,7 +35,7 @@ func NewCmdGet(f *cmdutil.Factory) *cobra.Command {
},
}

cmd.Flags().StringVar(&domainID, "domain-id", "", "Sending domain ID (required)")
cmd.Flags().StringVar(&domainID, "domain-id", "", "Domain ID (required)")

return cmd
}
4 changes: 2 additions & 2 deletions internal/commands/companyinfo/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {

cmd := &cobra.Command{
Use: "update",
Short: "Update company info for a sending domain",
Short: "Update company info for a domain",
RunE: func(cmd *cobra.Command, args []string) error {
if err := cmdutil.RequireFlag("domain-id", domainID); err != nil {
return err
Expand Down Expand Up @@ -76,7 +76,7 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {
},
}

cmd.Flags().StringVar(&domainID, "domain-id", "", "Sending domain ID (required)")
cmd.Flags().StringVar(&domainID, "domain-id", "", "Domain ID (required)")
cmd.Flags().StringVar(&name, "name", "", "Company or individual name")
cmd.Flags().StringVar(&address, "address", "", "Street address")
cmd.Flags().StringVar(&city, "city", "", "City")
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/domains/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func NewCmdCreate(f *cmdutil.Factory) *cobra.Command {

cmd := &cobra.Command{
Use: "create",
Short: "Create a sending domain",
Short: "Create a domain",
RunE: func(cmd *cobra.Command, args []string) error {
if err := cmdutil.RequireFlag("name", name); err != nil {
return err
Expand Down
4 changes: 2 additions & 2 deletions internal/commands/domains/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func NewCmdDelete(f *cmdutil.Factory) *cobra.Command {

cmd := &cobra.Command{
Use: "delete",
Short: "Delete a sending domain",
Short: "Delete a domain",
RunE: func(cmd *cobra.Command, args []string) error {
if err := cmdutil.RequireFlag("id", domainID); err != nil {
return err
Expand All @@ -31,7 +31,7 @@ func NewCmdDelete(f *cmdutil.Factory) *cobra.Command {
return err
}

path := cmdutil.AccountPath("sending_domains", fmt.Sprintf("%s", domainID))
path := cmdutil.AccountPath("sending_domains", domainID)

if err := c.Delete(context.Background(), client.BaseGeneral, path, nil); err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/domains/domains.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
func NewCmdDomains(f *cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "domains",
Short: "Manage sending domains",
Short: "Manage domains",
}

cmd.AddCommand(NewCmdList(f))
Expand Down
5 changes: 2 additions & 3 deletions internal/commands/domains/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package domains

import (
"context"
"fmt"

"github.com/mailtrap/mailtrap-cli/internal/client"
"github.com/mailtrap/mailtrap-cli/internal/cmdutil"
Expand All @@ -16,7 +15,7 @@ func NewCmdGet(f *cmdutil.Factory) *cobra.Command {

cmd := &cobra.Command{
Use: "get",
Short: "Get a sending domain",
Short: "Get a domain",
RunE: func(cmd *cobra.Command, args []string) error {
if err := cmdutil.RequireFlag("id", domainID); err != nil {
return err
Expand All @@ -32,7 +31,7 @@ func NewCmdGet(f *cmdutil.Factory) *cobra.Command {
return err
}

path := cmdutil.AccountPath("sending_domains", fmt.Sprintf("%s", domainID))
path := cmdutil.AccountPath("sending_domains", domainID)

var domain Domain
if err := c.Get(context.Background(), client.BaseGeneral, path, nil, &domain); err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/domains/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ var domainSettingsColumns = append(
func NewCmdList(f *cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List all sending domains",
Short: "List all domains",
RunE: func(cmd *cobra.Command, args []string) error {
c, err := f.NewClient()
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/domains/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func NewCmdUpdate(f *cmdutil.Factory) *cobra.Command {

cmd := &cobra.Command{
Use: "update",
Short: "Update a sending domain",
Short: "Update a domain",
RunE: func(cmd *cobra.Command, args []string) error {
if err := cmdutil.RequireFlag("id", domainID); err != nil {
return err
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/emailcampaigns/attributes.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type campaignAttrs struct {

func addAttributeFlags(cmd *cobra.Command, attrs *campaignAttrs) {
cmd.Flags().StringVar(&attrs.Name, "name", "", "Campaign name")
cmd.Flags().Int64Var(&attrs.DomainID, "domain-id", 0, "ID of the verified sending domain, as returned by the Sending Domains endpoints")
cmd.Flags().Int64Var(&attrs.DomainID, "domain-id", 0, "ID of the verified domain, as returned by the Domains endpoints")
cmd.Flags().StringVar(&attrs.FromDisplayName, "from-display-name", "", "Display name shown in the From header")
cmd.Flags().StringVar(&attrs.FromLocalPart, "from-local-part", "", "Local part (before the @) of the From address")
cmd.Flags().StringVar(&attrs.ReplyToDisplayName, "reply-to-display-name", "", "Reply-To display name")
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/inbound/inboxes/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func NewCmdCreate(f *cmdutil.Factory) *cobra.Command {

cmd.Flags().StringVar(&folderID, "folder-id", "", "Folder ID (required)")
cmd.Flags().StringVar(&name, "name", "", "Inbox name (required)")
cmd.Flags().IntVar(&domainID, "domain-id", 0, "Sending domain ID for a custom-domain (catch-all) inbox")
cmd.Flags().IntVar(&domainID, "domain-id", 0, "Domain ID for a custom-domain (catch-all) inbox")

return cmd
}
4 changes: 2 additions & 2 deletions internal/commands/sandbox_send/sandbox_send.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
func NewCmdSandboxSend(f *cmdutil.Factory) *cobra.Command {
cmd := &cobra.Command{
Use: "sandbox-send",
Short: "Send emails to a Mailtrap sandbox inbox",
Long: "Send single or batch emails to a Mailtrap sandbox inbox for testing.",
Short: "Send emails to a Mailtrap sandbox",
Long: "Send single or batch emails to a Mailtrap sandbox for testing.",
}

cmd.AddCommand(NewCmdSingle(f))
Expand Down
8 changes: 4 additions & 4 deletions internal/commands/sandboxes/clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import (
)

func NewCmdClean(f *cmdutil.Factory) *cobra.Command {
var inboxID string
var sandboxID string

cmd := &cobra.Command{
Use: "clean",
Short: "Clean a sandbox",
RunE: func(cmd *cobra.Command, args []string) error {
if err := cmdutil.RequireFlag("id", inboxID); err != nil {
if err := cmdutil.RequireFlag("id", sandboxID); err != nil {
return err
}

Expand All @@ -31,7 +31,7 @@ func NewCmdClean(f *cmdutil.Factory) *cobra.Command {
return err
}

path := cmdutil.AccountPath("inboxes", fmt.Sprintf("%s", inboxID), "clean")
path := cmdutil.AccountPath("inboxes", sandboxID, "clean")

if err := c.Patch(context.Background(), client.BaseGeneral, path, nil, nil); err != nil {
return err
Expand All @@ -42,7 +42,7 @@ func NewCmdClean(f *cmdutil.Factory) *cobra.Command {
},
}

cmd.Flags().StringVar(&inboxID, "id", "", "Sandbox ID")
cmd.Flags().StringVar(&sandboxID, "id", "", "Sandbox ID")

return cmd
}
9 changes: 4 additions & 5 deletions internal/commands/sandboxes/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package sandboxes

import (
"context"
"fmt"

"github.com/mailtrap/mailtrap-cli/internal/client"
"github.com/mailtrap/mailtrap-cli/internal/cmdutil"
Expand Down Expand Up @@ -36,18 +35,18 @@ func NewCmdCreate(f *cmdutil.Factory) *cobra.Command {
return err
}

path := cmdutil.AccountPath("projects", fmt.Sprintf("%s", projectID), "inboxes")
path := cmdutil.AccountPath("projects", projectID, "inboxes")
body := map[string]interface{}{
"inbox": map[string]string{"name": name},
}

var inbox Inbox
if err := c.Post(context.Background(), client.BaseGeneral, path, body, &inbox); err != nil {
var sandbox Sandbox
if err := c.Post(context.Background(), client.BaseGeneral, path, body, &sandbox); err != nil {
return err
}

format := cmdutil.GetOutputFormat()
return output.Print(f.IOStreams.Out, format, inbox, inboxColumns)
return output.Print(f.IOStreams.Out, format, sandbox, sandboxColumns)
},
}

Expand Down
Loading
Loading