Search code examples
bashcommand-line-interfacesendgrid

Sending a complex html as the body of email from the command line via an SendGrid API


I need to send an HTML file as the body of an eamil to several customers. Our company will be using SendGrid for this, and I need to be able to send the email via API Curl Call.

The way that I'm doing it so far works for simple html or plain text:

curl -s --request POST \
--url https://api.sendgrid.com/v3/mail/send \
--header "Authorization: Bearer SECRET_API_KEY" \
--header 'Content-Type: application/json' \
--data '{"personalizations":[{"to":[{"email":"[email protected]"},{"email":"[email protected]"}]}],"from":{"email":"[email protected]"},"subject":"Testing sending emails via SendgridAPI","content":[{"type":"text\/html","value":"Test API Email From ME"}]}'

Now this works just fine. The problem is when I want to replace 'Test API Email From ME' with the contents of a rather large, complex HTML file. This has all the usual cli nightmares such as a mix of ' and " and new lines everywhere. I need to sanatize the HTML in order to accomplish three things:

  1. The final result needs to be a valid command line string

  2. The --data switch argument needs to remain a valid JSON enconded string

  3. The HTML should not break.

What I do is I create the actual string command and the execute it using a scripting language. So I can perform any operation that I want on the html before inserting it in the value field of the content field. So my question is: what are the string operations that I should perform on the html so that I can send the email using this methodology?


Solution

  • Using jq and bash

    I'll do it with static data, you may improve upon it

    • Define a JSON template for the API:
    IFS='' read -r -d '' json_template <<'EOF'
    {
      "personalizations": [
        {
          "to": [
            { "email": "[email protected]" },
            { "email": "[email protected]" }
          ]
        }
      ],
      "from": { "email": "[email protected]" },
      "subject": "Testing sending emails via SendgridAPI",
      "content": [
        {
          "type": "text/html",
          "value": "Test API Email From ME"
        }
      ]
    }
    EOF
    
    • Define the HTML content:
    IFS='' read -r -d '' html_email <<'EOF'
    <!doctype html>
    <html>
      <head>
        title>Simple Email</title>
      </head>
      <body>
        Test API Email From ME
      </body
    </html>
    EOF
    
    • Replace the email content in the JSON with the HTML
    json_data=$(
        jq -c -n \
            --arg html "$html_email" \
            --argjson template "$json_template" \
            '$template | .content[0].value = $html'
    )
    
    • Send the query
    curl -s --request POST \
        --url https://api.sendgrid.com/v3/mail/send \
        --header "Authorization: Bearer SECRET_API_KEY" \
        --header 'Content-Type: application/json' \
        --data "$json_data"