Skip to content

EmailOS Send Command Documentation

The mailos send command sends emails with support for markdown formatting, attachments, and signatures.

Basic Usage

bash
mailos send --to [email protected] --subject "Subject" --body "Message"

If the nearest emailos.json or emailos.toml sets from_address, that project sender policy controls the send account and outgoing From address. Passing --from or --account selects an account only when no project sender policy is present; otherwise MailOS warns and keeps the project config values.

To send a quick test email to the resolved sender address, use mailos echo. It reuses the mailos send delivery path and fills --to from the current project or the default machine MailOS account.

To check a message against a fixed safe recipient, configure the destination once and use --test:

bash
mailos configure --test-to-email [email protected]
mailos send --to [email protected] --subject "Check" --body "Test message" --test

Test mode reads test_to_email from the root config at ~/.email/config.json, replaces all To recipients with that address, and clears CC and BCC.

Project Media

mailos send can attach media files explicitly with --media, and it automatically attaches files listed in emailos.json or emailos.toml under media, in addition to any --attach files:

bash
mailos send --to [email protected] --subject "Photos" --body "See attached" --media assets/photo.png
json
{
  "media": ["assets/photo.png", "/path/to/document.pdf"]
}

Relative media paths are resolved from the directory containing the project config file.

Project Body Limit

If project config sets max_body_words, mailos send rejects bodies over that limit before sending. Signatures are appended after this check, so signature text does not count toward the body word limit.

Campaign Metadata

Use --campaign-id to stamp outgoing messages with a hidden X-MailOS-Campaign-ID header for later search. MailOS also adds a stable Message-ID header when sending, and campaign search includes replies whose In-Reply-To or References headers point back to the original campaign Message-IDs. Use --send-separately when a group or recipient list should receive separate initial emails instead of one email with every address in To.

For recurring folder-scoped work, prefer mailos campaign. It saves the campaign ID and purpose locally, remembers the active campaign, and wraps this send command as mailos campaign send.

bash
mailos send \
  --group ./recipients.txt \
  --subject "Initial outreach" \
  --body "Hello" \
  --campaign-id "spring-2026" \
  --send-separately

Then retrieve the campaign originals and replies with:

bash
mailos search --type sent --campaign-id "spring-2026"

Email Preheaders

The preheader is a brief text snippet that appears after the subject line in email clients' inbox view. It provides additional context to encourage recipients to open your email.

Best Practices

  • Keep it between 30-100 characters
  • Don't duplicate the subject line
  • Use it to add compelling details or create curiosity
  • Include a call to action when appropriate

Example

bash
mailos send \
  --to [email protected] \
  --subject "Your order has shipped!" \
  --preheader "Track your package with the link inside" \
  --body "Your order #12345 is on its way..."

Command-Line Flags

Basic Options

FlagShortTypeDefaultDescriptionExample
--accountstringEmail account to usemailos send --account value
--bcc[]stringBCC recipientsmailos send --bcc value
--body-bstringEmail body (Markdown supported). Use @path/to/file to load file contentmailos send --body value
--cc-c[]stringCC recipientsmailos send --cc value
--fromstringEmail account to use (alias for --account)mailos send --from value
--subject-sstringEmail subjectmailos send --subject value
--to-t[]stringRecipient email addressesmailos send --to value

Advanced Options

