Performing text / time manipulation in the action of an automation

I’m trying to parse the content of an incoming email to extract a start and end date for use in creating a Google calendar entry.

As I’ve not done anything like this before, I’ve tried doing it in small steps and now think I have all the small steps working but don’t know how to bring them together in the action of an automation, First off, I’ve got an automation that’s triggered by the incoming email and extracts the strings representing the dates. This works successfully:

alias: New email notification
description: ""
triggers:
  - trigger: event
    event_type: imap_content
conditions: []
actions:
  - action: persistent_notification.create
    metadata: {}
    data:
      message: >-
        {{ trigger.event.data["text"] | regex_findall_index("[0-9]{1,2}
        [a-zA-Z]{3} [0-9]{4} - ([0-9]{1,2} [a-zA-Z]{3} [0-9]{4})") }}
      title: Email received
mode: single

I’ve then got the following working in Settings → Developer tools → Templates to trial how to get these strings turned into datetimes

{% set string = '16 Feb 2026 - 23 Feb 2026' %}

{% set booking_dates = {
  "start": string | regex_findall_index("([0-9]{1,2} [a-zA-Z]{3} [0-9]{4}) - [0-9]{1,2} [a-zA-Z]{3} [0-9]{4}"),
  "end": string | regex_findall_index("[0-9]{1,2} [a-zA-Z]{3} [0-9]{4} - ([0-9]{1,2} [a-zA-Z]{3} [0-9]{4})")
} %}
{%
set booking_times = {
  "start": strptime (booking_dates.start, '%d %b %Y') + timedelta(hours = 16),
  "end": strptime (booking_dates.end, '%d %b %Y') + timedelta(hours = 10)
} %}

The time range is {{ booking_times.start }} to {{ booking_times.end }}.

Finally, I know I can create a Google calendar entry with the following action:

  - action: calendar.create_event
    metadata: {}
    data:
      start_date_time: "2026-02-17 11:00:00"
      end_date_time: "2026-02-18 16:00:00"
    target:

I just don’t know how to combine this all into a single action i.e. the logic to extract and translate the date strings plus creating the Google calendar event. Can someone point me in the right direction?

Thanks in anticipation

You just need to set your Jinja variables up as Script/YAML variables. Also, if the first regex “works successfully” to extract the desired string from the text, there’s no reason to repeat variations of it multiple times. Just extract the date range string and process it with more efficient string methods.

alias: New email notification
description: ""
triggers:
  - trigger: event
    event_type: imap_content
conditions: []
actions:
  - variables:
      dates_string: |
        {{ trigger.event.data["text"] 
        | regex_findall_index("[0-9]{1,2} [a-zA-Z]{3} [0-9]{4} - [0-9]{1,2} [a-zA-Z]{3} [0-9]{4}") }}
      booking_dates: 
        start: "{{ dates_string.split(' - ')[0] }}" 
        end: "{{ dates_string.split(' - ')[1] }}"
  - action: calendar.create_event
    metadata: {}
    data:
      start_date_time: "{{ strptime(booking_dates.start ~ ' 16', '%d %b %Y %H')|as_local }}"
      end_date_time: "{{ strptime(booking_dates.end ~ ' 10', '%d %b %Y %H')|as_local }}"
    target:
      entity_id: calendar.EXAMPLE
mode: single

You haven’t shared how the IMAP is set up, but for something like this you need to have some filtering so you don’t end up with a bunch of false calendar events. If you did that during the setup of the IMAP integration, great. Otherwise, make sure to include it in the trigger and/or conditions blocks.

Thank you, I think your variables insight pushed me over the finishing line!

I knew I didn’t need to repeat the regex, I was just doing separate proof of concepts as best I could to satisfy myself the different elements worked before I joined them up and tidied them.

Yes, I’ve added some extra filtering now the core functionality is working. It’s also on a separate IMAP mailbox which only has very specific messages forwarded to it.

Thanks again!