How to Send Property Viewing Reminders from a Schedule with Send Email
Build a Spojit workflow that runs every morning, pulls tomorrow's confirmed inspections from your bookings database, and emails each prospect a personalized viewing reminder with the property address and agent name.
What This Integration Does
Real estate teams lose prospects to no-shows. A reminder the day before an inspection, addressed to the right person and naming the exact property and showing time, keeps your viewing calendar full and your agents prepared. This Spojit workflow removes the manual chase: it wakes up on a Schedule, reads tomorrow's confirmed inspections straight from your bookings database with the mysql connector, works out the local viewing window with the date connector, and sends one tailored email per attendee. No agent has to remember to send anything.
The workflow runs unattended on a 5-field cron schedule in a timezone you choose. Each run queries the bookings table for inspections scheduled on tomorrow's date, loops over every returned booking, skips any slot whose status is cancelled, and sends a reminder through Spojit's built-in Send Email node. It writes nothing back to your database, so it is safe to re-run: if the morning run fails you can trigger it again by hand without corrupting any records, though a prospect may receive a duplicate reminder if you re-run after some mail has already gone out. Each run's output is simply the set of emails dispatched, visible in the execution history.
Prerequisites
- A mysql connection to your bookings database, added under Connections -> Add connection, with read access to the table that holds inspections (this tutorial assumes a table named
bookings). - Columns available on that table for at least: a booking id, the prospect's email and name, the inspection date/time, the property address, the assigned agent name, and a status field (for example
confirmed/cancelled). - The IANA timezone your office books viewings in, for example
Australia/Sydney. - Your prospects' and agents' email domains added to the org allowlist under Settings -> General -> Email recipients, since the Send Email node only sends to allowlisted recipients.
- Enough monthly email allowance for the volume of reminders you expect, as each Send Email send counts toward it.
Step 1: Start with a Schedule trigger
Create a new workflow and set the Trigger node type to Schedule. Add a cron expression that fires once each morning and pick the IANA timezone your bookings use. For an 8:00 AM weekday run in Sydney, use:
Cron: 0 8 * * 1-5
Timezone: Australia/Sydney
A single Schedule trigger can hold multiple schedules, so you could add a second weekend cron if your agency runs Saturday inspections. The trigger's output is { scheduledAt }, the moment the run started, which the next step uses to anchor "tomorrow".
Step 2: Compute tomorrow's local date with the date connector
Add a Connector node on the date connector in Direct mode and pick the add tool to move one day forward from the run time. Feed it the trigger's {{ trigger.scheduledAt }} and add one day, anchored to your booking timezone so a late-evening run still resolves to the correct calendar day.
{
"date": "{{ trigger.scheduledAt }}",
"unit": "days",
"amount": 1,
"timezone": "Australia/Sydney"
}
Then add a second date Direct mode node using the format tool to render that result as a plain YYYY-MM-DD string your SQL query can match against. Map its input to the previous step's output and set the format pattern to YYYY-MM-DD. Capture this as a variable, for example {{ tomorrow.formatted }}. If you prefer, you can compute the viewing window's start and end of day here with the date connector's start-of and end-of tools instead, then pass two timestamps to the query in Step 3.
Step 3: Query tomorrow's confirmed inspections with mysql execute-query
Add a Connector node on the mysql connector in Direct mode and select the execute-query tool. Use a parameterized query with a ? placeholder and pass the formatted date through params so the value is bound safely rather than concatenated into the SQL string.
query: SELECT id, prospect_email, prospect_name, property_address,
agent_name, viewing_time, status
FROM bookings
WHERE DATE(viewing_time) = ?
ORDER BY viewing_time ASC
params: ["{{ tomorrow.formatted }}"]
The execute-query tool returns the matching rows. Capture the result as a variable such as {{ inspections }} so the loop in the next step can iterate over the row list. Keep the column list explicit (not SELECT *) so downstream templates reference stable field names.
Step 4: Loop over each attendee
Add a Loop node in ForEach mode and point it at the row array returned by the query, for example {{ inspections.rows }} (match this to the field your mysql result exposes for the row list). Each iteration exposes the current booking as a loop item, for instance {{ booking }}, giving the inner nodes access to {{ booking.prospect_email }}, {{ booking.property_address }}, {{ booking.agent_name }}, and the rest. All of the remaining steps live inside this loop body so they run once per inspection.
Step 5: Skip cancelled slots with a Condition node
Inside the loop, add a Condition node that only lets confirmed bookings continue to the email step. Even though the query filters on the inspection date, a slot may have been cancelled after booking, so guard against it here. Configure the condition to check that the booking's status equals confirmed:
{{ booking.status }} equals confirmed
Connect the Condition's true output to the Send Email node in Step 6. Leave the false output unconnected so cancelled slots simply fall through without sending. If you would rather filter cancelled rows out before the loop, add AND status = 'confirmed' to the query in Step 3; the Condition node is the safer choice when status can change between booking and the morning run.
Step 6: Send the templated reminder with a Send Email node
On the Condition's true branch, add a Send Email node. It sends from Spojit's built-in mail service, so no connection is required. Template every field from the current loop item:
Recipients: {{ booking.prospect_email }}
Subject: Reminder: your viewing of {{ booking.property_address }} tomorrow
Body: Hi {{ booking.prospect_name }},
This is a reminder that your inspection of
{{ booking.property_address }} is booked for
{{ booking.viewing_time }}.
Your agent {{ booking.agent_name }} will meet you there.
Reply to this email if you need to reschedule.
Set Reply-To to a monitored agency inbox so prospects can reply to reschedule. Set If sending fails to Continue anyway so one bad address does not abort the whole batch and stop later prospects from being reminded. Remember that only upstream variables resolve in the template, and external recipient domains must be on the allowlist under Settings -> General -> Email recipients. To send from your own agency domain instead of the built-in service, swap this node for a Connector node on the resend or smtp connector using its send-email tool.
Tips
- Anchor every date operation to the same IANA timezone as the schedule. Mixing UTC and local time is the most common reason a run picks up the wrong calendar day near midnight.
- If your date result and SQL column store time differently, you can also use the json connector's
gettool to pluck a single field out of a step's output before passing it on, keeping templates tidy. - Order the query by
viewing_timeso reminders go out in viewing order, which makes the execution history easy to scan when you spot-check a morning run. - Ask Miraxa, the intelligent layer across your automation, to scaffold this for you: "Build a workflow with a Schedule trigger that queries tomorrow's confirmed bookings with mysql execute-query, loops the rows, and sends each prospect a Send Email reminder." Then fine-tune the query and templates in the properties panel.
Common Pitfalls
- Building the date into the SQL string by hand instead of using a
?placeholder withparams. Always parameterize, both for safety and so the bound value matches your column type exactly. - Forgetting the allowlist. The Send Email node silently refuses recipients whose domain is not under Settings -> General -> Email recipients, so add prospect domains before going live.
- Pointing the Loop at the wrong field. The
execute-queryresult wraps the rows in a property; map the loop to that row list, not the whole result object, or the loop will run zero times. - Leaving If sending fails on Fail the workflow. One invalid prospect email would then halt the run and skip everyone booked later that day.
Testing
Before enabling the schedule, validate on a tiny scope. Insert one or two test bookings dated for tomorrow with your own email as the prospect, one confirmed and one cancelled. Use the Run button to trigger the workflow manually and watch the execution history: confirm the query returns your test rows, the Loop iterates the right number of times, the Condition skips the cancelled slot, and you receive exactly one reminder with the property address and agent name filled in. Once the small batch behaves, turn the Schedule trigger on and check the first live morning run.