0

I have the following bash script for sending an email reports. I am trying to get it working correctly with mail command on bash and want to use variable substitution conditional which requires to use eval.

#!/bin/bash

LOG="/tmp/error.txt"
echo "test" > $LOG

INCLUDED="aaaaaaaaaaaaaaaaa"
EXCLUDED="bbbbbbbbbbbbbbbbb"
STR=INCLUDED

BODY="
Email Body:
\${!STR}"

#Set STR based on some condition
STR=EXCLUDED                    # set conditional with if statement

SUB="email subject"
PARAMS="-r \" Sender <ret@address.com>\""
PARAMS+=" -s \"$SUB\""
PARAMS+=" -A $LOG"              # use conditional with if statement

eval echo \"MESSAGE: "${BODY}"\" | mail $(eval echo ${PARAMS}) "user@email.com"

While running the below code, I have to pass $PARAMS output without the quotes around the string as input to mail command, which does not recognise the diff options. The closest I can get to is using calling $(eval echo $PARAMS), but this garbels the subject since it remove the double quotes around the subject.

+ LOG=/tmp/error.txt
+ echo test
+ INCLUDED=aaaaaaaaaaaaaaaaa
+ EXCLUDED=bbbbbbbbbbbbbbbbb
+ STR=INCLUDED
+ BODY='
Email Body:
${!STR}'
+ STR=EXCLUDED
+ SUB='email subject'
+ PARAMS='-r " Sender <ret@address.com>"'
+ PARAMS+=' -s "email subject"'
+ PARAMS+=' -A /tmp/error.txt'
+ eval echo '"MESSAGE:' '
Email Body:
${!STR}"'
++ echo 'MESSAGE: 
Email Body:
bbbbbbbbbbbbbbbbb'
++ eval echo -r '"' Sender '<ret@address.com>"' -s '$SUB' -A /tmp/error.txt
+++ echo -r ' Sender <ret@address.com>' -s email subject -A /tmp/error.txt
+ mail -r Sender '<ret@address.com>' -s email subject -A /tmp/error.txt user@email.com

How do I pass the $PARAMS to the mail command with passing the subject (-s) as quoted string ?

Greg Petr
  • 1,099
  • 2
  • 11
  • 18

1 Answers1

1

Use an array instead and put each string in an array element.

params=('-r')
params=("${params[@]}" ' Sender <ret@address.com>')

mail "${params[@]}"

Or simpler

params=('-r')
params+=(' Sender <ret@address.com>')

mail "${params[@]}"

See here: Bash: add value to array without specifying a key

Update, because I think you lack some fundamental shell programming knowledge.

  1. Don't use eval! If you need to delay an evaluation, write a function, which performs the evaluation, when you call it.
  2. Use single quotes for static strings and double quotes for strings containing variables.
  3. Use arrays, if you need arrays.
  4. Group commands in curly braces, if you need to group commands.

This is you example updated according to the rules above.

LOG=/tmp/error.txt
echo 'test' > $LOG

INCLUDED='aaaaaaaaaaaaaaaaa'
EXCLUDED='bbbbbbbbbbbbbbbbb'
STR=INCLUDED

body () { echo "
Email Body:
$STR"
}

#Set STR based on some condition
STR=EXCLUDED                    # set conditional with if statement

SUB='email subject'
PARAMS=('-r' 'Sender <ret@address.com>')
PARAMS+=('-s' "$SUB")
PARAMS+=('-A' "$LOG")              # use conditional with if statement

{ echo -n 'MESSAGE: '; body; } | mail "${PARAMS[@]}" 'user@email.com'

You can test your code by putting a mail mock-up at the beginning of the program.

mail() { echo mail "$@"; cat; }
Community
  • 1
  • 1
ceving
  • 21,900
  • 13
  • 104
  • 178
  • Does this handle variable substitution within the array variable ? It would result with the same issue – Greg Petr Apr 13 '17 at 07:49
  • The variable substitution happens when you add a value to the array. When you use single quotes no substitution is done and when you use double quotes substitution is done. Variables are evaluates only once. When passing the array to `mail` no substitution is done on the array values, just on the array itself. Otherwise evaluation would happen twice. – ceving Apr 13 '17 at 07:55
  • This solution does not remove the single quote around $PARAMS when it gets substituted. – Greg Petr Apr 13 '17 at 07:59
  • Remote all the `eval`s from your code. They are not necessary and confuse you. – ceving Apr 13 '17 at 08:07
  • Why are you recommending to remove eval's ? How will the $STR and $SUB get substituted then – Greg Petr Apr 13 '17 at 09:00
  • @ceving Variable substitution is performed on unquoted strings those enclosed in double quotes. It is not performed on strings enclosed in single quotes. In your code, you will need to modify `'$SUB'` to `"$SUB"`. Most of the time (which does not mean 100% of the time, but close), `eval` is best avoided, as there is a simpler, easier to maintain, and safer alternative. – Fred Apr 13 '17 at 09:31