Search code examples
linuxbashemailmandrillgetopt

bash script modify to take parameter from echo command


I have this small bash script(sendmail.sh) to send emails using mandril which works super when used like this ./sendmail.sh "my@email.com" "Email Subject" "Email body". Thanks to black @ LET However I want this script to take its email body from echo command like the linux mail commands works . echo "email body" | mail -s "email subject" email@any.com

When I use the below script with this command echo "email body" |./sendmail.sh "my@email.com" "Email Subject" it prints the error specified in else block(since only 2 arguments are given but 3 needed) /sendmail.sh requires 3 arguments - to address, subject, content Example: ././sendmail.sh "to-address@mail-address.com" "test" "hello this is a test message"

Surprised to see why echo commands output is not being taken as input for $3 argument in the script.

#!/bin/bash
#created by black @ LET
#MIT license, please give credit if you use this for your own projects
#depends on curl

key="" #your maildrill API key
from_email="" #who is sending the email
reply_to="$from_email" #reply email address
from_name="curl sender" #from name


if [ $# -eq 3 ]; then
    msg='{ "async": false, "key": "'$key'", "message": { "from_email": "'$from_email'", "from_name": "'$from_name'", "headers": { "Reply-To": "'$reply_to'" }, "return_path_domain": null, "subject": "'$2'", "text": "'$3'", "to": [ { "email": "'$1'", "type": "to" } ] } }'
    results=$(curl -A 'Mandrill-Curl/1.0' -d "$msg" 'https://mandrillapp.com/api/1.0/messages/send.json' -s 2>&1);
    echo "$results" | grep "sent" -q;
    if [ $? -ne 0 ]; then
        echo "An error occured: $results";
        exit 2;
    fi
else
echo "$0 requires 3 arguments - to address, subject, content";
echo "Example: ./$0 \"to-address@mail-address.com\" \"test\" \"hello this is a test message\""
exit 1;
fi

Solution

  • Why is that surprising? You are mixing arguments and standard input, which are fundamentally completely different.

    However, it's not hard to accommodate this requirement.

    case $# in
       3) text="$3" ;;
       2) text=$(cat) ;;
    esac
    : .... do stuff with "$text"
    

    Your script has slightly sloppy indentation and quoting, so here is a somewhat refactored version.

    key="" #your maildrill API key
    from_email="" #who is sending the email
    from_name="curl sender" #from name
    
    case $# in
      3) text="$3";;
      2) text="$(cat)";;
      *) echo "$0: oops!  Need 2 or 3 arguments -- aborting" >&2; exit 1 ;;
    esac
    
    msg='{ "async": false, "key": "'"$key"'", "message": { "from_email": "'"$from_email"'", "from_name": "'"$from_name"'", "return_path_domain": null, "subject": "'"$2"'", "text": "'"$text"'", "to": [ { "email": "'"$1"'", "type": "to" } ] } }'
    result=$(curl -A 'Mandrill-Curl/1.0' -d "$msg" 'https://mandrillapp.com/api/1.0/messages/send.json' -s 2>&1)
    case $results in
      *"sent"*) exit 0;;
      *) echo "$0: error: $results" >&2; exit 2;;
    esac
    

    Notice in particular how any user-supplied string absolutely must be within double quotes.

    (I took out Reply-To: because it's completely superfluous when it's equal to the From: header.)