Guide for developers

Postgres query to a chart in an email

An n8n workflow that runs a SQL query on a schedule and emails the result as a chart. The Postgres node reads the rows S3, a Code node turns them into a ChartPNG URL, and the Send Email node puts that URL in an <img> tag. No file, no binary field, no attachment.

Sources read on 3 Nov 2026. Each fact about n8n or mail clients links to its source (S1, S2...), listed at the end with a short quote.

The short version

Why a URL in an img tag

Send Email attaches files from binary properties: you enter the name of the field that holds the fileS4. Two forum threads show people struggling with it: one user could not tell what to put in the attachment field nameS1; another saw an attachment listed as "unknown", with Outlook 365 named in a reply S2. When the same user asked for the image in the body of the email, the answer was an img tag with a remote sourceS2.

A ChartPNG /chart URL is that kind of source: it returns a PNG for a config in the URL. The workflow never handles the image, so there is no binary field to name, no file extension to set and no upload step. It only builds a string.

The workflow

Four nodes, and a note on the canvas.

  1. Every Monday at 8 (Schedule Trigger). For a daily report, set the interval to days instead of weeks.
  2. Example query (replace) (Postgres, operation Execute Query S3). A SELECT over a made-up orders table. Replace it.
  3. Build chart (Code). Reads the rows, builds the Chart.js config and the image URL, the sentence and the table.
  4. Send email (Send Email, format HTML S4). Puts them in the body.

Import it

  1. Download postgres-chart-to-email.json, or copy the import link https://chartpng.dev/templates/n8n/postgres-chart-to-email.json.
  2. In n8n, open the Workflow menu (the three dots) and choose Import from File or Import from URL. The n8n guide has the details.
  3. Open Example query (replace) and pick your Postgres credential. The file holds the name Postgres account as a placeholder, no secrets.
  4. Open Send email, pick your SMTP credential and set From, To and Subject.
  5. Run Execute workflow once and look at the email. Then publish the workflow (on n8n 1.x, switch it to Active).

The example query, and keeping it read-only

This query is an example over a made-up orders table with created_at and total. It returns the last eight full weeks, one row each. Replace it with your own and keep the three column names, or edit Build chart to match.

SELECT to_char(date_trunc('week', created_at), 'DD Mon') AS week,
       count(*) AS orders,
       round(sum(total)) AS revenue
FROM orders
WHERE created_at >= date_trunc('week', now()) - interval '8 weeks'
  AND created_at < date_trunc('week', now())
GROUP BY date_trunc('week', created_at)
ORDER BY date_trunc('week', created_at);

A report only reads. The template's query is one SELECT statement and the tests fail if it ever contains a write or a second statement. That checks the text in the template, not the database, so as a convention, give the credential a database user that has SELECT and nothing else. If you put values into the query, use query parameters: n8n sanitizes data in query parameters, which prevents SQL injection S3.

What goes in the email

The Code node outputs the chart, the image URL, the alt text, a one-line summary and the table rows. The Send Email node uses them in this HTML:

<p>Revenue by week, the last 8 full weeks.</p>
<img src="{{ $json.imageUrl }}" alt="{{ $json.alt }}" width="600" style="max-width:100%;height:auto">
<p>{{ $json.summary }}</p>
<table style="border-collapse:collapse;font-size:14px">
<tr><th style="padding:4px 12px;text-align:left">Week</th><th style="padding:4px 12px;text-align:right">Orders</th><th style="padding:4px 12px;text-align:right">Revenue</th></tr>
{{ $json.tableHtml }}
</table>

This is the chart for the sample rows. The footer says "Sample data"; yours says "Source: orders table" until you change it.

Bar chart of revenue by week, 8 weeks. Week of 03 Nov: 12,480 revenue from 281 orders. Up 23.5% on the week before.

The config behind it, which the Code node builds from your rows:

{
  "type": "bar",
  "data": {
    "labels": [
      "15 Sep",
      "22 Sep",
      "29 Sep",
      "06 Oct",
      "13 Oct",
      "20 Oct",
      "27 Oct",
      "03 Nov"
    ],
    "datasets": [
      {
        "label": "Revenue",
        "data": [
          9841,
          10420,
          9211,
          11030,
          11890,
          11640,
          10105,
          12480
        ]
      }
    ]
  },
  "options": {
    "plugins": {
      "title": {
        "display": true,
        "text": "Revenue by week"
      },
      "chartpng": {
        "source": "Sample data"
      }
    }
  }
}

The Postgres node can output NUMERIC and BIGINT columns as text S3, so the Code node converts every value with Number() and stops with a message naming the row if a value is empty (NULL) or not a number, instead of charting it as 0. Text from the database goes through an HTML escape before it reaches the email.

When the image does not show

Classic Outlook for Windows blocks automatic picture downloads by default, and the reader can unblock them S5. Nodemailer says many email clients block external images by default S6. So treat the picture as a bonus on top of the text:

Sizing, dark mode, Gmail's image proxy and the client differences are in Charts in emails, with sources, so they are not repeated here.

Troubleshooting

Checklist before you publish

More workflows: all guides and the n8n templates.

What we could not confirm

Sources

All pages read on 3 Nov 2026. Quotes are exact and short. Web pages change, so check the date.

  1. S1n8n community: How to Send a QuickChart Graph in Gmail?https://community.n8n.io/t/how-to-send-a-quickchart-graph-in-gmail/90437

    Quote: "You can attach this file to the Gmail node directly"

    Read 3 Nov 2026. Reply of 20 Mar 2025. The person who asked was sending a chart as a file and wrote: "I’m not sure what I’m supposed to put in the attachment field name". A forum thread, not n8n documentation.

  2. S2n8n community: When sending an email attachment, the file extension does not show and is displayed as "unknown"https://community.n8n.io/t/when-sending-an-email-attachment-the-file-extension-does-not-show-and-is-displayed-as-unknown/140829

    Quote: "you can use regular img with remote source"

    Read 3 Nov 2026. Reply of 2 Jul 2025, with an HTML example whose img tag has a remote src. The thread starts on 30 Jun 2025 with the "unknown" attachment; Outlook 365 is named in a reply of 2 Jul 2025, not in the first post, and the attachment problem is not solved in the thread. A forum thread, not n8n documentation.

  3. S3n8n docs: Postgres nodehttps://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.postgres/

    Quote: "Execute Query : Execute an SQL query"

    Read 3 Nov 2026. The same page says of Query Parameters: "n8n sanitizes data in query parameters, which prevents SQL injection." It also lists the option "Output Large-Format Numbers As" for "NUMERIC and BIGINT columns", as Numbers or Text.

  4. S4n8n docs: Send Email nodehttps://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.sendemail/

    Quote: "Enter the name of the binary properties that contain data to add as an attachment."

    Read 3 Nov 2026. The page also says Email Format HTML will "Send the email in HTML format." and that the node uses an SMTP credential.

  5. S5Microsoft Support: automatic picture downloads in classic Outlook for Windowshttps://support.microsoft.com/en-us/outlook/block-or-unblock-automatic-picture-downloads-in-classic-outlook-email-messages

    Quote: "Microsoft Outlook is configured by default to block automatic picture downloads from the Internet."

    Read 3 Nov 2026. It goes on: "You can, however, unblock pictures that you think are safe to download." The page covers classic Outlook for Windows only.

  6. S6Nodemailer: Embedded imageshttps://nodemailer.com/message/embedded-images

    Quote: "Many email clients block external images by default for privacy and security reasons."

    Read 3 Nov 2026. Nodemailer is the library behind SMTP sending in many Node apps; this is its own statement about clients.