# @bobfrankston/mailx-send

Queue-based mail sender with SMTP and OAuth2 support. Messages are queued as RFC 822 `.ltr` files and sent via SMTP with automatic retry.

Part of the [mailx](../../README.md) email client, but usable standalone by any application.

## Install

```bash
npm install @bobfrankston/mailx-send
# or globally for CLI tools:
npm install -g @bobfrankston/mailx-send
```

## Two CLI Commands

This package provides two commands:

- **`mailsend`** — create and queue a new message for sending
- **`mailq`** — manage the outgoing mail queue (process, retry, status)

## Directory Structure

Each account has its own queue:

```
{baseDir}/
  {accountId}/
    queue/        pending .ltr files
    sent/         sent messages (YYYY/MM/DD/) — optional log
    fail/         failed messages awaiting retry
```

## Library API

```typescript
import { initMailSend, queueMessage } from "@bobfrankston/mailx-send";

// Initialize once at startup
initMailSend({
    baseDir: "./mailqueue",
    defaultAccount: "iecc",
    logSent: true,
    retryIntervalMs: 300000,  // 5 min
    accounts: {
        iecc: {
            host: "smtp.iecc.com",
            port: 587,
            auth: "password",
            user: "bob",
            password: "secret",
            from: "Bob Frankston <bob@iecc.com>",
        },
        gmail: {
            host: "smtp.gmail.com",
            port: 587,
            auth: "oauth2",
            user: "bob@gmail.com",
            from: "Bob Frankston <bob@gmail.com>",
            tokenProvider: async () => getOAuthToken(),
        },
    },
});

// Queue a message — returns filename, sends in background
queueMessage({
    from: "Bob Frankston <bob@iecc.com>",
    to: ["alice@example.com"],
    subject: "Hello",
    html: "<p>Rich <b>HTML</b> body</p>",
    accountId: "iecc",
});
```

### MailMessage interface

```typescript
interface MailMessage {
    from: string;           // "Name <address>"
    to: string[];
    cc?: string[];
    bcc?: string[];
    subject: string;
    html?: string;          // HTML body (preferred for rich email)
    text?: string;          // Plain text body
    inReplyTo?: string;     // Message-ID for threading
    references?: string;    // References header for threading
    accountId?: string;     // Queue/account to send from
}
```

### Other API functions

```typescript
import { initMailSend, queueMessage, getMailSender } from "@bobfrankston/mailx-send";

const sender = initMailSend(config);

sender.processQueue("iecc");      // Process one account's queue
sender.processAllQueues();         // Process all accounts
sender.getStatus();                // { iecc: { pending: 2, failed: 0 }, gmail: { ... } }
sender.startWorker();              // Start background retry timer (auto-started by initMailSend)
sender.stopWorker();               // Stop background processing
```

## CLI: mailsend

Create and queue a new message:

```bash
# From CLI arguments
mailsend --to alice@example.com --subject "Hello" --body "Message text"
mailsend -q gmail --from "Bob <bob@gmail.com>" --to alice@example.com --subject "Test"

# From a JSON file
mailsend --json message.json
mailsend --json message.json -q gmail

# From stdin
echo '{"to":["alice@example.com"],"subject":"Test","text":"Hello"}' | mailsend --json -

# Custom config file
mailsend --config /path/to/mailsend.json --to ...
```

### JSON message format

```json
{
    "to": ["alice@example.com"],
    "cc": ["bob@example.com"],
    "from": "Bob Frankston <bob@iecc.com>",
    "subject": "Hello",
    "html": "<p>Rich body</p>",
    "text": "Plain text fallback",
    "accountId": "iecc"
}
```

## CLI: mailq

Manage the outgoing mail queue:

```bash
mailq                     # Show queue status (all accounts)
mailq --process           # Process all queues (send pending, retry failed)
mailq --process -q gmail  # Process only the gmail queue
```

## Configuration

Create `mailsend.json`:

```json
{
    "baseDir": "./mailqueue",
    "defaultAccount": "iecc",
    "logSent": true,
    "retryIntervalMs": 300000,
    "accounts": {
        "iecc": {
            "host": "smtp.iecc.com",
            "port": 587,
            "auth": "password",
            "user": "bob",
            "password": "secret",
            "from": "Bob Frankston <bob@iecc.com>"
        }
    }
}
```

## Queue Format

Messages are stored as `.ltr` files — standard RFC 822 format with an `X-MailSend-Account` header for routing. Filenames: `YYYYMMDD_HHMMSS-NNNN.ltr`

## Building MIME Messages

mailx-send currently builds simple single-part RFC 822 messages (text or HTML). For complex MIME messages (multipart, attachments, inline images), use one of these packages to build the raw message, then pass it to the queue:

- **[nodemailer](https://www.npmjs.com/package/nodemailer)** — `MailComposer` class builds full MIME from parts (already a dependency)
- **[emailjs-mime-builder](https://www.npmjs.com/package/emailjs-mime-builder)** — lightweight MIME builder
- **[mimetext](https://www.npmjs.com/package/mimetext)** — simple API for building MIME messages: `createMimeMessage()`, add text/html/attachments
- **[mailcomposer](https://www.npmjs.com/package/mailcomposer)** — standalone MIME composer (from nodemailer's author)

Example with nodemailer's MailComposer:

```typescript
import MailComposer from "nodemailer/lib/mail-composer";

const mail = new MailComposer({
    from: "Bob <bob@iecc.com>",
    to: "alice@example.com",
    subject: "With attachment",
    html: "<p>See attached</p>",
    attachments: [{ filename: "doc.pdf", path: "/path/to/doc.pdf" }],
});

const raw = await mail.compile().build();
// Write raw to the queue directory as a .ltr file
```

## Retry

Failed messages move to `{accountId}/fail/YYYY/MM/DD/`. The background worker retries at the configured interval (default 5 min) by moving them back to the queue.

## OAuth2 (Gmail)

Set `auth: "oauth2"` and provide a `tokenProvider` function returning a current access token. Integrates with `@bobfrankston/oauthsupport` or any OAuth2 flow.

## Sent Log

When `logSent: true`, sent messages are preserved in `{accountId}/sent/YYYY/MM/DD/` for debugging.

## License

MIT