FlagShortTypeDefaultDescriptionExample
--attach-a[]stringAttachmentsmailos send --attach value
--campaign-idstringAdd a shared hidden X-MailOS-Campaign-ID header for later searchmailos send --campaign-id value
--check-duplicateboolfalseCheck if email with same subject has already been sent to recipientsmailos send --check-duplicate
--confirmboolfalseConfirm before sending each draftmailos send --confirm
--delete-afterboolfalseDelete drafts after successful sending instead of retaining them as sentmailos send --delete-after
--draft-dirstringDirectory containing draft emails (default: ~/.email/drafts)mailos send --draft-dir value
--draftsboolfalseSend all draft emails from .email/drafts foldermailos send --drafts
--electron-pathstringCustom path to Electron app (default: ~/Desktop/mailos-electron-ui)mailos send --electron-path value
--file-fstringRead body from filemailos send --file value
--filterstringFilter drafts (e.g., 'priority:high', 'to:*@example.com')mailos send --filter value
--forceboolfalseForce send email bypassing dynamic content warnings and template validationmailos send --force
--forward-message-idstringAppend the matching received email thread by Message-ID below the message bodymailos send --forward-message-id value
--forward-message-linkstringAppend the matching received email thread from a mail client message link, such as macOS Mail message://...mailos send --forward-message-link value
--from-namestringOverride the sender's display namemailos send --from-name value
--group-gstringSend to a saved email group or local recipient metadata filemailos send --group value
--inputboolfalseOpen Electron UI for composing email instead of sending directlymailos send --input
--log-filestringLog sent emails to filemailos send --log-file value
--media[]stringMedia attachments such as photos, PDFs, or other filesmailos send --media value
--modelstringModel to use for natural language parsing (auto-detects if not specified)mailos send --model value
--no-popupbooltrueSkip confirmation popup and send directlymailos send --no-popup
--no-signatureboolfalseNo signaturemailos send --no-signature
--no-validateboolfalseSkip email address validationmailos send --no-validate
--ollama-urlstringhttp://localhost:11434Ollama server URL for natural language processingmailos send --ollama-url value
--plain-pboolfalseSend as plain textmailos send --plain
--preheaderstringBrief preview text shown after subject line (30-100 characters recommended)mailos send --preheader value
--providerstringollamaAI provider for natural language parsing (ollama|vllm)mailos send --provider value
--replace[]stringReplace dynamic content with KEY=VALUE pairs (e.g., --replace USER_NAME=John --replace DATE=2024-01-01)mailos send --replace value
--schedule-atstringSchedule email to be sent at specific time (RFC3339 format: 2024-01-01T15:04:05Z)mailos send --schedule-at value
--schedule-cancelboolfalseCancel scheduled emails (use with --filter)mailos send --schedule-cancel
--schedule-instringSchedule email to be sent after duration (e.g., '1h30m', '2h', '30s')mailos send --schedule-in value
--schedule-listboolfalseList all scheduled emailsmailos send --schedule-list
--send-separatelyboolfalseSend a separate email to each To recipientmailos send --send-separately
--signaturestringCustom signaturemailos send --signature value
--templateboolfalseApply HTML template to emailmailos send --template
--template-htmlstringPath to custom HTML template filemailos send --template-html value
--testboolfalseSend only to the test recipient saved in the global configmailos send --test
--validatebooltrueValidate recipient email addresses before sending (enabled by default)mailos send --validate
--validate-smtpboolfalsePerform SMTP verification during validation (slower but more thorough)mailos send --validate-smtp
--vllm-urlstringhttp://localhost:8290VLLM server URL for natural language processingmailos send --vllm-url value

Output Options

FlagShortTypeDefaultDescriptionExample
--dry-runboolfalsePreview what would be sent without actually sendingmailos send --dry-run
--previewboolfalsePreview the complete email without sendingmailos send --preview
--verbose-vboolfalseShow detailed SMTP debugging informationmailos send --verbose

Email Address Validation

EmailOS automatically validates recipient email addresses before sending to prevent bounce-backs. Validation is enabled by default and checks:

  1. Email syntax - Verifies the email format is valid
  2. Domain existence - Confirms the domain exists via DNS lookup
  3. MX records - Checks if the domain can receive email

Validation Behavior

bash
# Default behavior - validation is automatic
mailos send --to [email protected] --subject "Test" --body "Hello"

# If validation fails, you'll see an error:
# Error: Email validation failed for the following recipients:
#   - [email protected]
#     Error: Domain does not exist
#     Details: The domain 'nonexistent-domain.xyz' could not be found.

Bypassing Validation

bash
# Skip validation entirely
mailos send --to [email protected] --subject "Test" --body "Hello" --no-validate

# Force send even if validation fails (shows warning)
mailos send --to [email protected] --subject "Test" --body "Hello" --force

