Skip to content

Instantly share code, notes, and snippets.

@shanecelis
Created December 11, 2025 08:29
Show Gist options
  • Select an option

  • Save shanecelis/0329cd526490dd86ca42743abf3a5137 to your computer and use it in GitHub Desktop.

Select an option

Save shanecelis/0329cd526490dd86ca42743abf3a5137 to your computer and use it in GitHub Desktop.
Simulate regular mail binary on macOS using Mail.app because I don't have the patience to configure postfix once a blue moon.
#!/bin/bash
# Original code Copyright (c) 2024 Shane Celis[1]
# Licensed under the MIT License[2]
#
# [1]: https://mastodon.gamedev.place/@shanecelis
# [2]: https://opensource.org/licenses/MIT
# mail-app
#
# Simulate regular mail binary but using Mail.app instead because configuring
# postfix is something I don't have the patience for.
script_name="$(basename $0)";
function usage() {
echo "usage: $script_name [-hn] [-s subject] [-f from-addr] to-addr ..." >&2;
echo " -h help, show usage (this)" >&2;
echo " -f the from address, must be an account of Mail.app" >&2;
echo " addr format: 'name@email.com' or 'First Last <name@email.com>'" >&2;
echo " -n dry run, do not send message, opens in Mail.app" >&2;
echo "Simulates Unix 'mail' binary using Mail.app" >&2;
exit 2;
}
from="";
subject="";
dryrun=0;
while getopts hnf:s: opt; do
case $opt in
h) usage;;
n) dryrun=1;;
f) from="sender: \"$OPTARG\",";;
s) subject="$OPTARG";;
*) echo "error: invalid option given." >&2; usage;;
esac
done
shift $[ OPTIND - 1 ]
if [ $# -lt 1 ]; then
echo "error: must provide at least one email address." >&2;
usage;
fi
# Join addresses into a comma-separated string.
addresses=$(printf '"%s", ' "$@")
# Remove last comma.
addresses=${addresses%, }
if [ -z "$subject" ]; then
echo -n "Subject: ";
read subject;
fi
# Read from stdin.
body="$(cat)";
osascript <<EOF
set addresses to {$addresses}
set dryrun to $dryrun
tell application "Mail"
set msg to make new outgoing message with properties {$from subject:"$subject", content:"$body"}
tell msg
repeat with addr in addresses
make new recipient at end of to recipients with properties {address: addr}
end repeat
end tell
if dryrun is 0 then
send msg
end if
end tell
EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment