A Home Assistant custom integration that polls an IMAP mailbox for utility-bill emails, parses them with provider-specific extractors, and exposes the results as a sensor with detailed attributes.
- IMAP polling over SSL with configurable server, port, folder, and scan interval
- Pluggable per-provider parsers — current bundled parsers:
- Duke Energy
- PSNC Energy (Piedmont Natural Gas)
- City of Raleigh Water
- Truist Mortgage
- Single sensor per account whose state is the count of bills found in the configured lookback window
- Attributes expose individual bills, totals/summary, and last-update timestamp
- Fully UI-configured via Home Assistant config flow
- Open HACS in Home Assistant.
- Search for Utilities Email Tracker under Integrations and install.
- Restart Home Assistant.
- In HACS, open the menu and choose Custom repositories.
- Add
https://github.com/ljmerza/utilities_email_trackerwith category Integration. - Install Utilities Email Tracker from the integrations list and restart Home Assistant.
Copy custom_components/utilities_email_tracker/ into your Home Assistant
config/custom_components/ directory and restart.
After installation, add the integration via Settings → Devices & Services → Add Integration → Utilities Email Tracker.
| Field | Default | Notes |
|---|---|---|
| — | Mailbox address used for IMAP login. | |
| Password | — | App password recommended (e.g. Gmail app password). |
| IMAP server | imap.gmail.com |
Hostname of the IMAP server. |
| IMAP port | 993 |
TLS/SSL port. |
| Use SSL | true |
Disable only for non-SSL servers. |
| Folder | INBOX |
Mailbox/folder to scan. |
| Days old | 30 |
Lookback window for messages. |
| Scan interval | 30 minutes |
How often the coordinator polls. |
| Max messages | 100 |
Upper bound per poll to avoid expensive scans. |
Gmail tip: create an app password rather than using your account password, and confirm IMAP is enabled in Gmail settings.
The integration creates one sensor per configured account:
- State: number of bills detected in the lookback window
- Attributes:
bills— list of parsed bill objects (provider, amount, due date, account number, billing date, source email metadata)summary— aggregate totals and per-provider rollupscount— same as the statelast_update— ISO timestamp of the last successful poll
Parsers live in custom_components/utilities_email_tracker/parsers/. Each
parser is a pure function that takes a single email dict and returns either:
- a
dictdescribing one bill, - a
list[dict]of bills, or Noneif the email isn't relevant.
To add a parser:
- Create
parsers/<provider>.pyexporting aparse_<provider>(email)function. - Register it in
parsers/__init__.pyby appending a(name, callable)tuple to thePARSERSlist. - Restart Home Assistant.
Parsers should match on sender + subject before doing expensive body parsing,
and should fail closed (return None) on anything unexpected — extract_bills
already swallows parser exceptions.
- No bills appear: raise
Days oldand confirm the matching emails are in the configuredFolder. - Auth errors: verify IMAP is enabled and you're using an app password where required (Gmail, Outlook with 2FA, etc.).
- Debug logs: add the following to
configuration.yamland restart:logger: default: warning logs: custom_components.utilities_email_tracker: debug
Issues and pull requests welcome at https://github.com/ljmerza/utilities_email_tracker. New parsers and bug reports for existing ones are particularly appreciated — include a redacted sample of the email subject/body so the regex can be exercised.