Verbose Validation

bash
# See detailed validation output
mailos send --to [email protected] --subject "Test" --body "Hello" --verbose
# Output: Validating recipient email addresses...
# Output: All recipient email addresses validated successfully

Standalone Validation

For bulk validation before sending, use the dedicated validate command:

bash
# Validate addresses without sending
mailos validate [email protected] [email protected] --verbose

# See validate command documentation for more options
mailos validate --help

Markdown Support

By default, markdown in the message body is converted to HTML:

Supported Markdown

  • Bold: **text** or __text__
  • Italic: *text* or _text_
  • Code: `code`
  • Links: [text](url)
  • Lists: - item or 1. item
  • Headers: # Header
  • Code blocks: language ```

Example with Markdown

bash
mailos send \
  --to [email protected] \
  --subject "Project Update" \
  --body "## Status Update

**Completed:**
- Feature A
- Feature B

*In Progress:*
- Feature C

See [documentation](https://example.com)"

Input Methods

1. Command Line

bash
mailos send --to [email protected] --subject "Test" --body "Message"

2. From File

bash
mailos send --to [email protected] --subject "Report" --file ./report.md

3. Recipient Group From Markdown or Text

--group can be either a saved MailOS group name or a local .md, .markdown, or .txt file with recipient metadata. Use this for reusable recipient sets with to, cc, and bcc; the email body still comes from --body, stdin, or --file.

bash
mailos send --group ./recipients.md --body "Hello team"
mailos send --group ./recipients.txt --body "Hello team" --plain

Frontmatter format:

markdown
---
name: "Project Team"
to:
  - [email protected]
  - [email protected]
cc: [email protected]
bcc:
  - [email protected]
subject: "Project update"
description: "Short inbox preview"
signature: "Regards, Team"
file:
  - /path/to/report.pdf
---

Optional notes about this recipient set.

Plain metadata format without frontmatter delimiters:

text
to: [email protected], [email protected]
cc: [email protected]
bcc: [email protected]
name: Project Team
signature: "Regards, Team"

Supported metadata keys are to, cc, bcc, subject, name, from_name, description, preheader, signature, group, priority, and file. description is used as the preheader when preheader is not set. When --group points to a file, at least one to, cc, or bcc recipient must be present.

4. Body From File Path (--body)

bash
mailos send --to [email protected] --subject "Weekly Update" --body @./examples/send-bodies/plain-update.txt

Use @@ to send a literal value that starts with @:

bash
mailos send --to [email protected] --subject "Literal" --body "@@start-with-at"

5. Interactive (stdin)

bash
mailos send --to [email protected] --subject "Notes"
# Then type your message and press Ctrl+D

6. Piped Input

bash
echo "Automated message" | mailos send --to [email protected] --subject "Alert"

7. Include a Previous Chain as Forwarded Text

bash
mailos send --to [email protected] --subject "FYI" --body "Adding this for context." --forward-message-id "<[email protected]>"

When copying a macOS Mail deeplink, use --forward-message-link for clarity:

bash
mailos send --to [email protected] --subject "FYI" --body "Adding this for context." --forward-message-link "message://%3cabc123%40example.com%3e"

Signature Management

Default Signature

Automatically appends:

--
Your Name
[email protected]

Custom Signature

bash
mailos send \
  --to [email protected] \
  --subject "Proposal" \
  --body "Please find attached..." \
  --signature "Best regards,\nJohn Smith\nSales Manager\nCompany Inc."

No Signature

bash
mailos send --to [email protected] --subject "Test" --body "Message" --no-signature

Account Selection

Use --account to choose the authenticated mailbox for SMTP credentials. --from is an alias of --account.

If the nearest parent emailos.json or emailos.toml sets from_address, that project sender policy wins. Passing --from or --account will not change the project send account or outgoing From address; MailOS warns and continues to use project config. Change email_address or from_address in the project config when the project sender should change.

Usage

bash
# Send using a specific authenticated account
mailos send --to [email protected] --subject "Test" --body "Hello" --account [email protected]

# Equivalent alias
mailos send --to [email protected] --subject "Test" --body "Hello" --from [email protected]

Account Management

  • Use mailos accounts to list configured accounts and aliases
  • Use mailos account --set [EMAIL] to set the default account for the session
  • Use mailos account --clear to clear the session default account
  • If --account/--from is not specified, the configured default account is used
  • The account must be properly authenticated with valid credentials

Sender Policy (MAILOS_FROM_EMAIL)

Set MAILOS_FROM_EMAIL in your environment to enforce the outgoing From address used for sending.

bash
export MAILOS_FROM_EMAIL="[email protected]"
mailos send --account [email protected] --to [email protected] --subject "Test" --body "Hello"

Behavior when MAILOS_FROM_EMAIL is set:

  • Email sending is allowed (not blocked)
  • The message is sent using MAILOS_FROM_EMAIL as the From address
  • If --account differs, EmailOS logs that it will still send using MAILOS_FROM_EMAIL
  • End-of-send output includes a policy reminder that emails are sent with MAILOS_FROM_EMAIL

Use only MAILOS_FROM_EMAIL for sender policy configuration.

Project Config and AI Shells

MAILOS_FROM_EMAIL may come from the real process environment, a local env file, or the nearest parent project config from_address. A plain printenv MAILOS_FROM_EMAIL only shows real environment variables, so it can miss values that MailOS resolves from emailos.json or emailos.toml.

Check MailOS' resolved send values with:

bash
mailos config --values
mailos env

If an AI client or wrapper script needs the resolved values as real shell variables, run:

bash
eval "$(mailos env --export)"

mailos env --export exports non-secret send values such as MAILOS_EMAIL_ADDRESS, MAILOS_FROM_EMAIL, MAILOS_FROM_NAME, MAILOS_SIGNATURE, MAILOS_PICTURE, and MAILOS_MEDIA.

Multiple Recipients

Using Comma Separation

bash
mailos send \
  --to "[email protected],[email protected],[USER3_ADDRESS]" \
  --cc "[email protected]" \
  --bcc "[email protected]" \
  --subject "Team Update" \
  --body "Meeting at 3pm"

Using Multiple Flags

bash
mailos send \
  --to [email protected] \
  --to [email protected] \
  --cc [email protected] \
  --subject "Notice" \
  --body "Important information"

Attachments

Single Attachment

bash
mailos send \
  --to [email protected] \
  --subject "Report" \
  --body "Please see attached" \
  --attach report.pdf

Media Attachment

bash
mailos send \
  --to [email protected] \
  --subject "Photo" \
  --body "Please see attached media" \
  --media assets/photo.png

Multiple Attachments

bash
mailos send \
  --to [email protected] \
  --subject "Documents" \
  --body "All requested files attached" \
  --attach "file1.pdf,file2.docx,data.xlsx"

Email Scheduling

You can schedule emails to be sent at a specific time or after a delay using the scheduling flags.

Schedule for Specific Time

bash
mailos send \
  --to [email protected] \
  --subject "Meeting Reminder" \
  --body "Don't forget our meeting tomorrow" \
  --schedule-at "2024-01-15T09:00:00Z"

Schedule with Delay

bash
mailos send \
  --to [email protected] \
  --subject "Weekly Update" \
  --body "Here's this week's progress..." \
  --schedule-in "2h30m"

Scheduling Flags

FlagDescriptionExample
--schedule-atSchedule for specific time (RFC3339 format)--schedule-at "2024-01-15T09:00:00Z"
--schedule-inSchedule after duration--schedule-in "1h30m"
--schedule-listList all scheduled emails--schedule-list
--schedule-cancelCancel scheduled emails--schedule-cancel --filter "to:*@example.com"

Sending Draft Emails

You can send all emails from your drafts folder at once using the --drafts flag.

Basic Draft Sending

bash
mailos send --drafts
mailos send --draft-id d_0123456789ab
mailos send --draft-id d_0123456789ab --preview
mailos send draft d_0123456789ab
mailos send ~/.email/drafts/d_0123456789ab.md --dry-run
mailos send ~/.email/drafts/d_0123456789ab.md --override-to [email protected] --dry-run

Pass a local draft Markdown path directly to select that draft. --preview and --dry-run are non-sending modes for drafts, show the complete message, and do not delete the local Markdown file.

mailos send draft <id> is the concise human ID-based form. It displays the complete signed email, then asks Send this draft? [y/N]. MailOS reads and hashes one immutable snapshot internally, so the operator does not need to copy its revision. Declining or sending EOF retains the draft and prints its path and mailos drafts edit <id> command. Add --preview or --dry-run for a non-interactive inspection.

Pressing Ctrl+C also exits without sending or changing the draft.

The bare shorthand refuses to prompt when stdin is not a terminal, returning immediate human-only guidance instead. Automated workflows must use --preview and pass the resulting --draft-revision explicitly, so agents cannot become stuck waiting for confirmation.

Draft preview, dry-run, and live delivery append the resolved project or account signature without writing that signature into the authoritative draft file.

Use --override-to with one draft to replace all of its original To, CC, and BCC recipients for a test preview or send. The draft file itself is not changed.

Human operators can use --force-send to send one draft immediately without supplying a preview revision:

bash
mailos send --draft-id d_0123456789ab --force-send
mailos send ~/.email/drafts/d_0123456789ab.md --force-send

This bypasses only the revision guard. Draft validation still runs. --force-send is intentionally reserved for direct human terminal use; automated agents and LLM workflows must continue to preview and pass the returned --draft-revision.

Draft Sending with Options

bash
mailos send --drafts \
  --dry-run \
  --confirm \
  --filter "priority:high" \
  --log-file sent_drafts.log

Draft Flags

FlagDescriptionDefaultExample
--draftsSend all draft emailsfalse--drafts
--draft-idSend exactly one local draft by ID--draft-id d_0123456789ab
--override-toReplace all recipients on one draft with test To recipients--override-to [email protected]
--force-sendHuman-only: send one draft without a preview revisionfalse--force-send
--draft-dirDirectory containing drafts~/.email/drafts--draft-dir ./my-drafts
--dry-runShow draft send metadata without sendingfalse--dry-run
--previewRender draft contents without sendingfalse--preview
--confirmConfirm before sending each draftfalse--confirm
--delete-afterDelete drafts after sending instead of retaining them with status: sentfalse--delete-after
--filterFilter which drafts to send--filter "to:*@company.com"
--log-fileLog sent emails to file--log-file sent.log

Forward existing message context under a draft before previewing or sending:

bash
mailos send --draft-id d_0123456789ab \
  --forward-message-link "message://%3cabc%40example.com%3e" \
  --preview

HTML Templates

If you have configured an HTML template using mailos template, it will automatically be applied to your emails unless you use --plain.

Custom HTML Template Files

Use the --template-html flag to specify a custom HTML template file for dynamic templating:

bash
mailos send \
  --to [email protected] \
  --subject "Professional Email" \
  --preheader "Custom template with responsive design" \
  --body "## Welcome to Our Service

Thank you for your interest in our product.

### Key Benefits:
- Professional email design
- Responsive layout
- Custom branding
- Markdown content support

Best regards!" \
  --template-html ./custom-template.html

Template Processing Logic

The system intelligently inserts your content using multiple strategies:

  1. Placeholder: If your template contains , content is inserted there
  2. Content Recognition: Automatically replaces sample content in common templates
  3. Smart Insertion: Finds <main> or <body> tags for content placement
  4. Preheader Replacement: Automatically updates preheader text in templates

Supported Template Features

  • Markdown Conversion: Your Markdown content is converted to HTML before insertion
  • Preheader Integration: Custom preheader text replaces template placeholder
  • Responsive Design: Works with any responsive email template
  • Professional Styling: Maintains template styling while inserting your content

Template Examples

bash
# Use a downloaded template
mailos send --template-html ./responsive-email.html --body "Your content here"

# With preheader customization  
mailos send --template-html ./template.html --preheader "Preview text" --body "Email body"

# Combine with other features
mailos send --template-html ./branded.html --attach file.pdf --body "**Markdown** content"

Examples

Simple Text Email

bash
mailos send \
  --to [email protected] \
  --subject "Hello" \
  --body "How are you?" \
  --plain

Professional Email with Markdown

bash
mailos send \
  --to [email protected] \
  --subject "Project Proposal" \
  --preheader "Comprehensive solution for your digital transformation needs" \
  --body "Dear Client,

**Project Overview**

We are pleased to present our proposal for your consideration.

## Deliverables
1. Design phase
2. Implementation
3. Testing
4. Deployment

Please review and let us know if you have questions.

Best regards"

Email from Template File

bash
# Create template file
cat > email_template.md << EOF
Dear {{Name}},

Thank you for your interest in our services.

**Next Steps:**
- Schedule a call
- Review documentation
- Sign agreement

Best regards,
Sales Team
EOF

# Send using template
mailos send \
  --to [PROSPECT_ADDRESS] \
  --subject "Follow-up" \
  --file email_template.md

Batch Email Script

bash
#!/bin/bash
for email in $(cat recipients.txt); do
  mailos send \
    --to "$email" \
    --subject "Newsletter" \
    --file newsletter.md \
    --attach newsletter.pdf
done

Confirmation Popup System

EmailOS includes a built-in confirmation popup system to ensure safety when sending emails on your behalf, especially when using AI features.

Default Behavior

When sending emails, a native system dialog appears showing:

  • Email details: Recipients, subject, and body preview
  • ⏰ 5-second countdown: Email will be sent automatically after 5 seconds
  • 🔑 Keyboard shortcuts: ENTER to send immediately, ESC to cancel
  • Manual controls: "Cancel" and "Send Now" buttons

User Options

  1. Auto-send: Wait 5 seconds for automatic sending (default behavior)
  2. Quick send: Press ENTER to send immediately
  3. Cancel: Press ESC or click "Cancel" to abort sending
  4. Manual choice: Click "Send Now" or "Cancel" buttons

Bypassing the Popup

For automated scripts or when you want to skip confirmation:

bash
mailos send --to [email protected] --subject "Test" --body "Message" --no-popup

Platform Support

  • macOS: Native AppleScript dialogs with system styling
  • Linux: zenity or kdialog integration
  • Windows: PowerShell-based dialogs
  • Fallback: Cross-platform dialog library

When Popup is Skipped

The confirmation popup is automatically bypassed for:

  • --dry-run mode (preview only)
  • --no-popup flag usage
  • Scheduled emails (--schedule-at / --schedule-in)
  • Draft batch sending (--drafts uses its own confirmation system)

Examples

bash
# Default behavior - shows 5-second countdown popup
mailos send --to [email protected] --subject "Test" --body "Hello"

# Skip popup for automated sending
mailos send --to [email protected] --subject "Auto" --body "Automated message" --no-popup

# Preview without popup or sending
mailos send --to [email protected] --subject "Preview" --body "Test" --dry-run

Error Handling

Common errors and solutions:

Authentication Failed

  • Verify email credentials: mailos info
  • Check app-specific password for Gmail/Outlook
  • Ensure 2FA is properly configured

Attachment Not Found

  • Use absolute paths for attachments and media when needed
  • Check file permissions
  • Verify file exists before sending

SMTP Connection Failed

  • Check internet connection
  • Verify SMTP settings for your provider
  • Ensure firewall allows SMTP ports
  • Dialog not appearing: Check system permissions for AppleScript (macOS) or GUI access
  • Dialog cancelled error: This is normal when user presses ESC or cancels
  • Fallback to terminal: If GUI dialogs fail, EmailOS will prompt in the terminal

Notes

  • Email body supports UTF-8 encoding
  • Use --media for photos, PDFs, and other media-style files that should be attached to a send.
  • Maximum attachment size depends on provider (usually 25MB)
  • HTML and plain text versions are sent as multipart/alternative
  • Sent emails are saved to Sent folder when IMAP is configured
  • Use --plain to force plain text only
  • Markdown tables are supported in HTML output

Released under the MIT License.