Search code examples
linuxbashsedmimepostfix-mta

bash to replace ${} placeholder for attachment


I've been trying use MIME-multipart encoding to send both a plain text and an HTML version of the message using postfix.

I've created a temp-email.txt in tmp directory with the following contents:

From:Sender <xxxx@xxxx.com>
To:Recipient <xxxx@xxxx.com>
Subject: Result
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="MixedBoundaryString"

--MixedBoundaryString
Content-Type: multipart/alternative; boundary="AlternativeBoundaryString"

--AlternativeBoundaryString
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

Result

${detail}

--AlternativeBoundaryString
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<html>
  <head>
</head>
  <body>
    <h1>Result</h1>
      <p>${detail}</p>
  </body>
</html>
--AlternativeBoundaryString--
--MixedBoundaryString
Content-Type: text/plain
MIME-Version: 1.0
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="${filename}"

${attachment}

--MixedBoundaryString--

And I've a bash script that replace ${} placeholders in temp-email.txt.

Following is part of my bash script:

ATTACHMENT=$(base64 /tmp/result.txt)
EMAIL="/report/result.txt"

sed -e "s/\${result}/$1/" \
    -e "s/\${attachment}/$ATTACHMENT/" \
    -e "s/\${filename}/$FILENAME/" temp-email > $EMAIL

My problem here is I got the following error when replacing the ${attachment}

sed: -e expression #2, char 92: unterminated `s' command

Thanks in advance.


Solution

  • When you run the command on a file long enough

    $ base64 /tmp/result.txt 
    

    it will produce an output like this:

    PEhpdD4KICAgPEhpdF9udW0+MTwvSGl0X251bT4KICAgPEhpdF9pZD5UUjpWNFUwTDVfOVJPU0k8
    L0hpdF9pZD4KICAgPEhpdF9kZWY+Z25sfFY0VTBMNXwgVW5jaGFyYWN0ZXJpemVkIHByb3RlaW4g
    W0hvbW8gc2FwaWVuXSBPWD0zOTMzMDUgR049Q0lDTEVfdjEwMDA4MTM2bWcgUEU9NCBTVj0xPC9I
    aXRfZGVmPgogICA8SGl0X2FjY2Vzc2lvbj5UUjpWNFUwTDVfOVJPU0k8L0hpdF9hY2Nlc3Npb24+
    CiAgIDxIaXRfbGVuPjM4ODwvSGl0X2xlbj4KPC9IaXQ+Cg==
    

    This output contains EOL characters that will break your command:

     -e "s/\${attachment}/PEhpdD4KICAgPEhpdF9udW0+MTwvSGl0X251bT4KICAgPEhpdF9pZD5UUjpWNFUwTDVfOVJPU0k8
    L0hpdF9pZD4KICAgPEhpdF9kZWY+Z25sfFY0VTBMNXwgVW5jaGFyYWN0ZXJpemVkIHByb3RlaW4g
    W0hvbW8gc2FwaWVuXSBPWD0zOTMzMDUgR049Q0lDTEVfdjEwMDA4MTM2bWcgUEU9NCBTVj0xPC9I
    aXRfZGVmPgogICA8SGl0X2FjY2Vzc2lvbj5UUjpWNFUwTDVfOVJPU0k8L0hpdF9hY2Nlc3Npb24+
    CiAgIDxIaXRfbGVuPjM4ODwvSGl0X2xlbj4KPC9IaXQ+Cg==/"
    

    and give the error:

    sed: -e expression #2, char 92: unterminated `s' command
    

    because the end of the s command is not on the same line.

    How to solve it:

    Just remove the \n before passing it to sed by using a command like tr -d'\n' this will have no impact on the base64 decoding

    example:

    $ cat /tmp/result.txt 
    <Hit>
       <Hit_num>1</Hit_num>
       <Hit_id>TR:V4U0L5_9ROSI</Hit_id>
       <Hit_def>gnl|V4U0L5| Uncharacterized protein [Homo sapien] OX=393305 GN=CICLE_v10008136mg PE=4 SV=1</Hit_def>
       <Hit_accession>TR:V4U0L5_9ROSI</Hit_accession>
       <Hit_len>388</Hit_len>
    </Hit>
    

    use

    base64 /tmp/result.txt  | tr -d '\n'
    

    if you decode it again:

    $ base64 /tmp/result.txt | tr -d '\n' | base64 --decode
    <Hit>
       <Hit_num>1</Hit_num>
       <Hit_id>TR:V4U0L5_9ROSI</Hit_id>
       <Hit_def>gnl|V4U0L5| Uncharacterized protein [Homo sapien] OX=393305 GN=CICLE_v10008136mg PE=4 SV=1</Hit_def>
       <Hit_accession>TR:V4U0L5_9ROSI</Hit_accession>
       <Hit_len>388</Hit_len>
    </Hit>
    

    TEST:

    $ sed "s/\${attachment}/$(base64 /tmpt/result.txt| tr -d '\n')/" email_template 
    From:Sender <xxxx@xxxx.com>
    To:Recipient <xxxx@xxxx.com>
    Subject: Result
    MIME-Version: 1.0
    Content-Type: multipart/mixed; boundary="MixedBoundaryString"
    
    --MixedBoundaryString
    Content-Type: multipart/alternative; boundary="AlternativeBoundaryString"
    
    --AlternativeBoundaryString
    Content-Type: text/plain; charset=UTF-8
    Content-Transfer-Encoding: quoted-printable
    
    Result
    
    ${detail}
    
    --AlternativeBoundaryString
    Content-Type: text/html; charset=UTF-8
    Content-Transfer-Encoding: quoted-printable
    
    <html>
      <head>
    </head>
      <body>
        <h1>Result</h1>
          <p>${detail}</p>
      </body>
    </html>
    --AlternativeBoundaryString--
    --MixedBoundaryString
    Content-Type: text/plain
    MIME-Version: 1.0
    Content-Transfer-Encoding: base64
    Content-Disposition: attachment; filename="${filename}"
    
    PEhpdD4KICAgPEhpdF9udW0+MTwvSGl0X251bT4KICAgPEhpdF9pZD5UUjpWNFUwTDVfOVJPU0k8L0hpdF9pZD4KICAgPEhpdF9kZWY+Z25sfFY0VTBMNXwgVW5jaGFyYWN0ZXJpemVkIHByb3RlaW4gW0hvbW8gc2FwaWVuXSBPWD0zOTMzMDUgR049Q0lDTEVfdjEwMDA4MTM2bWcgUEU9NCBTVj0xPC9IaXRfZGVmPgogICA8SGl0X2FjY2Vzc2lvbj5UUjpWNFUwTDVfOVJPU0k8L0hpdF9hY2Nlc3Npb24+CiAgIDxIaXRfbGVuPjM4ODwvSGl0X2xlbj4KPC9IaXQ+Cg==
    
    --MixedBoundaryString--