選択できるのは25トピックまでです。
トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
557 行
11 KiB
557 行
11 KiB
#!/bin/sh |
|
# mcom [TO] - compose mail |
|
|
|
NL=' |
|
' |
|
|
|
commajoin() { |
|
awk 'NR==1 {l=$0; next} |
|
{l=l", "$0} |
|
END {print l}' |
|
} |
|
|
|
notmine() { |
|
mine="$(maddr -a -h local-mailbox:alternate-mailboxes: "$MBLAZE/profile")" |
|
grep -Fv -e "$mine" |
|
} |
|
|
|
replyfrom() { |
|
addrs="$(maddr -a -h reply-from: "$MBLAZE/profile")" |
|
[ -z "$addrs" ] && addrs="$(maddr -a -h alternate-mailboxes: "$MBLAZE/profile")" |
|
grep -F -e "$addrs" |
|
} |
|
|
|
ouniq() { |
|
awk '!seen[$0]++' |
|
} |
|
|
|
reffmt() { |
|
sed 's/^[^<]*//g;s/[^>]*$//g;s/>[^<]*</>\ |
|
</g' | uniq | sed 's/^/ /' |
|
} |
|
|
|
msgid() { |
|
mgenmid 2>/dev/null | sed 's/^/Message-Id: /' |
|
} |
|
|
|
stampdate() { |
|
if ! mhdr -h date "$1" >/dev/null; then |
|
tmp=$(mktemp -t mcom.XXXXXX) |
|
{ |
|
printf 'Date: ' |
|
mdate |
|
cat "$1" |
|
} >"$tmp" && |
|
mv "$tmp" "$1" |
|
fi |
|
} |
|
|
|
checksensible() { |
|
awk ' |
|
/^$/ { |
|
seenheader=1 |
|
exit |
|
} |
|
!(/^[^ \t][^ \t]*[ \t]*:/ || /^[ \t]/) { |
|
bad=1 |
|
print "invalid header line: "$0 >"/dev/stderr" |
|
} |
|
END { |
|
if (!seenheader) { |
|
print "warning: message does not contain an empty line between headers and body." >"/dev/stderr" |
|
exit 1 |
|
} |
|
if (bad) |
|
exit 1 |
|
} |
|
' "$1" |
|
} |
|
|
|
stripempty() { |
|
tmp=$(mktemp -t mcom.XXXXXX) |
|
msed 's/^[ \t]*$//d' "$1" >"$tmp" |
|
mv "$tmp" "$1" |
|
} |
|
|
|
needs_multipart() { |
|
mhdr -h attach "$1" >/dev/null || |
|
grep -qE '^#[a-zA-Z]+/[a-zA-Z0-9+.;=#-]+ ' "$1" |
|
} |
|
|
|
do_mime() { |
|
if needs_multipart "$draft"; then |
|
( |
|
IFS=$NL |
|
msed '/attach/d' "$draft" |
|
for f in $(mhdr -M -h attach "$draft"); do |
|
printf '#%s %s\n' \ |
|
"$(file -Lb --mime "$f" | sed 's/ //g')" \ |
|
"$f" |
|
done |
|
) | mmime >"$draftmime" |
|
else |
|
mmime -r <"$draft" >"$draftmime" |
|
fi |
|
if [ $? -ne 0 ]; then |
|
printf 'mcom: fix above errors before continuing\n' 1>&2 |
|
rm -f "$draftmime" |
|
fi |
|
} |
|
|
|
MBLAZE=${MBLAZE:-$HOME/.mblaze} |
|
|
|
sendmail=$(mhdr -h sendmail "$MBLAZE/profile") |
|
sendmail_args=$(mhdr -h sendmail-args "$MBLAZE/profile") |
|
sendmail="${sendmail:-sendmail} ${sendmail_args:--t}" |
|
default_from=$(mhdr -h local-mailbox "$MBLAZE/profile") |
|
|
|
defaultc=e |
|
|
|
hdrs= |
|
resume= |
|
noquote= |
|
case "$0" in |
|
*mcom*) |
|
hdr=to |
|
while [ $# -gt 0 ]; do |
|
case "$1" in |
|
--) |
|
# -- is like -to, really |
|
shift |
|
hdr=to |
|
;; |
|
-r) |
|
shift |
|
resume=1 |
|
if [ "$#" -gt 0 ]; then |
|
case "$1" in |
|
/*|./*) draft="$1";; |
|
*) draft="./$1";; |
|
esac |
|
if ! [ -f "$draft" ]; then |
|
printf 'mcom: no such draft %s\n' \ |
|
"$draft" 1>&2 |
|
exit 1 |
|
fi |
|
echo "using draft $draft" |
|
shift |
|
fi |
|
;; |
|
-send) |
|
defaultc=justsend |
|
shift;; |
|
-??*) |
|
hdr=${1#-} |
|
shift;; |
|
[!-]*) |
|
hdrs="$hdrs$NL$(printf '%s: %s\n' "${hdr}" "$1")" |
|
shift;; |
|
*) |
|
printf 'mcom: invalid argument %s\n' "$1" 1>&2 |
|
exit 1;; |
|
esac |
|
done |
|
;; |
|
*mfwd*) |
|
hdr= |
|
raw= |
|
while [ $# -gt 0 ]; do |
|
case "$1" in |
|
--) |
|
shift |
|
break;; |
|
-r) |
|
shift |
|
raw=1;; |
|
-send) |
|
defaultc=justsend |
|
shift;; |
|
-??*) |
|
hdr=${1#-} |
|
shift;; |
|
[!-]*) |
|
[ -z "$hdr" ] && break |
|
hdrs="$hdrs$NL$(printf '%s: %s\n' "${hdr}" "$1")" |
|
shift;; |
|
*) |
|
printf 'mfwd: invalid argument %s\n' "$1" 1>&2 |
|
exit 1;; |
|
esac |
|
done |
|
[ "$#" -eq 0 ] && set -- . |
|
;; |
|
*mbnc*) |
|
hdr= |
|
while [ $# -gt 0 ]; do |
|
case "$1" in |
|
--) |
|
shift |
|
break;; |
|
-send) |
|
defaultc=justsend |
|
shift;; |
|
-??*) |
|
hdr=${1#-} |
|
shift;; |
|
[!-]*) |
|
[ -z "$hdr" ] && break |
|
hdrs="$hdrs$NL$(printf '%s: %s\n' "${hdr}" "$1")" |
|
shift;; |
|
*) |
|
printf 'mbnc: invalid argument %s\n' "$1" 1>&2 |
|
exit 1;; |
|
esac |
|
done |
|
[ "$#" -eq 0 ] && set -- . |
|
;; |
|
*mrep*) |
|
hdr= |
|
while [ $# -gt 0 ]; do |
|
case "$1" in |
|
--) |
|
shift |
|
break;; |
|
-send) |
|
defaultc=justsend |
|
shift;; |
|
-noquote) |
|
noquote=1 |
|
shift;; |
|
-??*) |
|
hdr=${1#-} |
|
shift;; |
|
[!-]*) |
|
[ -z "$hdr" ] && break |
|
hdrs="$hdrs$NL$(printf '%s: %s\n' "${hdr}" "$1")" |
|
shift;; |
|
*) |
|
printf 'mrep: invalid argument %s\n' "$1" 1>&2 |
|
exit 1;; |
|
esac |
|
done |
|
[ "$#" -eq 0 ] && set -- . |
|
;; |
|
esac |
|
|
|
hdrs="$(printf '%s\n' "${hdrs#$NL}" | mhdr -)" |
|
|
|
outbox=$(mhdr -h outbox "$MBLAZE/profile" | sed "s:^~/:$HOME/:") |
|
if [ -z "$outbox" ]; then |
|
if [ -z "$resume" ]; then |
|
i=0 |
|
while [ -f "snd.$i" ]; do |
|
i=$((i+1)) |
|
done |
|
draft="./snd.$i" |
|
elif [ -z "$draft" ]; then |
|
draft=$(ls -1t ./snd.*[0-9] | sed 1q) |
|
fi |
|
draftmime="$draft.mime" |
|
else |
|
if [ -z "$resume" ]; then |
|
draft="$(true | mdeliver -v -c -XD "$outbox")" |
|
if [ -z "$draft" ]; then |
|
printf '%s\n' "$0: failed to create draft in outbox $outbox." 1>&2 |
|
exit 1 |
|
fi |
|
elif [ -z "$draft" ]; then |
|
draft=$(mlist -D "$outbox" | msort -r -M | sed 1q) |
|
fi |
|
draftmime="$(printf '%s\n' "$draft" | sed 's,\(.*\)/cur/,\1/tmp/mime-,')" |
|
fi |
|
|
|
if [ -n "$resume" ] && [ -z "$draft" ]; then |
|
echo "mcom: no draft found" |
|
exit 1 |
|
fi |
|
|
|
[ -z "$resume" ] && |
|
{ |
|
case "$0" in |
|
*mcom*) |
|
{ |
|
printf '%s' "$hdrs" | mhdr -M -h to - | |
|
commajoin | sed 's/^/To: /' |
|
printf '%s' "$hdrs" | mhdr -M -h cc - | |
|
commajoin | sed 's/^/Cc: /' |
|
printf '%s' "$hdrs" | mhdr -M -h bcc - | |
|
commajoin | sed 's/^/Bcc: /' |
|
printf '%s\n' "$hdrs" | awk '{ print }' | |
|
msed "/to/d; /cc/d; /bcc/d; /body/d" - |
|
} | msed "/cc/a//; /bcc/a//; /subject/a//; /from/a/$default_from/" - | sed '/^$/d' |
|
msgid |
|
museragent |
|
cat "$MBLAZE/headers" 2>/dev/null |
|
printf '\n' |
|
( |
|
IFS=$NL |
|
cat -- /dev/null $(printf '%s' "$hdrs" | mhdr -M -h body -) |
|
) |
|
printf '\n' |
|
;; |
|
*mfwd*) |
|
{ |
|
printf '%s' "$hdrs" | mhdr -M -h to - | |
|
commajoin | sed 's/^/To: /' |
|
printf '%s' "$hdrs" | mhdr -M -h cc - | |
|
commajoin | sed 's/^/Cc: /' |
|
printf '%s' "$hdrs" | mhdr -M -h bcc - | |
|
commajoin | sed 's/^/Bcc: /' |
|
COLUMNS=10000 mscan -f 'Subject: Fwd: [%f] %s' "$@" 2>/dev/null | sed 1q |
|
printf '%s\n' "$hdrs" | awk '{ print }' | |
|
msed "/to/d; /cc/d; /bcc/d" - |
|
} | msed "/cc/a//; /bcc/a//; /from/a/$default_from/" - | sed '/^$/d' |
|
msgid |
|
museragent |
|
cat "$MBLAZE/headers" 2>/dev/null |
|
printf '\n\n' |
|
if [ -z "$raw" ]; then |
|
mseq -r "$@" | sed 's:^:#message/rfc822#inline :; s:$:>:' |
|
else ( |
|
SEP=----- |
|
IFS=$NL |
|
for f in $(mseq -r "$@"); do |
|
printf '%s Forwarded message from %s %s\n\n' \ |
|
$SEP "$(mhdr -d -A -h from "$f")" $SEP |
|
DISPLAY= mshow -n -N "$f" </dev/null | |
|
sed 's/^-/- &/' # RFC 934 |
|
printf '\n%s %s %s\n\n' \ |
|
$SEP 'End forwarded message' $SEP |
|
done |
|
) fi |
|
;; |
|
*mbnc*) |
|
set -- $(mseq -- "$@") |
|
if [ "$#" -ne 1 ]; then |
|
printf 'mbnc: needs exactly one mail to bounce\n' 1>&2 |
|
exit 1 |
|
fi |
|
|
|
{ |
|
printf '%s' "$hdrs" | mhdr -M -h resent-to - | |
|
commajoin | sed 's/^/Resent-To: /' |
|
printf '%s' "$hdrs" | mhdr -M -h resent-cc - | |
|
commajoin | sed 's/^/Resent-Cc: /' |
|
printf '%s\n' "$hdrs" | awk '{ print }' | |
|
msed "/resent-to/d; /resent-cc/d" - |
|
} | |
|
msed "/resent-to/a//; /resent-from/a/$default_from/" - | sed '/^$/d' |
|
msgid | sed 's/^/Resent-/' |
|
printf 'Resent-Date: %s\n' "$(mdate)" |
|
( |
|
IFS=$NL |
|
cat $(mseq -- "$@") |
|
) |
|
;; |
|
*mrep*) |
|
set -- $(mseq -- "$@") |
|
if [ "$#" -ne 1 ]; then |
|
printf 'mrep: needs exactly one mail to reply to\n' 1>&2 |
|
exit 1 |
|
fi |
|
|
|
ng=$(mhdr -h newsgroups "$1") |
|
if [ "$ng" ]; then |
|
printf 'Newsgroups: %s\n' "$ng" |
|
else |
|
to=$(mhdr -d -h reply-to "$1") |
|
[ -z "$to" ] && to=$(mhdr -d -A -h from "$1") |
|
printf 'To: %s\n' "$to" |
|
printf 'Cc: %s\n' \ |
|
"$(mhdr -d -A -h to:cc: "$1" | |
|
notmine |grep -Fv -e "$to" | |
|
ouniq |commajoin)" |
|
printf 'Bcc: \n' |
|
printf '%s\n' "$hdrs" | awk '{ print }' | |
|
msed "/body/d" - |
|
fi | sed '/^$/d' |
|
printf 'Subject: Re: %s\n' "$(COLUMNS=10000 mscan -f '%S' "$1")" |
|
if ! printf '%s\n' "$hdrs" | awk '{ print }' | |
|
mhdr -h from: - >/dev/null; then |
|
addr=$(maddr -a -h delivered-to:to:cc:bcc: "$1" | replyfrom | head -n1) |
|
[ -n "$addr" ] && from=$(maddr -h reply-from "$MBLAZE/profile" | grep -Fi "<$addr>" | head -n1) |
|
[ -n "$addr" ] && [ -z "$from" ] && from=$(maddr -h alternate-mailboxes "$MBLAZE/profile" | grep -Fi "<$addr>" | head -n1) |
|
[ -z "$from" ] && from=$(mhdr -h local-mailbox "$MBLAZE/profile") |
|
[ -n "$from" ] && printf 'From: %s\n' "$from" |
|
fi |
|
mid=$(mhdr -h message-id "$1") |
|
if [ "$mid" ]; then |
|
printf 'References:' |
|
{ |
|
mhdr -h references "$1" |
|
printf '%s\n' "$mid" |
|
} | reffmt |
|
printf 'In-Reply-To: %s\n' "$mid" |
|
fi |
|
msgid |
|
museragent |
|
cat "$MBLAZE/headers" 2>/dev/null |
|
printf '\n' |
|
|
|
if [ -z "$noquote" ]; then |
|
mquote "$1" |
|
printf '\n' |
|
fi |
|
( |
|
IFS=$NL |
|
cat -- /dev/null $(printf '%s' "$hdrs" | mhdr -M -h body -) |
|
) |
|
printf '\n' |
|
;; |
|
esac |
|
|
|
case "$0" in |
|
*mbnc*) ;; |
|
*) |
|
if [ -f "$MBLAZE/signature" ]; then |
|
SIGNATURE="$MBLAZE/signature" |
|
elif [ -f ~/.signature ]; then |
|
SIGNATURE="$HOME/.signature" |
|
fi |
|
|
|
if [ -n "$SIGNATURE" ]; then |
|
printf '%s\n' '-- ' |
|
cat "$SIGNATURE" |
|
fi |
|
esac |
|
} >"$draft" |
|
|
|
automime= |
|
c=$defaultc |
|
while :; do |
|
case "$c" in |
|
s|send) |
|
case "$(mhdr -h newsgroups "$draft")" in |
|
*gmane.*) sendmail="mblow -s news.gmane.org";; |
|
*.*) sendmail="mblow";; |
|
esac |
|
|
|
resent="$(maddr -h resent-to "$draft")" |
|
case "$resent" in |
|
?*) |
|
sendmail=$(mhdr -h sendmail "$MBLAZE/profile") |
|
sendmail="${sendmail:-sendmail} -- $resent" |
|
;; |
|
esac |
|
|
|
if [ -e "$draftmime" ]; then |
|
if [ "$draft" -ot "$draftmime" ] || [ "$automime" = 1 ]; then |
|
stampdate "$draftmime" |
|
if $sendmail <"$draftmime"; then |
|
if [ "$outbox" ]; then |
|
mv "$draftmime" "$draft" |
|
mflag -d -S "$draft" |
|
else |
|
rm "$draft" "$draftmime" |
|
fi |
|
else |
|
printf '%s\n' "mcom: $sendmail failed, kept draft $draft" |
|
exit 2 |
|
fi |
|
else |
|
printf 'mcom: re-run mmime first.\n' |
|
c= |
|
continue |
|
fi |
|
else |
|
if mmime -c <"$draft" && ! [ "$automime" = 1 ]; then |
|
stampdate "$draft" |
|
if $sendmail <"$draft"; then |
|
if [ "$outbox" ]; then |
|
mflag -d -S "$draft" |
|
else |
|
rm "$draft" |
|
fi |
|
else |
|
printf '%s\n' "mcom: $sendmail failed, kept draft $draft" |
|
exit 2 |
|
fi |
|
else |
|
printf '%s\n' "mcom: message needs to be MIME-encoded first." |
|
c= |
|
continue |
|
fi |
|
fi |
|
|
|
case "$0" in |
|
*mrep*) mflag -R -- "$1" ;; |
|
*mbnc*) mflag -P -- "$1" ;; |
|
*mfwd*) mflag -P -- "$@" ;; |
|
esac |
|
case "$0" in |
|
*mrep*|*mbnc*|*mfwd*) mseq -f | mseq -S ;; |
|
esac |
|
|
|
exit 0 |
|
;; |
|
c|cancel) |
|
stampdate "$draft" |
|
printf '%s\n' "mcom: cancelled draft $draft" |
|
exit 1 |
|
;; |
|
m|mime) |
|
do_mime |
|
mshow -t "$draftmime" |
|
c= |
|
;; |
|
e|edit) |
|
c= |
|
if ! ${VISUAL:-${EDITOR:-vi}} "$draft"; then |
|
c=d |
|
else |
|
if checksensible "$draft"; then |
|
stripempty "$draft" |
|
if mmime -c <"$draft" && ! needs_multipart "$draft"; then |
|
automime= |
|
else |
|
automime=1 |
|
do_mime |
|
fi |
|
else |
|
printf '\n' |
|
fi |
|
fi |
|
;; |
|
justsend) |
|
stripempty "$draft" |
|
if mmime -c <"$draft" && ! needs_multipart "$draft"; then |
|
automime= |
|
else |
|
automime=1 |
|
do_mime |
|
fi |
|
c=send |
|
;; |
|
d|delete) |
|
rm -i "$draft" |
|
if ! [ -f "$draft" ]; then |
|
rm -f "$draftmime" |
|
printf '%s\n' "mcom: deleted draft $draft" |
|
exit 0 |
|
fi |
|
c= |
|
;; |
|
sign) |
|
msign "$draft" >"$draftmime" |
|
mshow -t "$draftmime" |
|
c= |
|
;; |
|
encrypt) |
|
mencrypt "$draft" >"$draftmime" |
|
mshow -t "$draftmime" |
|
c= |
|
;; |
|
p|preview|show) |
|
if [ -e "$draftmime" ]; then |
|
mshow "$draftmime" |
|
else |
|
mshow "$draft" |
|
fi |
|
c= |
|
;; |
|
*) |
|
printf 'What now? (%s[s]end, [c]ancel, [d]elete, [e]dit, [m]ime, [p]review, sign, encrypt) ' "${automime:+mime and }" |
|
read -r c |
|
;; |
|
esac |
|
done
|
|
|