How to Customize the Proxmox VZDump Email Notification Format for Backup Summaries.

TonnarakNET

New Member
Mar 29, 2024
1
0
1
Hi,

I want the email notification to include only the VM table results, without attaching log data. The email should provide a summary of the backup results, such as:
  1. All backups succeeded.
  2. All backups succeeded except for specific VMIDs or VMNames.
  3. All backups failed.
Thank you.
 
https://bugzilla.proxmox.com/show_bug.cgi?id=6143

In the meanwhile you can edit the notification templates in /usr/share/proxmox-ve/templates/default, just be aware that your changes can be overridden by a package upgrade. Once the override mechanism as described in the bug report is implemented, this is not the case any more.
 
Hi.

I have some questions, Where to find the variable that we can use for backups, and which template to use? does it have a list of variable templates provided?

Thank you!
 
There are three template files, vzdump-body.html.hbs, vzdump-body.txt.hbs and vzdump-subject.txt.hbs. The subject template is used for the subject for the email. The backup notification mail is sent as a multi-part message, containing a plaintext part (vzdump-body.txt.hbs) and an HTML part (vzdump-body.html.hbs). If the HTML template file does not exist, the plaintext template is used for both the plaintext part and the HTML part.

Regarding variables, there is not really much more available than what is used at the moment in the existing templates. See [1] for which data is passed to the rendering engine.

The templates are based on Handlebars templates [2], refer to [3] for a syntax reference.

The following helper functions are available for our notification templates:
  • {{ human-byte <data> }} renders a byte value to humanly readable form (e.g. 1.4GiB)
  • {{ duration <data> }} format a duration (e.g. number of seconds to 1h 4m 10s)
  • {{ timestamp <data> }} format a Unix timestamp
  • {{ table <data> }} render a table. The data that is passed must conform to the expected schema (e.g see [4] for an example)
  • {{ object <data> }} format the passed data as pretty-printed JSON

The templates and helpers are still somewhat of an implementation detail and might change once we add the override mechanism.
Then we might add additional variables or helpers.

I hope this helps. Let me know if you have any further specific questions. Also let me know if you have any wishes or suggestions for what additional variables/helpers you could need, we will consider them when adding the override mechanism.

[1] https://git.proxmox.com/?p=pve-mana...e002a6268eec456d055c9ef42f79eb8e;hb=HEAD#l531
[2] https://docs.rs/handlebars/latest/handlebars/
[3] https://handlebarsjs.com/
[4] https://git.proxmox.com/?p=proxmox....18b027018f0d13532404b205e3dc6366;hb=HEAD#l101
 
If the HTML template file does not exist, the plaintext template is used for both the plaintext part and the HTML part.
Very useful info and look forward to the enhancement.

In my case, I send all my smtp notifications (including from pve) to a local smtp gateway and into Slack. To keep it condensed/readable on Slack, I have deleted the vzdump-body.html.hbs template to disable html content.

This works mostly ok, but strangely the text content that shows up in Slack includes <html><body><pre> tags at the top and bottom. Seems might be some code somewhere that must be calling the txt.hbs and adds in html wrapper tags when it's not needed.

Is there a clean/easy way to avoid this. Would be good if the enhancement resolves this as well.
 
In my case, I send all my smtp notifications (including from pve) to a local smtp gateway and into Slack. To keep it condensed/readable on Slack, I have deleted the vzdump-body.html.hbs template to disable html content.

This works mostly ok, but strangely the text content that shows up in Slack includes <html><body><pre> tags at the top and bottom. Seems might be some code somewhere that must be calling the txt.hbs and adds in html wrapper tags when it's not needed.

Is there a clean/easy way to avoid this. Would be good if the enhancement resolves this as well.

The mail-based notification targets always send multi-part messages, including a HTML part and a plaintext part. If the template for the HTML part could not be found, we render the plaintext one and wrap the content in <html><body><pre> tags. This is not likely to be changed with the introduced override mechanism (first draft here: [1]).
What we could do is to have an (advanced) setting for mail based targets to only send then plaintext part. Should not really hurt anyone and could help with these more exotic use cases like yours.

