> For the complete documentation index, see [llms.txt](https://docs.realmjoin.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.realmjoin.com/automation/runbooks/runbook-references/org/devices/notify-users-about-low-diskspace_scheduled.md).

# Notify Users About Low Diskspace Scheduled

Email users whose devices are running out of disk space

{% hint style="info" %}
This is a scheduled runbook. It is designed to run on a recurring schedule rather than being triggered for a single object. See [Scheduling](/automation/runbooks/scheduling.md) for details on how to configure runbook schedules.
{% endhint %}

### Description

Finds Windows and macOS devices in Intune whose free disk space is below a limit, either a fixed number of gigabytes or a percentage of the disk. Each primary user gets one email listing their affected devices with practical steps to free up space. Devices are rated Warning or Critical. The run can be limited to critical devices, to devices with a fresh inventory, to a device group and to certain users. A simulation mode only lists who would be notified, and an override recipient redirects all emails to a test mailbox.

### Common use cases

* Recurring reminders to users whose devices are about to run out of disk space, before updates and app installations start to fail
* Two-stage campaigns: report all devices below the threshold to administrators with **Report Devices Low Diskspace**, and notify only the users with critical devices via `NotifyOnSeverity`
* Staged rollouts per department or pilot group via the user and device group scope options
* Excluding service or shared accounts via the exclude group

### Data freshness and limitations

The free and total disk space values are read from the Intune hardware inventory of each managed device. This inventory is refreshed with the regular device check-in, so the runbook sees the state of the last successful inventory rather than the current state of the device. To avoid notifying users based on outdated numbers, devices whose last Intune sync is older than `MaxInventoryAgeDays` (default 14 days) are skipped and counted separately. Devices without a last sync date are treated as outdated as well. Set the parameter to `0` to disable this check.

The companion **Report Devices Low Diskspace** runbook deliberately does not apply this filter, so it lists devices with a stale inventory as well and can show more devices than are notified here. Both runbooks apply the same threshold and the same Critical/Warning rating, so a device is rated identically in both; the difference in the device count is exactly the devices skipped for an outdated inventory, which this runbook reports as a separate number in its output.

Devices that report a total disk size of zero bytes have no usable storage inventory, for example devices that have not completed an inventory yet. Such devices are excluded from the evaluation instead of being treated as "0 GB free", and their number is shown in the console output.

Only Windows and macOS devices are evaluated. The storage inventory of mobile devices is less reliable, the default threshold in gigabytes is dimensioned for desktop disks, and the cleanup guidance in the email is specific to desktop operating systems.

This runbook is the user-facing counterpart of **Report Devices Low Diskspace**. Both use the same threshold settings and the same Critical/Warning rating. Use the report for the administrative overview, including devices without a primary user, and this runbook to ask the affected users to free up space themselves.

### Threshold and severity

`ThresholdType` selects whether a device is considered based on a fixed amount of free space (`FreeSpaceThresholdGB`) or based on the share of free space relative to its disk size (`FreeSpacePercentThreshold`). Only the field belonging to the selected type is shown in the portal.

Every device below the threshold is rated: devices below half of the configured threshold are marked as **Critical**, all other devices below the threshold as **Warning**. The rating is shown per device in the email, and with the built-in English and German templates the subject line and introduction switch to an urgent wording as soon as one of the user's devices is Critical. The `Custom` template has a single subject and a single introduction, both taken verbatim from the runbook customization, so a Critical and a Warning notification read identically there - phrase the custom text so it works for both.

`NotifyOnSeverity` controls which devices trigger a notification. By default every device below the threshold does (*Warning and Critical*). With *Critical only*, users are contacted only when a device is below half of the threshold. This allows a two-stage approach: report all devices below the threshold to administrators via the report runbook, and notify only the users whose devices are critical.

### Notification behaviour

The runbook sends **one email per primary user** that lists all affected devices of that user with operating system, model, free and total disk space, rating and the date of the last inventory. The email contains practical cleanup steps for the platforms of the listed devices: the Windows section is included for Windows devices, the macOS section for macOS devices, and both when the user has affected devices of both kinds.

Recipients are resolved via Microsoft Graph: the primary user of a device is looked up by the Entra object id that Intune reports in `userId`, so guest accounts and users whose current UPN differs from the address recorded at enrollment resolve correctly; devices without a `userId` fall back to a lookup by user principal name. The email is then sent to the user's `mail` attribute, with the user principal name as fallback when no mail attribute is set. Disabled accounts and users that cannot be resolved are skipped and listed in the console output. Devices without a primary user cannot be notified; they are listed in the console output for central follow-up (the report runbook covers them as well).

`SimulationMode` lists the affected users, their devices and the intended recipients in the console output without sending any email. Use it to validate thresholds and scope filters before the first productive run.

`OverrideEmailRecipient` redirects **ALL** notifications to the given address (comma-separated for multiple recipients) instead of the end users. A warning is logged on every run while the override is active, and each redirected email states the affected user in the subject and body. Use this for testing the email content or for routing everything to a shared mailbox.

Keep in mind that the override mailbox then receives one email per affected user, all sent within a few seconds and with urgent subject lines. Mail filters may classify such a burst of similar emails as bulk or spam and move it to the junk folder or the quarantine, in particular when the override mailbox belongs to another tenant. The runbook only sees that Microsoft Graph accepted each email and reports it as sent; what the receiving side does afterwards is not visible in the job output. If the emails do not arrive, check the junk folder and the quarantine of the override mailbox and run a message trace for the sender address. A mailbox in the same tenant is the more reliable test target.

### Scoping options

* **User scope:** With `UseUserScope` enabled, `IncludeUserGroup` limits the notifications to users who are members of that group, and `ExcludeUserGroup` suppresses notifications for members of that group. Both use the transitive membership, so nested groups are resolved, and both are read once at the start of the run.
* **Device scope:** `IncludeDeviceGroup` limits the evaluation to devices that are (transitive) members of the given Entra device group. Devices are matched via their Entra device ID.

When a user scope and a device scope are configured, a device has to match both. A failing group lookup stops the runbook with an error instead of silently notifying every user.

### Setup regarding email sending

The notification emails are sent to the affected users; the sender address is taken from the `RJReport.EmailSender` tenant setting and is required.

This runbook sends emails using the Microsoft Graph API. To send emails via Graph API, you need to configure an existing email address in the runbook customization.

See the [RealmJoin Report Settings documentation](https://docs.realmjoin.com/automation/runbooks/runbook-report-settings) for details on all available settings.

#### Email branding

The notification email honors the optional `RJReport.Branding.*` tenant settings:

* **Header and footer image** – public HTTPS URLs, PNG/JPEG/GIF, max. 200 KB each
* **Footer link** – target of the footer image
* **Accent and text color** – 6-digit hex values, e.g. `#0052cc`

When these settings are not configured, the default RealmJoin graphics and colors are used. An image that cannot be downloaded or validated, or an invalid color value, never prevents the email – the corresponding default is used instead.

Setup instructions and image requirements: [Email branding](https://docs.realmjoin.com/automation/runbooks/runbook-report-settings#email-branding-optional).

#### Service Desk contact information

The optional `RJReport.ServiceDesk_DisplayName`, `RJReport.ServiceDesk_EMail`, `RJReport.ServiceDesk_Phone` and `RJReport.ServiceDesk_PortalUrl` tenant settings add a contact block to the end of every email. `ServiceDeskTicketUrl` can additionally link to a ticket.

### Mail Template Language Selection

This runbook supports three email template options:

1. **EN (English - Default)**: Uses the built-in English template
2. **DE (German)**: Uses the built-in German template
3. **Custom**: Uses a custom template from Runbook Customizations

#### Using Custom Mail Templates

To use a custom mail template (e.g., in Dutch, Spanish, or any other language), you need to configure the template text in the Runbook Customizations. If any custom template parameter is missing, the runbook will automatically fall back to the English template.

The custom template consists of a subject, a text before the device list and a text after the device list. The built-in cleanup steps, the "Why is this important" section and the "Questions" section are **not** rendered with the custom template, so the text after the device list should contain your own cleanup guidance.

**Example: Custom Template**

```json
{
    "Runbooks": {
        "rjgit-org_devices_notify-users-about-low-diskspace_scheduled": {
            "Parameters": {
                "CustomMailTemplateSubject": {
                    "Default": "This is a custom subject - Action Required: Low Disk Space"
                },
                "CustomMailTemplateBeforeDeviceDetails": {
                    "Default": "**This is above the Device Details.** \n\nDear user, the following devices are running out of disk space:"
                },
                "CustomMailTemplateAfterDeviceDetails": {
                    "Default": "**This is below the Device Details.** \n\n## What you can do now\n\n1. Empty the Recycle Bin\n2. ..."
                }
            }
        }
    }
}
```

**Important Notes:**

* Use `\n` for line breaks in the JSON configuration
* Markdown formatting (##, ###, \*\*, -) is supported in the template text
* All three custom template parameters (Subject, BeforeDeviceDetails, AfterDeviceDetails) should be configured
* If any parameter is missing, the runbook automatically falls back to the English (EN) template
* When using the custom template, select "Custom - Use Template from Runbook Customizations" in the Mail Template dropdown
* The device list labels are rendered in English for the custom template

### Location

Organization → Devices → Notify Users About Low Diskspace (Scheduled)

**Full Runbook name**

rjgit-org\_devices\_notify-users-about-low-diskspace\_scheduled

### Details

| Property         | Value                                                                                    |
| ---------------- | ---------------------------------------------------------------------------------------- |
| Version          | 1.0.0                                                                                    |
| Required modules | <p>RealmJoin.RunbookHelper (>= 0.8.10)<br>Microsoft.Graph.Authentication (>= 2.41.2)</p> |
| Schedulable      | yes                                                                                      |

### Permissions

#### Application permissions

* **Type**: Microsoft Graph
  * DeviceManagementManagedDevices.Read.All
    * *Reads Intune managed devices including freeStorageSpaceInBytes, totalStorageSpaceInBytes, lastSyncDateTime and the primary user (userId and userPrincipalName) to find devices below the low disk space threshold*
  * User.Read.All
    * *Resolves each affected primary user (mail address, display name and accountEnabled) before sending the notification*
  * Mail.Send
    * *Sends the low disk space notification email to each primary user or to the override recipient*
  * Organization.Read.All *(optional — feature: Tenant name in email footer)*
    * *Reads /organization for the tenant name shown in the email footer; without it the runbook falls back to 'Unknown Tenant'*
  * Directory.Read.All *(optional — feature: Group scope filtering)*
    * *Reads the transitive user members of the include/exclude user groups and the transitive device members (Entra device ID) of the optional device group*

### Parameters

#### ThresholdType

By a fixed amount of free gigabytes or by the percentage of free space on the disk.

| Property            | Value                                    |
| ------------------- | ---------------------------------------- |
| Required            | false                                    |
| Default Value       | Free space in GB                         |
| Type                | String                                   |
| Portal display name | How should low disk space be determined? |

**Portal options**

| Portal option                                      | Value                 |
| -------------------------------------------------- | --------------------- |
| Free space below a fixed size (GB)                 | Free space in GB      |
| Free space below a percentage of the disk size (%) | Free space in percent |

#### FreeSpaceThresholdGB

Devices with less free space than this many gigabytes are affected.

| Property            | Value                 |
| ------------------- | --------------------- |
| Required            | false                 |
| Default Value       | 20                    |
| Type                | Int32                 |
| Portal display name | Free space limit (GB) |

#### FreeSpacePercentThreshold

Devices with less free space than this percentage of the disk are affected.

| Property            | Value                                  |
| ------------------- | -------------------------------------- |
| Required            | false                                  |
| Default Value       | 10                                     |
| Type                | Int32                                  |
| Portal display name | Free space limit (%)                   |
| Hidden in portal    | yes (preset via runbook customization) |

#### NotifyOnSeverity

Every device below the limit (Warning and Critical), or only devices below half of it (Critical only).

| Property            | Value                                        |
| ------------------- | -------------------------------------------- |
| Required            | false                                        |
| Default Value       | Warning and Critical                         |
| Type                | String                                       |
| Portal display name | Which devices should trigger a notification? |

**Portal options**

| Portal option                                           | Value                |
| ------------------------------------------------------- | -------------------- |
| Warning and Critical - every device below the threshold | Warning and Critical |
| Critical only - devices below half of the threshold     | Critical only        |

#### Windows

Includes Windows devices.

| Property            | Value                    |
| ------------------- | ------------------------ |
| Required            | false                    |
| Default Value       | True                     |
| Type                | Boolean                  |
| Portal display name | Include Windows devices? |

#### MacOS

Includes macOS devices.

| Property            | Value                  |
| ------------------- | ---------------------- |
| Required            | false                  |
| Default Value       | True                   |
| Type                | Boolean                |
| Portal display name | Include macOS devices? |

#### MaxInventoryAgeDays

Devices whose last Intune sync is older than this many days are skipped, as their disk data is stale. 0 disables the check.

| Property            | Value                              |
| ------------------- | ---------------------------------- |
| Required            | false                              |
| Default Value       | 14                                 |
| Type                | Int32                              |
| Portal display name | Skip devices not synced for (days) |

#### EmailFrom

Sender address of the notification email. Taken from the tenant setting RJReport.EmailSender.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### BrandingHeaderImageUrl

Header image of the report email (HTTPS URL, PNG/JPEG/GIF, max 200 KB). Taken from the tenant setting RJReport.Branding.HeaderImageUrl; the default RealmJoin header is used when empty.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### BrandingFooterImageUrl

Footer image of the report email (HTTPS URL, PNG/JPEG/GIF, max 200 KB). Taken from the tenant setting RJReport.Branding.FooterImageUrl; the default RealmJoin footer is used when empty.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### BrandingFooterLink

Link behind the footer image of the report email. Taken from the tenant setting RJReport.Branding.FooterLink; realmjoin.com is used when empty.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### BrandingAccentColor

Accent color of the report email as a 6-digit hex value. Taken from the tenant setting RJReport.Branding.AccentColor; the RealmJoin default is used when empty or invalid.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### BrandingTextColor

Text color of the report email as a 6-digit hex value. Taken from the tenant setting RJReport.Branding.TextColor; the RealmJoin default is used when empty or invalid.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### ServiceDeskDisplayName

Service desk name shown in the email. Taken from the tenant setting RJReport.ServiceDesk\_DisplayName.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### ServiceDeskEmail

Service desk email address shown in the email. Taken from the tenant setting RJReport.ServiceDesk\_EMail.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### ServiceDeskPhone

Service desk phone number shown in the email. Taken from the tenant setting RJReport.ServiceDesk\_Phone.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### ServiceDeskPortalUrl

Link to the service desk portal shown in the email. Taken from the tenant setting RJReport.ServiceDesk\_PortalUrl.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### ServiceDeskTicketUrl

Link to the service desk ticket shown in the email. Taken from the tenant setting RJReport.ServiceDesk\_TicketUrl; empty means no link.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    |                                        |
| Type             | String                                 |
| Hidden in portal | yes (preset via runbook customization) |

#### UseUserScope

Whether users are filtered by group membership. Set by the "Filter users by group?" choice.

| Property         | Value                                  |
| ---------------- | -------------------------------------- |
| Required         | false                                  |
| Default Value    | False                                  |
| Type             | Boolean                                |
| Hidden in portal | yes (preset via runbook customization) |

#### IncludeUserGroup

Only users in this group, nested groups included, are notified.

| Property            | Value                                  |
| ------------------- | -------------------------------------- |
| Required            | false                                  |
| Default Value       |                                        |
| Type                | String                                 |
| Portal display name | Include users from group               |
| Hidden in portal    | yes (preset via runbook customization) |

#### ExcludeUserGroup

Users in this group, nested groups included, are not notified.

| Property            | Value                                  |
| ------------------- | -------------------------------------- |
| Required            | false                                  |
| Default Value       |                                        |
| Type                | String                                 |
| Portal display name | Exclude users from group               |
| Hidden in portal    | yes (preset via runbook customization) |

#### IncludeDeviceGroup

Only devices in this Entra ID group, nested groups included, are checked. Can be combined with the user filter.

| Property            | Value                     |
| ------------------- | ------------------------- |
| Required            | false                     |
| Default Value       |                           |
| Type                | String                    |
| Portal display name | Limit to devices in group |

#### OverrideEmailRecipient

Sends every email to these addresses instead of the users, for tests and pilots. The mailbox gets one email per affected user within seconds, which mail filters may treat as spam; prefer a mailbox in your own tenant.

| Property            | Value                  |
| ------------------- | ---------------------- |
| Required            | false                  |
| Default Value       |                        |
| Type                | String                 |
| Portal display name | Redirect all emails to |

#### SimulationMode

Simulation only lists the affected users and devices; nothing is sent.

| Property            | Value             |
| ------------------- | ----------------- |
| Required            | false             |
| Default Value       | False             |
| Type                | Boolean           |
| Portal display name | Notification mode |

**Portal options**

| Portal option                                       | Value |
| --------------------------------------------------- | ----- |
| Send notifications to users                         | false |
| Simulation - list affected users only, send nothing | true  |

#### MailTemplateLanguage

English, German, or the custom template from the runbook customization; English is used where the custom template is empty.

| Property            | Value                                  |
| ------------------- | -------------------------------------- |
| Required            | false                                  |
| Default Value       | EN                                     |
| Type                | String                                 |
| Portal display name | Mail template                          |
| Hidden in portal    | yes (preset via runbook customization) |

#### CustomMailTemplateSubject

Subject of the email when the custom template is used, for Warning and Critical alike.

| Property            | Value                                  |
| ------------------- | -------------------------------------- |
| Required            | false                                  |
| Default Value       |                                        |
| Type                | String                                 |
| Portal display name | Custom: email subject                  |
| Hidden in portal    | yes (preset via runbook customization) |

#### CustomMailTemplateBeforeDeviceDetails

Text above the device list when the custom template is used. Markdown is allowed.

| Property            | Value                                  |
| ------------------- | -------------------------------------- |
| Required            | false                                  |
| Default Value       |                                        |
| Type                | String                                 |
| Portal display name | Custom: text before device list        |
| Hidden in portal    | yes (preset via runbook customization) |

#### CustomMailTemplateAfterDeviceDetails

Text below the device list when the custom template is used; it replaces the built-in cleanup steps. Markdown is allowed.

| Property            | Value                                  |
| ------------------- | -------------------------------------- |
| Required            | false                                  |
| Default Value       |                                        |
| Type                | String                                 |
| Portal display name | Custom: text after device list         |
| Hidden in portal    | yes (preset via runbook customization) |

[Back to Runbook Reference overview](/automation/runbooks/runbook-references.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.realmjoin.com/automation/runbooks/runbook-references/org/devices/notify-users-about-low-diskspace_scheduled.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
