jaromail

a commandline tool to easily and privately handle your e-mail
git clone git://parazyd.org/jaromail.git
Log | Files | Refs | Submodules | README

commit dfa27a5b7fa391a424b14e3e7a5e618783804cd2
parent 28ab90e4ff96fc81af1ced9124813738d0172da5
Author: Jaromil <jaromil@dyne.org>
Date:   Wed, 14 Jan 2015 18:09:09 +0100

smtp cli command and cleanup, exitcode cleanup

Diffstat:
Mbuild/build-gnu.sh | 11+++++++++++
Msrc/jaro | 87++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Msrc/zlibs/email | 114++++++++++++++++++++++++++++++++++++-------------------------------------------
Msrc/zlibs/filters | 4++--
Msrc/zlibs/helpers | 21+++++++++++++++++++++
5 files changed, 135 insertions(+), 102 deletions(-)

diff --git a/build/build-gnu.sh b/build/build-gnu.sh @@ -117,6 +117,17 @@ mkdir -p build/gnu print OK } +{ test "$target" = "gpgewrap" } || { + test "$target" = "all" } && { + print -n "Compiling the GnuPG wrapper... " + pushd src + ${=cc} -c gpgewrap.c -I . + ${=cc} -o gpgewrap gpgewrap.o + popd + cp src/gpgewrap build/gnu/ + print OK +} + { test "$target" = "gnome-keyring" } || { test "$target" = "all" } && { diff --git a/src/jaro b/src/jaro @@ -32,7 +32,6 @@ for arg in ${argv}; do OLDARGS+=($arg); done QUIET=0 DEBUG=0 DRYRUN=0 -CLEANEXIT=1 CALLMUTT=1 # default permission on files @@ -88,7 +87,7 @@ typeset -h mutt pgpewrap dotlock # global variable for exit code typeset exitcode -exitcode=0 +# exitcode=0 # global variable for infos on imap folder # format: name;num_of_messages;size_in_bytes @@ -259,6 +258,7 @@ KEYRING="$MAILDIRS/Keyring" _endgame() { func "endgame() $1" [[ "$1" = "EXIT" ]] || { + error "QUIT signal sent to processes, waiting 2 seconds..." global_quit=1 sleep 2 } @@ -273,17 +273,19 @@ _endgame() { func "unlocking notmuch/Xapian search cache" unlock "$MAILDIRS"/cache/notmuch } + func "endgame() exit code: $exitcode" } # Trap functions for the _endgame event -TRAPINT() { _endgame INT } -TRAPEXIT() { _endgame EXIT } -TRAPHUP() { _endgame HUP } -TRAPQUIT() { _endgame QUIT } -TRAPABRT() { _endgame ABORT } -TRAPKILL() { _endgame KILL } -TRAPPIPE() { _endgame PIPE } -TRAPTERM() { _endgame TERM } -TRAPSTOP() { _endgame STOP } +TRAPINT() { _endgame INT; return $exitcode } +# TRAPEXIT() { _endgame EXIT; return $exitcode } +TRAPHUP() { _endgame HUP; return $exitcode } +TRAPQUIT() { _endgame QUIT; return $exitcode } +TRAPABRT() { _endgame ABORT; return $exitcode } +TRAPKILL() { _endgame KILL; return $exitcode } +TRAPPIPE() { _endgame PIPE; return $exitcode } +TRAPTERM() { _endgame TERM; return $exitcode } +TRAPSTOP() { _endgame STOP; return $exitcode } +# TRAPZERR() { func "function returns non-zero." } case $OS in GNU) @@ -582,6 +584,11 @@ main() subcommands_opts[extract]="" + subcommands_opts[smtp]="" + + subcommands_opts[crypt]="" + subcommands_opts[cryptsign]="" + ### Detect subcommand local -aU every_opts #every_opts behave like a set; that is, an array with unique elements for optspec in $subcommands_opts$main_opts; do @@ -606,7 +613,6 @@ main() [[ $exitcode = 0 ]] || { error "command \"$subcommand\" not recognized" act "try -h for help" - CLEANEXIT=0 } return $exitcode fi @@ -662,11 +668,11 @@ main() fi ADDRESSBOOK="$MAILDIRS"/$list.abook } - { option_is_set -h } && { CLEANEXIT=0 - usage; return 0 } - { option_is_set -v } && { CLEANEXIT=0 - cat $JAROMAILEXEC | awk 'BEGIN { v=1 } !/^#/ { exit }' - return 0 } + { option_is_set -h } && { usage; return 0 } + { option_is_set -v } && { + cat $JAROMAILEXEC | awk 'BEGIN { v=1 } !/^#/ { exit }' + return 0 + } { option_is_set -q } && { QUIET=1 } { option_is_set -D } && { DEBUG=1; QUIET=0 func "All debug messages ON" } @@ -701,24 +707,21 @@ main() update_sieve ;; - help) CLEANEXIT=0; usage ;; + help) usage ;; - index) CLEANEXIT=0; - nm_index - ;; - search) CLEANEXIT=0; search ${PARAM} ;; - - notmuch) CLEANEXIT=0; + index) nm_index ;; + search) search ${PARAM} ;; + notmuch) notice "Command: notmuch ${PARAM}" nm ${PARAM} ;; - stat) CLEANEXIT=0; stats ${PARAM} ;; + stat) stats ${PARAM} ;; - complete) CLEANEXIT=0; complete ${PARAM} ;; - isknown) CLEANEXIT=0; sender_isknown ${PARAM} ;; - learn) CLEANEXIT=0; learn ${PARAM} ;; - forget) CLEANEXIT=0; forget ${PARAM} ;; + complete) complete ${PARAM} ;; + isknown) sender_isknown ${PARAM} ;; + learn) learn ${PARAM} ;; + forget) forget ${PARAM} ;; import) import ${PARAM} ;; "export") @@ -735,9 +738,9 @@ main() abook) edit_abook ${PARAM} ;; - edit|vim) CLEANEXIT=0; edit_file ${PARAM} ;; - open) CLEANEXIT=0; open_folder ${PARAM} ;; - preview) CLEANEXIT=0; preview_file ${PARAM} ;; + edit|vim) edit_file ${PARAM} ;; + open) open_folder ${PARAM} ;; + preview) preview_file ${PARAM} ;; backup) backup ${PARAM} ;; rmdupes) rmdupes ${PARAM} ;; @@ -765,7 +768,7 @@ main() pubdb_render_maildir "$md" exitcode=$? ;; - 'source') CLEANEXIT=0; return 0 ;; + 'source') return 0 ;; __default) func "no command provided" autostart ${PARAM} exitcode=$? @@ -802,7 +805,6 @@ main() # ;; *) error "imap needs a subcommand: getsize or listfolders" - CLEANEXIT=0 ;; esac ;; @@ -812,21 +814,30 @@ main() exitcode=$? ;; + crypt) + crypt_queue ${PARAM} + exitcode=$? + ;; + + smtp) + smtp_send ${PARAM} + exitcode=$res + ;; + *) # unknown command, pass it to autostart func "unknown command, remote check" autostart ${PARAM} exitcode=$? - { $exitcode != 0 } && { + [[ $exitcode = 0 ]] || { error "command \"$subcommand\" not recognized" act "try -h for help" - CLEANEXIT=0 } ;; esac - exitcode=$? - return 0 } + check_bin main $@ +_endgame EXIT return $exitcode diff --git a/src/zlibs/email b/src/zlibs/email @@ -255,21 +255,9 @@ fetch() { return 0 } - -###### -# SEND -# this function should send all mails in outbox -send() { - adir="$WORKDIR/Accounts" - - - # list mails to send - queue_outbox=`${=find} "${MAILDIRS}/outbox" -type f` - queue_outbox_num=`print $queue_outbox | wc -l` - [[ "$queue_outbox" = "" ]] && { - notice "Outbox is empty, no mails to send." - return 0 } - +################################################ +# read an email from stdin and send it via msmtp +smtp_send() { read_account ${account} { test $? != 0 } && { error "Invalid account: $account" @@ -280,28 +268,60 @@ send() { [[ -z $auth ]] && { auth=plain } [[ -z $smtp_port ]] && { smtp_port=25 } - is_online ${smtp} ${smtp_port} - [[ $? = 0 ]] || { - error "Smtp host not reachable: $smtp_host:$smtp_port" - return 1 } - - notice "Sending out $queue_outbox_num mails via account ${account}" - - [[ $DRYRUN = 1 ]] && { return 0 } - - # from here on we must unlock on error - lock "${MAILDIRS}/outbox" + notice "SMTP send via account ${account}" type=smtp host=$smtp port=$smtp_port + ask_password [[ $? = 0 ]] || { error "Error retrieving password for $login on $smtp" unset password - unlock "${MAILDIRS}/outbox" return 1 } + _tmp_create + msmtpcfg="$JAROTMP" + cat <<EOF > $msmtpcfg +account default +from ${email} +user ${login} +host ${smtp} +port ${smtp_port} +tls on +tls_starttls on +tls_certcheck on +# tls_fingerprint sha1 44:e8:10:ef:35:fc:54:51:fd:84:cf:59:de:af:a9:ab:a1:55:b8:41 +# tls_fingerprint md5 88:65:6e:6d:a5:66:92:a1:9c:47:18:66:d5:b8:56:49 +tls_fingerprint 6A:D4:DF:E4:20:32:F9:66:94:35:0C:33:9D:74:96:5C +logfile "${MAILDIRS}/logs/msmtp.log" +auth ${auth} +password ${password} +EOF + unset password + msmtp -C $msmtpcfg -t + res=$? + func "msmtp returns: $res" + return $res +} + + +###### +# SEND +# this function should send all mails in outbox +send() { + # list mails to send + queue_outbox=`${=find} "${MAILDIRS}/outbox" -type f` + queue_outbox_num=`print $queue_outbox | wc -l` + [[ "$queue_outbox" = "" ]] && { + notice "Outbox is empty, no mails to send." + return 0 } + + [[ $DRYRUN = 1 ]] && { return 0 } + + # from here on we must unlock on error + lock "${MAILDIRS}/outbox" + for qbody in ${(f)queue_outbox}; do func "processing outbox queue: $qbody" # clean interrupt @@ -317,22 +337,6 @@ send() { _tmp_create anoncfg="$JAROTMP" - _tmp_create - msmtpcfg="$JAROTMP" - cat <<EOF > $msmtpcfg -account default -from ${email} -user ${login} -host ${smtp} -port ${smtp_port} -tls on -tls_starttls on -tls_certcheck off -logfile "${MAILDIRS}/logs/msmtp.log" -auth ${auth} -password ${password} -EOF - cat <<EOF > "$anoncfg" REMAIL n POOLSIZE 0 @@ -345,13 +349,13 @@ 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 $msmtpcfg -t +SENDMAIL=jaro -q smtp ERRLOG=${MAILDIRS}/logs/mixmaster.log VERBOSE=2 EOF - act "Sending out anonymous email via mixmaster" + notice "Sending out anonymous email via mixmaster" e_addr=() hdr $qbody | e_parse To hdr $qbody | e_parse Cc @@ -378,7 +382,7 @@ BEGIN { body=0 } else # normal send with msmtp - act "Sending out email" + act "Sending out email via ${account:-default}" hdr "$qbody" | awk ' /^From:/ { print " . " $0 } /^To:/ { print " . " $0 } @@ -388,20 +392,7 @@ BEGIN { body=0 } tsize=`stat -c '%s' "$qbody"` act "sending `human_size $tsize` over the network ..." - msmtp -C <(cat <<EOF -account default -from ${email} -user ${login} -host ${smtp} -port ${smtp_port} -tls on -tls_starttls on -tls_certcheck off -logfile "${MAILDIRS}/logs/msmtp.log" -auth ${auth} -password ${password} -EOF - ) -t < "${qbody}" + jaro -q smtp -a ${account:-default} < "${qbody}" res=$? fi @@ -418,10 +409,9 @@ EOF done - unset password unlock "$MAILDIRS/outbox" - return 0 + return $res } ###### diff --git a/src/zlibs/filters b/src/zlibs/filters @@ -458,10 +458,10 @@ EOF cat <<EOF >> "$MUTTDIR"/rc ## GnuPG specific settings # create a pgp/mime encrypted attachment -set pgp_encrypt_only_command="pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust -- -r %r $gpgkey -- '%f'" +set pgp_encrypt_only_command="pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust --encrypt-to $gpgkey -- -r %r -- '%f'" # create a pgp/mime encrypted and signed attachment -set pgp_encrypt_sign_command="pgpewrap gpg %?p?--passphrase-fd 0? --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r $gpgkey -- '%f'" +set pgp_encrypt_sign_command="pgpewrap gpg %?p?--passphrase-fd 0? --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust --encrypt-to $gpgkey -- -r %r -- '%f'" ## end of Jaro Mail generated muttrc #################################### diff --git a/src/zlibs/helpers b/src/zlibs/helpers @@ -377,6 +377,27 @@ human_size() { ###### # CERT # downloads and/or installs certificates + + +# TODO: save fingeprints of servers and check connections +fingerprint() { + read_account ${account} + { test $? != 0 } && { + error "Invalid account: $account" + return 1 + } + # defaults + [[ -z $smtp_port ]] && { smtp_port=25 } + + print QUIT \ + | openssl s_client -starttls smtp \ + -connect $smtp:$smtp_port \ + -showcerts 2>/dev/null \ + | openssl x509 -fingerprint -md5 -noout \ + | awk -F '=' '/^MD5 Fingerprint/ {print $2}' + +} + cert() { act "Downloading all known certificates (needs Internet connectivity)"