mail.mailutils sends, reads and triages local mail from one binary, and which mode you get depends entirely on the arguments you pass it. This guide covers sending a message, checking a mailbox, attaching a file and diagnosing the command-line mistakes that trip people up most. The examples target GNU Mailutils mail.mailutils 3.17, installed here as the mailutils package; mail and mailx are the same command on this system.
Allow about fifteen minutes. You need a shell, a recipient address you are allowed to contact, and a working local mail transport. Sending mail is an external side effect: do not point it at a real recipient until you have reviewed the address, subject and body. Reading a mailbox is normally unprivileged; accessing another user's mailbox may need elevated privileges, authorised separately.
Start with version and help output. These are read-only checks and do not need sudo:
$ mail.mailutils --version
mail.mailutils (GNU Mailutils) 3.17
$ command -v mail.mailutils
/usr/bin/mail.mailutils
$ mail.mailutils --help | sed -n '1,45p'
Version and path may differ on another host. This guide uses the long name so the operation is obvious, but mail and mailx are aliases provided by this installation:
$ command -v mail mailx
/usr/bin/mail
/usr/bin/mailx
Checkpoint: If the command is missing, stop here and install or enable the package through your normal system-management process. Do not copy a mail binary from another host just to make a script pass.
Give it one or more addresses and mail.mailutils enters sending mode. The subject comes from -s, and the body is read from standard input. This example uses a deliberately obvious placeholder address:
$ printf '%s\n' 'Replace this body before sending.' | \
mail.mailutils --subject='Test from mail.mailutils' [email protected]
Swap [email protected] for the approved destination only after checking it. The command normally prints nothing on success. A zero exit status means Mailutils handed the message to its configured transport, not that the recipient received it. A non-zero status means local composition or hand-off failed, and the diagnostic on standard error is the evidence worth reading.
Checkpoint: Capture the status immediately if you are testing a script:
$ printf '%s\n' 'Message body' | mail.mailutils -s 'Subject' [email protected]
$ status=$?
$ printf 'mail exit status: %s\n' "$status"
mail exit status: 0
Do not treat that sample status as a promise about your host. Your local MTA, DNS, credentials and recipient policy decide whether delivery can proceed. If mail reports it cannot connect or invoke its transport, fix that service instead of resending the same message over and over.
Redirect a reviewed text file when the body is longer than one shell string:
$ mail.mailutils --subject='Nightly report' [email protected] < /path/to/report.txt
Redirection reads the file; it does not delete it. Check the path and contents first:
$ test -r /path/to/report.txt && sed -n '1,20p' /path/to/report.txt
Keep the quoting around any subject containing spaces. Never build a command by concatenating an untrusted subject or recipient into a shell string; pass trusted values as separate arguments, and validate addresses upstream if they come from users.
Use --attach=FILE or -A FILE to attach a file to the message you are sending:
$ test -r /path/to/report.pdf
$ printf '%s\n' 'The report is attached.' | \
mail.mailutils --subject='Report with attachment' \
--attach=/path/to/report.pdf [email protected]
Mailutils reads the attachment while composing the outgoing message; it does not modify the source file. Check its size and contents first, because an attachment can carry credentials, personal data or simply more than the recipient needs:
$ ls -lh /path/to/report.pdf
$ file /path/to/report.pdf
For more controlled MIME output, the installed command also offers --content-type, --content-name, --content-filename and --encoding for subsequent attachment options. Reach for those only when the receiving system demands a particular representation. A wrong content type makes an otherwise valid attachment awkward to open; it does not make an unsafe file safe.
With no recipient, mail switches to reading mode. Use --file to pick a mailbox and --headers to print its header summary and exit. Point the example at a mailbox you own:
$ mail.mailutils --file=/path/to/mailbox --headers
No applicable messages
Output depends on the mailbox. If messages exist, expect a numbered header summary rather than every body in full. The command can update message state once you enter the interactive reader, so --headers is the safer first look. Here, an empty file produces the diagnostic above and a non-zero status.
For a script that only needs to know whether mail exists, use --exist:
$ if mail.mailutils --file=/path/to/mailbox --exist; then
> printf '%s\n' 'mail exists'
> else
> printf '%s\n' 'no applicable mail or mailbox could not be read'
> fi
no applicable mail or mailbox could not be read
Check the mailbox permissions and path before reading every non-zero status as "empty inbox". Do not reach for sudo as a general troubleshooting step. If you genuinely administer someone else's mailbox, use the smallest privilege available and avoid writing or deleting messages while you investigate.
Use --print or --read when you deliberately want every message printed to standard output:
$ mail.mailutils --file=/path/to/mailbox --print
This can expose message bodies and attachments to the terminal, logs or a pipeline. Keep it out of shared transcripts and automated logs unless that exposure is the point. Need only the headers? Use --headers instead.
The default startup summary and configuration can make scripted output surprising. Add --no-config for a controlled diagnostic that skips the site and user configuration files:
$ mail.mailutils --no-config --file=/path/to/mailbox --headers
A separate --norc option suppresses the system mailrc, according to this installed help. Prefer the more explicit --no-config when you need to exclude both site and user Mailutils configuration. Never assume a user's mail configuration is harmless: it can supply defaults, alter the transport, or change command behaviour outright.
Mailutils supports --config-file=FILE, which loads a named configuration and implies --no-config, plus --config-lint to check syntax and exit. Validate a proposed file before using it for delivery:
$ mail.mailutils --no-config \
--config-file=/path/to/proposed-mailutils.conf \
--config-lint
$ printf 'config-lint exit status: %s\n' "$?"
config-lint exit status: 0
Use a file you have reviewed, with permissions appropriate to its contents. Configuration can hold transport paths, addresses or other security-sensitive settings. A successful lint check proves syntax, not that the transport works or the resulting policy is sensible. The command makes no configuration change by itself. To undo one, restore the previous file from your configuration-management system or backup, then rerun the lint check before restarting any dependent service.
mail.mailutils --version and check the expected binary is first in PATH.--no-config so they are not hiding the real cause.--config-lint against a proposed configuration, never a production file you have not backed up.A missing mailbox, an unreadable mailbox and a failed delivery are three different problems. Keep the diagnostics separate. Changing permissions, restarting an MTA or resending test messages can affect other users and services, so each of those needs its own explicit decision and a rollback plan.
PATH actually selects.--no-config, --norc and --config-lint make diagnostics reproducible.