commit 4a12cc222848994d4d797743f9a580c0b903c78d
parent a92bfd3efbf6f766699c8b62b6d46c5ec9f18760
Author: Jaromil <jaromil@dyne.org>
Date: Sun, 4 May 2014 20:44:27 +0200
new mixmaster support to send anonymous emails
Diffstat:
M | TODO.md | | | 38 | +++++++++++++++++++++++--------------- |
M | src/zlibs/email | | | 161 | ++++++++++++++++++++++++++++++++++++++++++++++++------------------------------- |
2 files changed, 121 insertions(+), 78 deletions(-)
diff --git a/TODO.md b/TODO.md
@@ -5,6 +5,29 @@
https://dyne.org/donate
+## Vacation trigger
+sieve script example
+
+```
+
+require ["fileinto", "vacation", "variables"];
+
+if header :is "X-Spam-Flag" "YES" {
+ fileinto "Spam";
+}
+
+if header :matches "Subject" "*" {
+ set "subjwas" ": ${1}";
+}
+
+vacation
+ :days 1
+ :subject "Out of office reply${subjwas}"
+"I'm out of office, please contact Joan Doe instead.
+Best regards
+John Doe";
+```
+
## Peek to open imap folders with reverse Date ordering
when open, imap folders should list emails without threading
this is really intended for a peek
@@ -37,14 +60,6 @@
PLAN: use isync and open local maildirs
-## Mixmaster
- basically is an almost finished implementation, only thing
- missing is to clear out the header handling between jaromail and mutt
-
-## Multiple outboxes
- handle different send programs
- for example anonymous/ for the mixmaster queue
-
## Substitute procmail with a simple C filter
we just filter From, To:, CC: and mailman headers
@@ -57,13 +72,6 @@
## TBT
time based text, all included in html mails
-## Install
- * Full integration with the Tomb process creation
- * integrate install/setup command in jaro
-
-## Mouse enable MUA
- mutt or mu in debian?
- * Find out how to make mouse selection work
## Speedmail or Quickmail
write down a mail from commandline and send it right away (if online)
diff --git a/src/zlibs/email b/src/zlibs/email
@@ -23,8 +23,8 @@
# extract all emails found in stdin, one per line
extract_emails() {
awk '{ for (i=1;i<=NF;i++)
- if ( $i ~ /[[:alnum:]]@[[:alnum:]]/ ) {
- gsub(/<|>|,/ , "" , $i); print $i } }'
+ if ( $i ~ /[[:alnum:]]@[[:alnum:]]/ ) {
+ gsub(/<|>|,/ , "" , $i); print $i } }'
}
compose() {
@@ -48,9 +48,12 @@ queue() {
queue_to=($@)
# set it ready for saving in outbux
queue_body="$base"
- cat > $TMPDIR/$queue_body.mail
-
+ # pre-processing of the email headers
+ cat | awk '
+/User-Agent:/ { print "User-Agent: Jaro Mail <http://jaromail.dyne.org>"; next }
+{ print $0 }
+' > "$TMPDIR/${queue_body}.mail"
maildirmake $MAILDIRS/outbox
{ test $? = 0 } || {
@@ -76,18 +79,17 @@ queue() {
# bodies: the list of mail bodies to send
# corresponding to files with same name and extension .msmtp
bodies=(`find $tmppp -type f -name '*.mail'`)
- rcpt=(`find $tmppp -type f -name '*.msmtp'`)
for i in ${bodies}; do mv $i $MAILDIRS/outbox/new/; done
- for i in ${rcpt}; do mv $i $MAILDIRS/outbox/send/${i%%.msmtp}.rcpt; done
rmdir $tmppp
fi
}
- mkdir -p $MAILDIRS/outbox/send
+ ${=mkdir} $MAILDIRS/outbox/send
lock $MAILDIRS/outbox
+ # check if recipients are a Group
if [[ "${=queue_to}" =~ '@jaromail.group' ]]; then
- # recipients are in a group
+
groupfile="`print ${=queue_to}|cut -d@ -f1`"
act "email recipients are in group ${groupfile}"
@@ -104,7 +106,8 @@ queue() {
groupmode="`head -n1 $MAILDIRS/Groups/$groupfile | awk '/^#mode/ { print $2 } { next }'`"
{ test "$groupmode" = "" } && { groupmode="individual" }
act "$groupnum recipients in total, sending mode $groupmode"
-
+
+
case $groupmode in
# individual group mode hides other recipients and send
@@ -112,12 +115,9 @@ queue() {
individual)
for i in ${(f)recipients}; do
ig=${base}-${RANDOM}
- cat ${TMPDIR}/${queue_body}.mail | \
+ cat "${TMPDIR}/${queue_body}.mail" | \
awk '/^To:/ { print "'"To: $i"'"; next } { print $0 }' \
> ${MAILDIRS}/outbox/new/${ig}.mail
- # TODO: check email validation and <stripping>
- print "$i" | sed 's/.*<//;s/>$//' \
- > ${MAILDIRS}/outbox/send/${ig}.rcpt
done
;;
@@ -130,28 +130,16 @@ queue() {
else cc+=", $i"; fi
done
ig=${base}-${RANDOM}
- cat ${TMPDIR}/${queue_body}.mail | \
+ cat "${TMPDIR}/${queue_body}.mail" | \
awk '/^To:/ { print "'"To: $cc"'"; print "'"Reply-To: $cc"'"; next }
- { print $0 }' \
- > ${MAILDIRS}/outbox/new/${ig}.mail
- # extract emails one per line
- rcpt=`print $cc | extract_emails`
- func "cc: $cc"
- func "rcpt: $rcpt"
- print ${=rcpt} > ${MAILDIRS}/outbox/send/${ig}.rcpt
+ { print $0 }' \
+ > ${MAILDIRS}/outbox/new/${ig}.mail
;;
esac
else
# recipients are set in the email envelope
- act "email recipients: $queue_to"
- # file into the outbox filtering headers
- cat $TMPDIR/$queue_body.mail | awk '
-/User-Agent:/ { print "User-Agent: Jaro Mail <http://jaromail.dyne.org>"; next }
-{ print $0 }
-' > $MAILDIRS/outbox/new/$queue_body.mail
- rm $TMPDIR/$queue_body.mail
- print "${=queue_to}" > $MAILDIRS/outbox/send/$queue_body.rcpt
+ mv $TMPDIR/$queue_body.mail $MAILDIRS/outbox/new/$queue_body.mail
fi
unlock $MAILDIRS/outbox
@@ -211,8 +199,8 @@ fetch() {
# return here if the imap folders are all empty
# { test ${imap_info[${#imap_info}]} = 0 } && {
- # act "Mailbox is empty, nothing to fetch."
- # return 0 }
+ # act "Mailbox is empty, nothing to fetch."
+ # return 0 }
# notice "Total occupation is `human_size ${imap_info[${#imap_info}]}`"
@@ -303,8 +291,8 @@ send() {
# list mails to send
- queue_rcpt=(`${=find} ${MAILDIRS}/outbox/send -type f -name '*.rcpt'`)
- { test ${#queue_rcpt} = 0 } && {
+ queue_outbox=(`${=find} ${MAILDIRS}/outbox -type f -name '*.mail'`)
+ { test ${#queue_outbox} = 0 } && {
act "Outbox is empty, no mails to send."
return 0 }
@@ -321,7 +309,7 @@ send() {
is_online ${host} ${port}
{ test $? = 0 } || { return 1 }
- notice "Sending out ${#queue_rcpt} mails via ${type}.${account}"
+ notice "Sending out ${#queue_outbox} mails via ${type}.${account}"
{ test $DRYRUN = 1 } && { return 0 }
@@ -351,41 +339,88 @@ logfile ${MAILDIRS}/logs/msmtp.log
auth ${auth}
password ${password}
EOF
- unset password
- for q in ${queue_rcpt}; do
- qr=`basename ${q%%.rcpt}`
- func "looking for a mail body to send labeled $qr"
- qbody=(`${=find} $MAILDIRS/outbox -type f -name "${qr}.mail*"`)
- func "found ${#qbody} hits: ${=qbody}"
- recipients=(`cat $q`)
- func "recipients: ${=recipients}"
-
- { test ${#qbody} = 0 } && {
- # body for rcpt not found, mail must have been deleted from outbox
- act "canceled delivery for a deleted mail to: `cat $q`"
- ${=rm} $q
- continue }
-
- { test ${#qbody} -gt 1 } && {
- error "too many mail bodies found for a message to: `cat $q`"
- error "this is quite confusing, check your outbox, we'll skip for now."
- continue }
-
- act "To: ${=recipients}"
- msmtp -C $tmp -- ${=recipients} < "${qbody}"
- if [ $? != 0 ]; then
+ for qbody in ${queue_outbox}; do
+
+ # check if this is an anonymous mail
+ head -n 20 "$qbody" | grep -i '^from: anon' > /dev/null
+ if [ $? = 0 ]; then
+ anoncfg="${TMPDIR}/${host}.anon.$RANDOM"
+ cat <<EOF > "$anoncfg"
+REMAIL n
+POOLSIZE 0
+SENDPOOLTIME 0m
+RATE 100
+
+PGPREMPUBASC /var/lib/mixmaster/used-stats/pubring.asc
+PUBRING /var/lib/mixmaster/used-stats/pubring.mix
+TYPE1LIST /var/lib/mixmaster/used-stats/rlist.txt
+TYPE2REL /var/lib/mixmaster/used-stats/mlist.txt
+TYPE2LIST /var/lib/mixmaster/used-stats/type2.list
+
+SENDMAIL=msmtp -C $tmp -t
+ERRLOG=${MAILDIRS}/logs/mixmaster.log
+VERBOSE=2
+
+EOF
+
+ act "Sending out anonymous email via mixmaster"
+ act "`head -n 20 $qbody | grep '^Subject:'`"
+ recipients=(`cat $qbody | fetchaddr -a -x to | cut -d, -f1`)
+ recipients+=(`cat $qbody | fetchaddr -a -x cc | cut -d, -f1`)
+ for r in ${recipients}; do
+ act "Sending to: ${r}"
+ # strip headers and send via mixmaster
+ cat "$qbody" | awk '
+BEGIN { head=1 }
+/^To: / { print $0; next }
+/^Cc: / { print $0; next }
+/^Bcc: / { print $0; next }
+/^Subject: / { print $0; next }
+/^In-Reply-To: / { print $0; next }
+/^References: / { print $0; next }
+/^Mime-Version: / { print $0; next }
+/^Content-Type: / { print $0; next }
+/^Content-Disposition: / { print $0; next }
+/^$/ { head=0 }
+{ if(head==0) print $0 }
+' | mixmaster --config=$anoncfg -m --to="$r"
+ res=$?
+ func "mixmaster returns $res"
+ done
+
+ ${=rm} $anoncfg
+
+ else # normal send with msmtp
+
+ act "Sending out email"
+ head -n 10 "$qbody" | awk '
+/^From:/ { print " . " $0 }
+/^To:/ { print " . " $0 }
+/^Cc:/ { print " . " $0 }
+/^Subject:/ { print " . " $0 }
+'
+ msmtp -C $tmp -t < "${qbody}"
+ res=$?
+
+ fi
+
+ # evaluate results
+ if [ "$res" != "0" ]; then
error "Error sending mail, skipped"
else
- act "Mail sent succesfully"
- # whitelist those to whom we send mails
+ notice "Mail sent succesfully"
+ # whitelist those to whom we send mails
cat "$qbody" | $WORKDIR/bin/jaro -q learn recipient
- ${=rm} "$q" "$qbody"
+ mv "$qbody" $MAILDIRS/sent/new/
fi
+
done
+ unset password
unlock $MAILDIRS/outbox
- unlink $tmp
+ unlock $tmp
+ ${=rm} $tmp
return 0
}
@@ -441,8 +476,8 @@ EOF
unset password
print "source '$tmp'" > $TMPDIR/muttpass
# when peeking don't mark unread messages as Old
- # and sort date received with no threading (latest up)
- cat <<EOF >> $TMPDIR/muttpass
+ # and sort date received with no threading (latest up)
+ cat <<EOF >> $TMPDIR/muttpass
unset mark_old
set sort=reverse-date-received
EOF