CalendarScheduling.httpRsvpTemplate is used as the RSVP link base URL, breaking RSVP links in iMIP invitation emails

Issue Description

Hi there,

I have a Stalwart enterprise license and try to customise the calendar invite HTML. iMIP works, but when we add something to RSVP it breaks.

Expected Behavior

Adding HTML code to the RSVP template is rendered and used correctly.

Actual Behavior

Setting CalendarScheduling.httpRsvpTemplate (to supply a custom RSVP web-response page) also changes the base URL used for the RSVP links embedded in iMIP invitation emails. The code that builds itip_http_rsvp_url reads the http_rsvp_template field instead of http_rsvp_url. As a result, every Accept/Decline/Tentative link in the invitation email becomes &m=ACCEPTED and is broken. Separately, httpRsvpUrl - the setting documented to override the base URL - is never read.

Location: crates/common/src/config/groupware.rs, constructing itip_http_rsvp_url:

itip_http_rsvp_url: if sched.http_rsvp_enable {
if let Some(url) = sched
.http_rsvp_template // ← should be sched.http_rsvp_url
.as_deref()
.map(|v| v.trim().trim_end_matches(ā€˜/’))
.filter(|v| !v.is_empty())
{
Some(url.to_string())
} else {
Some(format!(ā€œhttps://{}/calendar/rsvpā€, system.default_hostname))
}
} else {
None
},

Expected: base URL comes from http_rsvp_url (falling back to https://{default_hostname}/calendar/rsvp);
http_rsvp_template is used only to render the web page.

Actual: base URL is taken from http_rsvp_template. With a custom template set, RSVP links become the
template HTML; http_rsvp_url has no effect.

PS: Do I really have to restart the stalwart docker container to trigger a reload?

Reproduction Steps

Reproduce

  1. Enterprise licence active.
  2. Set CalendarScheduling.httpRsvpTemplate to any HTML.
  3. Restart; create an event with an external attendee.
  4. Inspect the invitation email — the Yes/No/Maybe hrefs are …&m=ACCEPTED instead of
    https:///calendar/rsvp?…&m=ACCEPTED.

Impact: a custom RSVP web page cannot be used without breaking RSVP links in invitation emails; the httpRsvpUrl override is non-functional.

Suggested fix: read sched.http_rsvp_url (not sched.http_rsvp_template) when building itip_http_rsvp_url.

Stalwart Version

v0.16.x

Installation Method

Docker

Database Backend

RocksDB

Blob Storage

RocksDB

Search Engine

Internal

Directory Backend

Internal

I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.

on

I have searched this support forum (open and closed topics) and confirm this is not a duplicate.

on

I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.

on

Good, there’s a ā€œReloadSettingsā€ action so restarting the container shouldn’t be necessary. That answers the PS question too.

I have enough to answer both parts confidently.

Confirmed in the source: this is a real bug. In crates/common/src/config/groupware.rs, the itip_http_rsvp_url field is built from sched.http_rsvp_template instead of sched.http_rsvp_url:

itip_http_rsvp_url: if sched.http_rsvp_enable {
    if let Some(url) = sched
        .http_rsvp_template   // should be sched.http_rsvp_url
        ...

This matches your analysis exactly — the base URL used to build RSVP links in iMIP emails is taken from the HTML template content instead of the configured httpRsvpUrl, so any custom template gets embedded as the link base, breaking Accept/Decline/Tentative links. httpRsvpUrl is indeed never read for this purpose. This is a genuine defect and will need a code fix on Stalwart’s side (swapping the field reference to http_rsvp_url); there’s no config-only workaround since the template field is what’s wired in.

On your PS: no, a full container restart shouldn’t be required for config changes. Stalwart supports reloading settings live via a ReloadSettings action (triggerable from the WebUI’s server actions section or via CLI), separate from ReloadTlsCertificates. See the Action object reference for the available reload variants.

This is an automated reply from the Stalwart Help Bot. Other community members may follow up if this answer is incomplete or wrong.

This has been fixed in v0.16.12 which will be released this week.

Great. Thanks for the fast reply and fix.