#!/bin/bash # CHAIN: # cat invite.ics | ./import_khal.sh # cat invite.ics | ./gen_reply.sh [accept|...] > reply.ics # cat reply.ics | ./gen_email.sh > reply.eml # cat reply.eml | msmtp-wrap.sh sender recipient # cat invite.ics | ./gen_mail_reply.sh > reply.eml (get the sender and recipient from the invite.ics) # Usage: cat mail.eml | ./msmtp-wrap.sh [sender_address] [recipient_address] if [ $# -eq 2 ]; then SENDER_ADDRESS="$1" RECPT_ADDRESS="$2" else SENDER_ADDRESS="" RECPT_ADDRESS="" fi; MCONFIG_DIR="${HOME}/.config/msmtp-wrap" MSMTP_MCONFIG_DIR="${HOME}/.config/msmtp" # IMPORTANT: Apparmor limits the paths msmtp can read ! # see /etc/apparmor.d/usr.bin.msmtp for a list of allowed paths ! MSMTP_LCONFIG_DIR="/tmp" #TMPDIR=/tmp CUR_DATE=$(date +%s) cur_inc=0 FILE=$(cat) # First, get the header section # and the body section of the message # fed to the program MAIL_HEAD_RAW='' MAIL_MIMEHEAD='' MAIL_CONTENT_RAW='' isbody=0 ismime=0 ismid=0 isdate=0 while IFS= read -r line; do if [ $isbody -eq 0 ]; then # if we are not in the body section yet, check if the line # looks like a header printf '%s\n' "$line" | grep -q -E '^([[:graph:]]*:| ).*' if [ $? -eq 0 ]; then printf '%s\n' "$line" | grep -q -Ei '^Message-ID:.*' retmih=$? printf '%s\n' "$line" | grep -q -Ei '^Date:.*' retdh=$? # printf '%s\n' "$line" | grep -q -Ei '^(MIME-Version|Content-(Type|Disposition|Transfer-Encoding)):.*' # retmh=$? printf '%s\n' "$line" | grep -q -E '^( ).*' rethf=$? if [ $retmih -eq 0 ] || ([ $ismid -eq 1 ] && [ $rethf -eq 0 ]); then # if the line looks like a message-id header, discard it ismid=1 isdate=0 ismime=0 elif [ $retdh -eq 0 ] || ([ $isdate -eq 1 ] && [ $rethf -eq 0 ]); then # if the line looks like a date header, discard it ismid=0 isdate=1 ismime=0 # elif [ $retmh -eq 0 ] || ([ $ismime -eq 1 ] && [ $rethf -eq 0 ]); then # # if the line looks like a mime header, save it in a different var # ismime=1 # if [ -z "$MAIL_MIMEHEAD" ]; then # MAIL_MIMEHEAD=$(printf '%s\n' "$line") # else # MAIL_MIMEHEAD=$(printf '%s\n' "$MAIL_MIMEHEAD" ; printf '%s\n' "$line") # fi # # Note: We don't do anything with the collected mime # # headers they are just discarded for now. We # # effectively replace them with our own. This implies # # that we are converting the original e-mail body to a # # utf-8, quoted-printable e-mail. else ismid=0 isdate=0 ismime=0 # if the line looks like a # non-message-id, # non-date, # non-mime header, put it in the # headersection file # printf '%s\n' "$line" # printf '%s\n' "$line" >> ${TMPDIR}/mail-head_raw.txt if [ -z "$MAIL_HEAD_RAW" ]; then MAIL_HEAD_RAW=$(printf '%s\n' "$line") else MAIL_HEAD_RAW=$(printf '%s\n' "$MAIL_HEAD_RAW" ; printf '%s\n' "$line") fi fi else # if the line doesn't look like a header, check if it's an # empty line printf '%s\n' "$line" | grep -q -E '^$' if [ $? -ne 0 ]; then # if the line is not empty, put it in the bodysection # file # printf '%s\n' "$line" # printf '%s\n' "$line" >> ${TMPDIR}/mail-content_raw.txt if [ -z "$MAIL_CONTENT_RAW" ]; then MAIL_CONTENT_RAW=$(printf '%s\n' "$line") else MAIL_CONTENT_RAW=$(printf '%s\n' "$MAIL_CONTENT_RAW" ; printf '%s\n' "$line") fi fi # acknowledge that we are in the body section isbody=1 fi else # if we are in the body section, put the line in the # bodysection file # printf '%s\n' "$line" # printf '%s\n' "$line" >> ${TMPDIR}/mail-content_raw.txt if [ -z "$MAIL_CONTENT_RAW" ]; then MAIL_CONTENT_RAW=$(printf '%s\n' "$line") else MAIL_CONTENT_RAW=$(printf '%s\n' "$MAIL_CONTENT_RAW" ; printf '%s\n' "$line") fi fi done <&2 exit 1 else MAIL_HEAD_UNFOLDED=$( printf '%s\n' "To: ${RECPT_ADDRESS}" ; printf '%s\n' "$MAIL_HEAD_UNFOLDED" | grep -iv '^To:'; ) fi fi # Note: The 'From:' header can appear only once in an e-mail # Search for the From: header address # If non-null, keep it # otherwise create a new From: header based on ${SENDER_ADDRESS} MFROMFULL_HEAD_VALUE=$(printf '%s\n' "$MAIL_HEAD_UNFOLDED" | grep -i '^From:' | sed s/'^[fF][rR][oO][mM]:[ \t\r\v\n\f]*'/''/) if [ "x$MFROMFULL_HEAD_VALUE" == "x" ]; then if [ "x$SENDER_ADDRESS" == "x" ]; then printf '%s\n' "No sender address found ! Aborting." >&2 exit 1 else MAIL_HEAD_UNFOLDED=$( printf '%s\n' "From: ${SENDER_ADDRESS}" ; printf '%s\n' "$MAIL_HEAD_UNFOLDED" | grep -iv '^From:'; ) fi fi # We read a file ~/.config/send_mail.sh/${SENDER_CANONICAL_ADDRESS}.conf # which contains: # a. the name of the msmtp config file # b. a copy of all the MUA options we need: # - folder (Maildir mailbox) # - record (Sent folder) # - from header (copy of 'my_hdr From:' or 'set from') # - bcc header (copy of 'my_hdr Bcc:') # - openpgp header (copy of 'my_hdr OpenPGP:') # - possibly some openpgp info (in case we want to sign/encrypt in the future) SENDER_CANONICAL_ADDRESS=$( printf '%s\n' "${SENDER_ADDRESS}" | sed -E s/'([^+ \t]+?)(\+[ \t]+?)?@([ \t]+)'/'\1@\3'/ ) . ${MCONFIG_DIR}/${SENDER_CANONICAL_ADDRESS}.conf # printf '%s\n' "msmtp_config: $msmtp_config" >&2 # printf '%s\n' "msmtp_account: $msmtp_account" >&2 # printf '%s\n' "folder: $folder" >&2 # printf '%s\n' "record: $record" >&2 # printf '%s\n' "header_from: $header_from" >&2 # printf '%s\n' "header_bcc: $header_bcc" >&2 # printf '%s\n' "header_openpgp: $header_openpgp" >&2 # printf '%s\n' "pgp_default_key: $pgp_default_key" >&2 # printf '%s\n' "crypt_autosign: $crypt_autosign" >&2 # printf '%s\n' "crypt_replyencrypt: $crypt_replyencrypt" >&2 # printf '%s\n' "crypt_replysignencrypted: $crypt_replysignencrypted" >&2 # Note: The 'Bcc:' header can appear only once in an e-mail # If there is a bcc header in config # Search for the Bcc: header address # Create a new Bcc: header or add a new field to existing Bcc: header if [ "x$header_bcc" != "x" ]; then BCC_HEAD=$(printf '%s\n' "$MAIL_HEAD_UNFOLDED" | grep -i -m1 '^Bcc:') if [ "x$BCC_HEAD" != "x" ]; then BCC_HEAD_VALUE=$(printf '%s\n' "$BCC_HEAD" | sed s/'^[bB][cC][cC]:[ \t\r\v\n\f]*'/''/) if [ "x$BCC_HEAD_VALUE" != "x" ]; then header_bcc=", ${header_bcc}" fi MAIL_HEAD_UNFOLDED=$( printf '%s\n' "$MAIL_HEAD_UNFOLDED" | sed -E s/'^([bB][cC]{2}:.*)'/"\1${header_bcc}"/; ) else MAIL_HEAD_UNFOLDED=$( printf '%s\n' "$MAIL_HEAD_UNFOLDED"; printf '%s\n' "Bcc: ${header_bcc}" ; ) fi fi MAIL_CUR_DATE=$(date -R -d "@${CUR_DATE}") # Search for a Date: header # If non-null, keep it # otherwise create a new Date: header DATE_HEAD_VALUE=$(printf '%s\n' "$MAIL_HEAD_UNFOLDED" | grep -i '^Date:' | sed s/'^[dD][aA][tT][eE]:[ \t\r\v\n\f]*'/''/) if [ "x$DATE_HEAD_VALUE" == "x" ]; then MAIL_HEAD_UNFOLDED=$( printf '%s\n' "$MAIL_HEAD_UNFOLDED" | grep -iv '^Date:'; printf '%s\n' "Date: ${MAIL_CUR_DATE}" ; ) fi MAIL_MSG_ID=$(date '+%Y%m%d%H%M%S' -d "@${CUR_DATE}").$(tr -dc 0-9A-Z &2 printf '%s\n' "$FILE" >&2 printf '%s\n' "=== ===" >&2 # eventually we send the e-mail # printf '%s\n' "* msmtp -C ${MSMTP_MCONFIG_DIR}/${SENDER_CANONICAL_ADDRESS}.conf -f $SENDER_ADDRESS -t -- $RECPT_ADDRESS" >&2 # printf '%s\n' "$FILE" | msmtp -C "${MSMTP_MCONFIG_DIR}/${SENDER_CANONICAL_ADDRESS}.conf" -f "$SENDER_ADDRESS" -t -- "$RECPT_ADDRESS" printf '%s\n' "* msmtp -C ${MSMTP_MCONFIG_DIR}/${SENDER_CANONICAL_ADDRESS}.conf --read-envelope-from -t --" >&2 printf '%s\n' "$FILE" | msmtp -C "${MSMTP_MCONFIG_DIR}/${SENDER_CANONICAL_ADDRESS}.conf" --read-envelope-from -t -- ret=$? # if successful, we copy the file in our Sent folder if [ $ret -eq 0 ]; then cur_pid=$$ cur_inc=$(( $cur_inc + 1 )) cur_host=$(hostname) filename="${CUR_DATE}.${cur_pid}_${cur_inc}.${cur_host}" printf '%s\n' "** printf '%s\n' \"\$FILE\" > ${record}/new/${filename}" printf '%s\n' "$FILE" > ${record}/new/${filename} fi # No need to configure password, since it's a one-time use # we'll give it when we are prompted for it # config_password () { # account="$1" # printf '%s' "Password for ${account}: " # read -s password &2 # cp "${MSMTP_MCONFIG_DIR}/${account}.conf" "${MSMTP_LCONFIG_DIR}/.${USER}_msmtp_${account}.conf" # printf '%s\n' "* chmod -R 600 ${MSMTP_LCONFIG_DIR}/.${USER}_msmtp_${account}.conf" >&2 # chmod -R 600 "${MSMTP_LCONFIG_DIR}/.${USER}_msmtp_${account}.conf" # sed -i "s/#password dummy/password \"${password}\"/" "${MSMTP_LCONFIG_DIR}/.${USER}_msmtp_${account}.conf" # } # cd $HOME # if [ -e "${MSMTP_LCONFIG_DIR}/.${USER}_msmtp_${SENDER_ADDRESS}.conf" ]; then # printf '%s\n' "File ${MSMTP_LCONFIG_DIR}/.${USER}_msmtp_${SENDER_ADDRESS}.conf already exist" >&2 # else # printf '%s\n' "* $0" >&2 # config_password "$SENDER_ADDRESS" # fi # printf '%s\n' "* msmtp -C ${MSMTP_LCONFIG_DIR}/.${USER}_msmtp_${SENDER_ADDRESS}.conf -f $SENDER_ADDRESS -t -- $RECPT_ADDRESS" >&2 # printf '%s\n' "$FILE" | msmtp -C "${MSMTP_LCONFIG_DIR}/.${USER}_msmtp_${SENDER_ADDRESS}.conf" -f "$SENDER_ADDRESS" -t -- "$RECPT_ADDRESS"