Node-RED

Node-RED Email Alert from MQTT Data: Thresholds, Hysteresis and Silence Detection

Send email alerts when MQTT values cross a limit, without flooding your inbox. This tutorial builds a Node-RED flow with hysteresis, a cooldown, a silent-device watchdog and SMTP setup, and compares it with ConnectMQ's built-in threshold alert rules.

Node-RED email alert flow sending a notification when an MQTT temperature value crosses a threshold
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

A Node-RED email alert is one of the simplest ways to get notified when a sensor value published over MQTT goes out of range. In this tutorial you will build a flow that watches a temperature topic, sends an email when it crosses a limit, avoids sending dozens of duplicates, and also warns you when a device stops publishing altogether.

What We Are Building

The finished flow does four things:

  1. Subscribes to a sensor topic on an MQTT broker.
  2. Decides whether the value is in an alarm state, using a high limit and a lower reset limit (hysteresis), so a value hovering at the limit does not trigger repeated emails.
  3. Sends one email when the alarm starts and one when it clears, with a cooldown so a flapping sensor cannot flood your inbox.
  4. Sends a separate email if no message has arrived for ten minutes, because a dead sensor is often more dangerous than a high reading.

For the examples we use the free public MQTT broker at broker.connectmq.com with the topic prefix connectmq/demo/k7f3qa. Pick your own random string instead of k7f3qa, and remember that the public area is readable by anyone.

Installing the Email Node

Node-RED does not ship with an email node. Install it from Menu → Manage palette → Install by searching for node-red-node-email, or from the command line in your Node-RED user directory:

cd ~/.node-red
npm install node-red-node-email
# then restart Node-RED

The package adds an e-mail output node that sends via SMTP and an e-mail input node that reads a mailbox. We only need the output node. Its behaviour is simple: msg.payload becomes the body, msg.topic becomes the subject, and if the To field in the node is left empty, msg.to sets the recipient.

SMTP settings that actually work

Provider Server Port Secure connection Notes
Gmail / Google Workspace smtp.gmail.com 465 Enabled Requires 2-step verification and an app password
Microsoft 365 smtp.office365.com 587 Disabled (uses STARTTLS) SMTP AUTH must be allowed for the mailbox
Transactional service (SendGrid, Mailgun, SES) Provider host 465 or 587 Per provider Best deliverability for automated mail
Local relay (Postfix) localhost 25 Disabled Only if you already run a relay

With Gmail, do not use your normal password. Create an app password in your Google account security settings and paste that into the node. For anything beyond a hobby project, a transactional email service with a verified sending domain gives better deliverability, because automated alert mail from a personal mailbox is easily caught by spam filters.

Building the Node-RED Email Alert Flow

The flow is: mqtt in → function (alarm logic) → e-mail, plus a trigger node branch for silence detection. If you have not wired MQTT nodes before, the Node-RED MQTT tutorial covers the broker config node in detail.

Step 1: Subscribe to the sensor

Add an mqtt in node with:

  • Server: broker.connectmq.com, port 1883, a unique client ID such as nr-alerts-k7f3qa
  • Topic: connectmq/demo/k7f3qa/greenhouse/temperature
  • Output: auto-detect (parsed JSON object or string)

Step 2: The alarm logic

A plain switch node that checks payload > 30 sends an email for every reading above 30. If the sensor reports every ten seconds, that is 360 emails an hour. Instead, track state in the node context and only emit on transitions. Put this in a function node:

const HIGH = 30;          // raise alarm at or above this value
const RESET = 28;         // clear alarm at or below this value
const COOLDOWN_MS = 15 * 60 * 1000;  // minimum time between emails

let value = msg.payload;
if (typeof value === "object" && value !== null) value = value.value;
value = Number(value);
if (isNaN(value)) return null;

const inAlarm = context.get("inAlarm") || false;
const lastSent = context.get("lastSent") || 0;
const now = Date.now();

let event = null;
if (!inAlarm && value >= HIGH) event = "raised";
if (inAlarm && value <= RESET) event = "cleared";
if (!event) return null;

context.set("inAlarm", event === "raised");

// Always report a clear, but rate-limit new alarms
if (event === "raised" && now - lastSent < COOLDOWN_MS) {
    node.status({ fill: "yellow", shape: "ring", text: "alarm suppressed (cooldown)" });
    return null;
}
context.set("lastSent", now);

node.status({
    fill: event === "raised" ? "red" : "green",
    shape: "dot",
    text: event + " at " + value
});

msg.topic = event === "raised"
    ? `ALARM: greenhouse temperature ${value} C`
    : `Cleared: greenhouse temperature back to ${value} C`;

msg.payload =
    `Greenhouse temperature ${event}.\n\n` +
    `Current value: ${value} C\n` +
    `Alarm limit: ${HIGH} C, reset limit: ${RESET} C\n` +
    `Time: ${new Date(now).toISOString()}\n` +
    `Source topic: connectmq/demo/k7f3qa/greenhouse/temperature\n`;

return msg;

The gap between HIGH and RESET is the hysteresis band. A value bouncing between 29.8 and 30.2 triggers once and then stays in alarm until it really falls back to 28.

Step 3: Configure the e-mail node

Wire the function output to an e-mail node. Fill in the recipient, server, port, secure connection, user ID and password from the table above. Deploy, and the node status shows whether the SMTP login succeeded the first time a message passes through.

Step 4: Detect silent devices

Add a second wire from the mqtt in node to a trigger node configured as:

  • Send: nothing
  • Then: wait for 10 minutes, with extend delay if new message arrives checked
  • Then send: a string such as No data from greenhouse sensor for 10 minutes

