EmailOS Send Command Documentation
The mailos send command sends emails with support for markdown formatting, attachments, and signatures.
Basic Usage
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:
mailos configure --test-to-email [email protected]
mailos send --to [email protected] --subject "Check" --body "Test message" --testTest 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:
mailos send --to [email protected] --subject "Photos" --body "See attached" --media assets/photo.png{
"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.
mailos send \
--group ./recipients.txt \
--subject "Initial outreach" \
--body "Hello" \
--campaign-id "spring-2026" \
--send-separatelyThen retrieve the campaign originals and replies with:
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
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
| Flag | Short | Type | Default | Description | Example |
|---|---|---|---|---|---|
--account | string | Email account to use | mailos send --account value | ||
--bcc | []string | BCC recipients | mailos send --bcc value | ||
--body | -b | string | Email body (Markdown supported). Use @path/to/file to load file content | mailos send --body value | |
--cc | -c | []string | CC recipients | mailos send --cc value | |
--from | string | Email account to use (alias for --account) | mailos send --from value | ||
--subject | -s | string | Email subject | mailos send --subject value | |
--to | -t | []string | Recipient email addresses | mailos send --to value |
Advanced Options
| Flag | Short | Type | Default | Description | Example |
|---|---|---|---|---|---|
--attach | -a | []string | Attachments | mailos send --attach value | |
--campaign-id | string | Add a shared hidden X-MailOS-Campaign-ID header for later search | mailos send --campaign-id value | ||
--check-duplicate | bool | false | Check if email with same subject has already been sent to recipients | mailos send --check-duplicate | |
--confirm | bool | false | Confirm before sending each draft | mailos send --confirm | |
--delete-after | bool | false | Delete drafts after successful sending instead of retaining them as sent | mailos send --delete-after | |
--draft-dir | string | Directory containing draft emails (default: ~/.email/drafts) | mailos send --draft-dir value | ||
--drafts | bool | false | Send all draft emails from .email/drafts folder | mailos send --drafts | |
--electron-path | string | Custom path to Electron app (default: ~/Desktop/mailos-electron-ui) | mailos send --electron-path value | ||
--file | -f | string | Read body from file | mailos send --file value | |
--filter | string | Filter drafts (e.g., 'priority:high', 'to:*@example.com') | mailos send --filter value | ||
--force | bool | false | Force send email bypassing dynamic content warnings and template validation | mailos send --force | |
--forward-message-id | string | Append the matching received email thread by Message-ID below the message body | mailos send --forward-message-id value | ||
--forward-message-link | string | Append the matching received email thread from a mail client message link, such as macOS Mail message://... | mailos send --forward-message-link value | ||
--from-name | string | Override the sender's display name | mailos send --from-name value | ||
--group | -g | string | Send to a saved email group or local recipient metadata file | mailos send --group value | |
--input | bool | false | Open Electron UI for composing email instead of sending directly | mailos send --input | |
--log-file | string | Log sent emails to file | mailos send --log-file value | ||
--media | []string | Media attachments such as photos, PDFs, or other files | mailos send --media value | ||
--model | string | Model to use for natural language parsing (auto-detects if not specified) | mailos send --model value | ||
--no-popup | bool | true | Skip confirmation popup and send directly | mailos send --no-popup | |
--no-signature | bool | false | No signature | mailos send --no-signature | |
--no-validate | bool | false | Skip email address validation | mailos send --no-validate | |
--ollama-url | string | http://localhost:11434 | Ollama server URL for natural language processing | mailos send --ollama-url value | |
--plain | -p | bool | false | Send as plain text | mailos send --plain |
--preheader | string | Brief preview text shown after subject line (30-100 characters recommended) | mailos send --preheader value | ||
--provider | string | ollama | AI provider for natural language parsing (ollama|vllm) | mailos send --provider value | |
--replace | []string | Replace dynamic content with KEY=VALUE pairs (e.g., --replace USER_NAME=John --replace DATE=2024-01-01) | mailos send --replace value | ||
--schedule-at | string | Schedule email to be sent at specific time (RFC3339 format: 2024-01-01T15:04:05Z) | mailos send --schedule-at value | ||
--schedule-cancel | bool | false | Cancel scheduled emails (use with --filter) | mailos send --schedule-cancel | |
--schedule-in | string | Schedule email to be sent after duration (e.g., '1h30m', '2h', '30s') | mailos send --schedule-in value | ||
--schedule-list | bool | false | List all scheduled emails | mailos send --schedule-list | |
--send-separately | bool | false | Send a separate email to each To recipient | mailos send --send-separately | |
--signature | string | Custom signature | mailos send --signature value | ||
--template | bool | false | Apply HTML template to email | mailos send --template | |
--template-html | string | Path to custom HTML template file | mailos send --template-html value | ||
--test | bool | false | Send only to the test recipient saved in the global config | mailos send --test | |
--validate | bool | true | Validate recipient email addresses before sending (enabled by default) | mailos send --validate | |
--validate-smtp | bool | false | Perform SMTP verification during validation (slower but more thorough) | mailos send --validate-smtp | |
--vllm-url | string | http://localhost:8290 | VLLM server URL for natural language processing | mailos send --vllm-url value |
Output Options
| Flag | Short | Type | Default | Description | Example |
|---|---|---|---|---|---|
--dry-run | bool | false | Preview what would be sent without actually sending | mailos send --dry-run | |
--preview | bool | false | Preview the complete email without sending | mailos send --preview | |
--verbose | -v | bool | false | Show detailed SMTP debugging information | mailos send --verbose |
Email Address Validation
EmailOS automatically validates recipient email addresses before sending to prevent bounce-backs. Validation is enabled by default and checks:
- Email syntax - Verifies the email format is valid
- Domain existence - Confirms the domain exists via DNS lookup
- MX records - Checks if the domain can receive email
Validation Behavior
# 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
# 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" --forceVerbose Validation
# 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 successfullyStandalone Validation
For bulk validation before sending, use the dedicated validate command:
# Validate addresses without sending
mailos validate [email protected] [email protected] --verbose
# See validate command documentation for more options
mailos validate --helpMarkdown 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:
- itemor1. item - Headers:
# Header - Code blocks:
language ```
Example with Markdown
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
mailos send --to [email protected] --subject "Test" --body "Message"2. From File
mailos send --to [email protected] --subject "Report" --file ./report.md3. 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.
mailos send --group ./recipients.md --body "Hello team"
mailos send --group ./recipients.txt --body "Hello team" --plainFrontmatter format:
---
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:
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)
mailos send --to [email protected] --subject "Weekly Update" --body @./examples/send-bodies/plain-update.txtUse @@ to send a literal value that starts with @:
mailos send --to [email protected] --subject "Literal" --body "@@start-with-at"5. Interactive (stdin)
mailos send --to [email protected] --subject "Notes"
# Then type your message and press Ctrl+D6. Piped Input
echo "Automated message" | mailos send --to [email protected] --subject "Alert"7. Include a Previous Chain as Forwarded Text
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:
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
mailos send \
--to [email protected] \
--subject "Proposal" \
--body "Please find attached..." \
--signature "Best regards,\nJohn Smith\nSales Manager\nCompany Inc."No Signature
mailos send --to [email protected] --subject "Test" --body "Message" --no-signatureAccount 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
# 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 accountsto list configured accounts and aliases - Use
mailos account --set [EMAIL]to set the default account for the session - Use
mailos account --clearto clear the session default account - If
--account/--fromis 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.
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_EMAILas theFromaddress - If
--accountdiffers, EmailOS logs that it will still send usingMAILOS_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:
mailos config --values
mailos envIf an AI client or wrapper script needs the resolved values as real shell variables, run:
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
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
mailos send \
--to [email protected] \
--to [email protected] \
--cc [email protected] \
--subject "Notice" \
--body "Important information"Attachments
Single Attachment
mailos send \
--to [email protected] \
--subject "Report" \
--body "Please see attached" \
--attach report.pdfMedia Attachment
mailos send \
--to [email protected] \
--subject "Photo" \
--body "Please see attached media" \
--media assets/photo.pngMultiple Attachments
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
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
mailos send \
--to [email protected] \
--subject "Weekly Update" \
--body "Here's this week's progress..." \
--schedule-in "2h30m"Scheduling Flags
| Flag | Description | Example |
|---|---|---|
--schedule-at | Schedule for specific time (RFC3339 format) | --schedule-at "2024-01-15T09:00:00Z" |
--schedule-in | Schedule after duration | --schedule-in "1h30m" |
--schedule-list | List all scheduled emails | --schedule-list |
--schedule-cancel | Cancel 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
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-runPass 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:
mailos send --draft-id d_0123456789ab --force-send
mailos send ~/.email/drafts/d_0123456789ab.md --force-sendThis 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
mailos send --drafts \
--dry-run \
--confirm \
--filter "priority:high" \
--log-file sent_drafts.logDraft Flags
| Flag | Description | Default | Example |
|---|---|---|---|
--drafts | Send all draft emails | false | --drafts |
--draft-id | Send exactly one local draft by ID | --draft-id d_0123456789ab | |
--override-to | Replace all recipients on one draft with test To recipients | --override-to [email protected] | |
--force-send | Human-only: send one draft without a preview revision | false | --force-send |
--draft-dir | Directory containing drafts | ~/.email/drafts | --draft-dir ./my-drafts |
--dry-run | Show draft send metadata without sending | false | --dry-run |
--preview | Render draft contents without sending | false | --preview |
--confirm | Confirm before sending each draft | false | --confirm |
--delete-after | Delete drafts after sending instead of retaining them with status: sent | false | --delete-after |
--filter | Filter which drafts to send | --filter "to:*@company.com" | |
--log-file | Log sent emails to file | --log-file sent.log |
Forward existing message context under a draft before previewing or sending:
mailos send --draft-id d_0123456789ab \
--forward-message-link "message://%3cabc%40example.com%3e" \
--previewHTML 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:
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.htmlTemplate Processing Logic
The system intelligently inserts your content using multiple strategies:
- Placeholder: If your template contains
, content is inserted there - Content Recognition: Automatically replaces sample content in common templates
- Smart Insertion: Finds
<main>or<body>tags for content placement - 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
# 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
mailos send \
--to [email protected] \
--subject "Hello" \
--body "How are you?" \
--plainProfessional Email with Markdown
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
# 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.mdBatch Email Script
#!/bin/bash
for email in $(cat recipients.txt); do
mailos send \
--to "$email" \
--subject "Newsletter" \
--file newsletter.md \
--attach newsletter.pdf
doneConfirmation 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
- Auto-send: Wait 5 seconds for automatic sending (default behavior)
- Quick send: Press ENTER to send immediately
- Cancel: Press ESC or click "Cancel" to abort sending
- Manual choice: Click "Send Now" or "Cancel" buttons
Bypassing the Popup
For automated scripts or when you want to skip confirmation:
mailos send --to [email protected] --subject "Test" --body "Message" --no-popupPlatform 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-runmode (preview only)--no-popupflag usage- Scheduled emails (
--schedule-at/--schedule-in) - Draft batch sending (
--draftsuses its own confirmation system)
Examples
# 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-runError 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
Popup Dialog Issues
- 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
--mediafor 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
--plainto force plain text only - Markdown tables are supported in HTML output