[1] https://lore.proxmox.com/pve-devel/20250313151734.258337-1-a.zeidler@proxmox.com/
 
That works for me. Thanks.

For now in case it helps others, you can use body_checks and header_checks to process the outgoing notification in proxmox/postfix, to strip out the <html><body><pre><tags> and to modify the email header to force the content to be received as plain text.
 
https://bugzilla.proxmox.com/show_bug.cgi?id=6143

In the meanwhile you can edit the notification templates in /usr/share/proxmox-ve/templates/default, just be aware that your changes can be overridden by a package upgrade. Once the override mechanism as described in the bug report is implemented, this is not the case any more.
Hi Lukas,

Not finding /usr/share/proxmox-ve/templates/default in my Proxmox install version 8.4.1. I see this is a recent post but my /usr/share/proxmox-ve/ folder only has one file in it (pve-apt-hook).

Thanks
 
Hi Lukas,

Not finding /usr/share/proxmox-ve/templates/default in my Proxmox install version 8.4.1. I see this is a recent post but my /usr/share/proxmox-ve/ folder only has one file in it (pve-apt-hook).

Thanks

Oh sorry, this was a typo from me. It's the /usr/share/pve-manager/templates/default directory.
But good news, Proxmox VE 8.4 now added support for overridable templates, this eliminates the problem of changes being overridden by package updates.
To override a template, create/copy a template file at /etc/pve/notification-templates/default . For example, if you want to override the subject for backup notifications, create a /etc/pve/notification-templates/default/vzdump-subject.txt.hbs template. You may want to use the default template at /usr/share/pve-manager/templates/default as a reference.
 
Hi, I've been having a bit of a read through this as I also wanted to make some adjustmnets to the notification template. I was tring to add some HTML styling to make the table look more table-esque and to add some highlighting to it but that does not appear to be wokring.

Does proxmox perform any validation that strips the template of any styling?
 
Does proxmox perform any validation that strips the template of any styling?
We don't.
Could you explain how you attempted to override the template (e.g. which files did you use?)
Have you ensured that the HTML actually arrives in your email client? E.g. by viewing the raw email (e.g. in Thunderbird you can do this by selecting the mail and hitting Ctrl + U).
Keep in mind that writing HTML for emails is much different than writing HTML for browsers. Many features that you would expect in a Browser are not supported by email clients and this also varies from client to client. CSS for instance is not really supported by most if not all clients, you have to use inline formatting on the HTML elements.
 
Could you explain how you attempted to override the template (e.g. which files did you use?)
I made new versions of vzdump-body.html.hbs, vzdump-body.txt.hbs and vzdump-subject.txt.hbs. I've also got an eml file that I can provide showing what I've been sent. Thinking about it after checking what I've got in the gmail client and what I have in the eml file, I'm really not sure if it's actually just showing me the text version of the message for some reason and excluding the html one, although that does appear in the eml file so it is bieng sent.

vzdump-subject.txt.hbs
My change to this file was simply to re-order the subject line to show the node first:

HTML:
({{fqdn}}) vzdump backup status: {{status-text}}

vzdump-body.html.hbs
My change to this file was to improve readability by:
- Adding a summary section at the top (status, node, date, duration, size)
- Replacing the default table with one that includes:
- Borders around each cell using inline `style="border: 1px solid"` rules
- Colored rows for each guest entry based on status:
- Green for "Okay" (status = `ok`)
- Red for "Failed" (status = `err`)
- Yellow for "Skipped" (anything else)
- Each `<td>` element has a `background-color` applied inline (since `<tr>` styling didn’t work in my mail client)
- Status labels are shown as "Okay", "Failed", or "Skipped" to improve alignment and clarity