Every incoming reading restarts the timer, so the trigger only fires when the sensor goes quiet. Feed its output into a change node that sets msg.topic to a subject line, then into the same e-mail node.

Testing Without Waiting for a Heatwave

Publish test values from a terminal:

# normal
mosquitto_pub -h broker.connectmq.com -p 1883 -i test-k7f3qa -t "connectmq/demo/k7f3qa/greenhouse/temperature" -m "24.5"
# raise alarm
mosquitto_pub -h broker.connectmq.com -p 1883 -i test-k7f3qa -t "connectmq/demo/k7f3qa/greenhouse/temperature" -m "31.2"
# still high, no new email
mosquitto_pub -h broker.connectmq.com -p 1883 -i test-k7f3qa -t "connectmq/demo/k7f3qa/greenhouse/temperature" -m "30.4"
# clear
mosquitto_pub -h broker.connectmq.com -p 1883 -i test-k7f3qa -t "connectmq/demo/k7f3qa/greenhouse/temperature" -m "27.0"

You should receive exactly two emails. While testing, temporarily lower COOLDOWN_MS and the trigger delay, and put a debug node in parallel with the e-mail node so you can see what would be sent without hitting the SMTP server every time.

Troubleshooting Email Delivery

Problem What to check
Node shows "Invalid login" Use an app password for Gmail; check that SMTP AUTH is enabled for Microsoft 365 mailboxes
Connection timeout Port 25 and sometimes 465/587 are blocked by some ISPs and cloud providers; try the other port or a transactional service
"Self signed certificate" error Wrong port and secure combination, for example secure enabled on 587
Emails land in spam Send from a domain with SPF and DKIM configured, avoid all-caps subjects
Email for every reading The function node is not keeping state; make sure you return null when there is no transition
No email after restart while value is high Context is in memory by default; that is expected, the next reading re-evaluates the state

If you need the alarm state to survive a Node-RED restart, enable a persistent context store in settings.js and use context.get("inAlarm", "file"). The Node-RED context guide explains the options.

Node-RED Email Alerts vs ConnectMQ Threshold Alert Rules

If your devices publish to a ConnectMQ broker, you already have a second option. Its portal includes threshold alert rules and an alerts log: you pick a topic, set a limit, and every crossing is recorded where you and your team can review it, without running any extra software.

The two approaches complement each other:

Need Portal alert rules Node-RED email flow
Simple threshold on a topic Yes, configured in the portal Yes
History of alerts in one place Alerts log in the portal You build it, for example with Node-RED and MySQL
Custom logic (hysteresis, combined conditions, schedules) Threshold rules only Anything you can write in JavaScript
Delivery to an inbox, chat or SMS Not the purpose of the alerts log Email node, plus Telegram or other notification nodes
No extra server to maintain Yes Needs a Node-RED instance

A common pattern is to configure threshold rules in the portal for visibility and auditing, and to run a small Node-RED flow next to it for the handful of conditions that must reach someone's phone at night. Because Node-RED is just another MQTT client, both read the same topics from the same broker. That is the general shape of integrations with a fully managed MQTT service: the broker moves messages reliably, and external tools subscribe and act on them.

Production Checklist

  1. Move from the public broker to your own credentials (YOUR_USERNAME, YOUR_PASSWORD, YOUR_CLIENT_ID) on port 8883 with TLS.
  2. Store SMTP passwords in the node credentials, never in a function node or a flow file you commit to git.
  3. Use QoS 1 on the subscription so a brief disconnect does not silently drop the reading that crosses the limit.
  4. Keep the silence watchdog; it catches dead batteries, Wi-Fi outages and crashed gateways.
  5. Send to a group address or distribution list rather than a single person.
  6. Test the full chain monthly by publishing a fake high value.

Get Started with ConnectMQ

Alerts are only as reliable as the broker delivering the readings. ConnectMQ gives you a hosted MQTT broker with TLS, MQTT 5 and portal-side threshold alerts, and your Node-RED flows connect to it like any other client. Create a free Serverless broker at app.connectmq.com, no credit card required, and you can move this flow from the public test broker to private credentials in a few minutes.

Frequently Asked Questions

Which Node-RED node sends email?

The e-mail output node from the node-red-node-email package. Install it from the palette manager, then set msg.payload for the body and msg.topic for the subject.

How do I stop Node-RED from sending an email for every reading?

Track the alarm state in context and only send on transitions, add a reset limit below the alarm limit for hysteresis, and enforce a cooldown between alarm emails as shown in the function node above.

Can ConnectMQ send the email instead of Node-RED?

The portal provides threshold alert rules and an alerts log. To deliver notifications to an inbox, run a client such as Node-RED that subscribes to the broker and sends the email.

Why does Gmail reject my Node-RED login?

Google blocks regular passwords for SMTP from apps. Enable 2-step verification, generate an app password and use it in the e-mail node with smtp.gmail.com on port 465 with a secure connection.

Related articles

Node-RED OPC UA Client to MQTT with ISA-95 Topics

Use node-red-contrib-opcua to subscribe to OPC UA variables on a PLC or simulation server, map node IDs to ISA-95 style MQTT topics, and publish values with quality and timestamps.

9 min read

Node-RED Chart History: Keep MQTT Chart Data Across Restarts

Dashboard charts forget everything when Node-RED restarts. This guide shows two reliable ways to keep Node-RED chart history for MQTT data: file-backed context storage and a small SQLite table, both replayed into Dashboard 2.0 on startup.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.