HTML:
<html>
  <body>
    {{error}}

    <h1 style="font-size: 1.2em">Backup Summary</h1>
    <p><strong>Status:</strong> {{summary-status}}</p>
    <p><strong>Node:</strong> {{node}}</p>
    <p><strong>Mode:</strong> {{mode}}</p>
    <p><strong>Date:</strong> {{timestamp}}</p>
    <p><strong>Total Time:</strong> {{duration total-time}}<br/>
       <strong>Total Size:</strong> {{human-bytes total-size}}</p>

    <h2 style="font-size: 1.1em">Details</h2>
    <table style="border-collapse: collapse; width: 100%;">
      <tr>
        <th style="border: 1px solid #000; padding: 4px;">VMID</th>
        <th style="border: 1px solid #000; padding: 4px;">Name</th>
        <th style="border: 1px solid #000; padding: 4px;">Status</th>
        <th style="border: 1px solid #000; padding: 4px;">Time</th>
        <th style="border: 1px solid #000; padding: 4px;">Size</th>
        <th style="border: 1px solid #000; padding: 4px;">Filename</th>
      </tr>
      {{#each guest-table.data}}
      <tr>
        <td style="border: 1px solid #000; padding: 4px;
          {{#if (eq this.status "ok")}}background-color: #e6f4ea;
          {{else if (eq this.status "err")}}background-color: #fce8e6;
          {{else}}background-color: #fff8e1;
          {{/if}}">{{this.vmid}}</td>

        <td style="border: 1px solid #000; padding: 4px;
          {{#if (eq this.status "ok")}}background-color: #e6f4ea;
          {{else if (eq this.status "err")}}background-color: #fce8e6;
          {{else}}background-color: #fff8e1;
          {{/if}}">{{this.name}}</td>

        <td style="border: 1px solid #000; padding: 4px;
          {{#if (eq this.status "ok")}}background-color: #e6f4ea;
          {{else if (eq this.status "err")}}background-color: #fce8e6;
          {{else}}background-color: #fff8e1;
          {{/if}}">
          {{#if (eq this.status "ok")}}Okay
          {{else if (eq this.status "err")}}Failed
          {{else}}Skipped{{/if}}
        </td>

        <td style="border: 1px solid #000; padding: 4px;
          {{#if (eq this.status "ok")}}background-color: #e6f4ea;
          {{else if (eq this.status "err")}}background-color: #fce8e6;
          {{else}}background-color: #fff8e1;
          {{/if}}">{{this.time}}</td>

        <td style="border: 1px solid #000; padding: 4px;
          {{#if (eq this.status "ok")}}background-color: #e6f4ea;
          {{else if (eq this.status "err")}}background-color: #fce8e6;
          {{else}}background-color: #fff8e1;
          {{/if}}">{{this.size}}</td>

        <td style="border: 1px solid #000; padding: 4px;
          {{#if (eq this.status "ok")}}background-color: #e6f4ea;
          {{else if (eq this.status "err")}}background-color: #fce8e6;
          {{else}}background-color: #fff8e1;
          {{/if}}">{{this.filename}}</td>
      </tr>
      {{/each}}
    </table>

    <h2 style="font-size: 1.1em">Logs</h2>
    <pre>{{logs}}</pre>
  </body>
</html>

vzdump-body.txt.hbs
My change to this file was to reformat the plain-text message for both readability and better parsing in Home Assistant:
- A summary section is shown first (status, node, mode, date, total time, total size)
- A clearly formatted table follows using fixed-width columns:

Code:
{{#if error}}{{error}}

{{/if}} Proxmox Backup Summary - {{summary-status}}

Node: {{node}}
Backup Mode: {{mode}}
Date: {{timestamp}}
Total time: {{duration total-time}}
Total size: {{human-bytes total-size}}

VMID | Name          | Status | Duration | Size     | Filename
------------------------------------------------------------------
{{#each guest-table.data}}
{{this.vmid}}   | {{this.name}} | {{#if (eq this.status "ok")}}Okay{{else if (eq this.status "err")}}Failed{{else}}Skipped{{/if}} | {{this.time}} | {{this.size}} | {{this.filename}}
{{/each}}

{{#if logs}}
Logs
====
{{logs}}
{{/if}}

Edit during writting
Okay, So I downlaoded Thunderbird and read the email using that and the table does partialy render properly, It's missing the colour styling for some reason. I'm thinking Gmail does somehting silly to remove the formating, whhich is weird becuase other emails I receive with custom styling work fine.