NameSilo DNS Integration Failure

Issue Description

When Stalwart is setting automatic DNS records for NameSilo, we are getting failures.

Expected Behavior

The records should be created using the NameSilo API.

Actual Behavior

An error is given from the Scheduled Task.

Reproduction Steps

  1. Configure NameSilo Provider
  2. Add Domain
  3. Check scheduled task.

Relevant Log Output

Failed to set DNS RRSet for emytesting.net./TXT: Failed to set DNS RRSet: Parse error: Invalid XML response: invalid type: string "{\"request\":{\"operation\":\"dnsListRecords\",\"ip\":\"64.246.108.222\"},\"reply\":{\"code\":300,\"detail\":\"success\",\"resource_record\":[{\"record_id\":\"735210d93042101c80bcf814e788f32c\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"e964e73efb8c07b91b6b9e37ae985154\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"1add1ecde258692c6365f098aa8bfc86\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"3a71e70f70522359bb68543f429b33fb\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"a86376772acec19fc682df725a121ff2\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d16555ee99bcb547072e7d3b3e5a4c64\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d23ce37b5dbc98b8064fcb2328dfab2a\",\"type\":\"TXT\",\"host\":\"_domainconnect\",\"value\":\"www.namesilo.com\\/domainconnect\",\"ttl\":3600,\"distance\":0}]}}", expected struct NameSiloEnvelope; Failed to set DNS RRSet for _ua-auto-config.emytesting.net./TXT: Failed to set DNS RRSet: Parse error: Invalid XML response: invalid type: string "{\"request\":{\"operation\":\"dnsListRecords\",\"ip\":\"64.246.108.222\"},\"reply\":{\"code\":300,\"detail\":\"success\",\"resource_record\":[{\"record_id\":\"735210d93042101c80bcf814e788f32c\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"e964e73efb8c07b91b6b9e37ae985154\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"1add1ecde258692c6365f098aa8bfc86\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"3a71e70f70522359bb68543f429b33fb\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"a86376772acec19fc682df725a121ff2\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d16555ee99bcb547072e7d3b3e5a4c64\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d23ce37b5dbc98b8064fcb2328dfab2a\",\"type\":\"TXT\",\"host\":\"_domainconnect\",\"value\":\"www.namesilo.com\\/domainconnect\",\"ttl\":3600,\"distance\":0}]}}", expected struct NameSiloEnvelope; Failed to set DNS RRSet for _imaps._tcp.emytesting.net./SRV: Failed to set DNS RRSet: Parse error: Invalid XML response: invalid type: string "{\"request\":{\"operation\":\"dnsListRecords\",\"ip\":\"64.246.108.222\"},\"reply\":{\"code\":300,\"detail\":\"success\",\"resource_record\":[{\"record_id\":\"735210d93042101c80bcf814e788f32c\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"e964e73efb8c07b91b6b9e37ae985154\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"1add1ecde258692c6365f098aa8bfc86\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"3a71e70f70522359bb68543f429b33fb\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"a86376772acec19fc682df725a121ff2\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d16555ee99bcb547072e7d3b3e5a4c64\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d23ce37b5dbc98b8064fcb2328dfab2a\",\"type\":\"TXT\",\"host\":\"_domainconnect\",\"value\":\"www.namesilo.com\\/domainconnect\",\"ttl\":3600,\"distance\":0}]}}", expected struct NameSiloEnvelope; Failed to set DNS RRSet for mta-sts.emytesting.net./CNAME: Failed to set DNS RRSet: Parse error: Invalid XML response: invalid type: string "{\"request\":{\"operation\":\"dnsListRecords\",\"ip\":\"64.246.108.222\"},\"reply\":{\"code\":300,\"detail\":\"success\",\"resource_record\":[{\"record_id\":\"735210d93042101c80bcf814e788f32c\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"e964e73efb8c07b91b6b9e37ae985154\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"1add1ecde258692c6365f098aa8bfc86\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"3a71e70f70522359bb68543f429b33fb\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"a86376772acec19fc682df725a121ff2\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d16555ee99bcb547072e7d3b3e5a4c64\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d23ce37b5dbc98b8064fcb2328dfab2a\",\"type\":\"TXT\",\"host\":\"_domainconnect\",\"value\":\"www.namesilo.com\\/domainconnect\",\"ttl\":3600,\"distance\":0}]}}", expected struct NameSiloEnvelope; Failed to set DNS RRSet for autodiscover.emytesting.net./CNAME: Failed to set DNS RRSet: Parse error: Invalid XML response: invalid type: string "{\"request\":{\"operation\":\"dnsListRecords\",\"ip\":\"64.246.108.222\"},\"reply\":{\"code\":300,\"detail\":\"success\",\"resource_record\":[{\"record_id\":\"735210d93042101c80bcf814e788f32c\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"e964e73efb8c07b91b6b9e37ae985154\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"1add1ecde258692c6365f098aa8bfc86\",\"type\":\"A\",\"host\":\"@\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"3a71e70f70522359bb68543f429b33fb\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.235\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"a86376772acec19fc682df725a121ff2\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.232.24.161\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d16555ee99bcb547072e7d3b3e5a4c64\",\"type\":\"A\",\"host\":\"www\",\"value\":\"172.234.25.42\",\"ttl\":3603,\"distance\":0},{\"record_id\":\"d23ce37b5dbc98b8064fcb2328dfab2a\",\"type\":\"TXT\",\"host\":\"_domainconnect\",\"value\":\"www.namesilo.com\\/domainconnect\",\"ttl\":3600,\"distance\":0}]}}", expected struct NameSiloEnvelope;

### Stalwart Version
v0.16.x

### Installation Method
Binary (Linux)

### Database Backend
PostgreSQL

### Blob Storage
S3-compatible

### Search Engine
PostgreSQL

### 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

Possible Root Cause:

Root cause

The error isn’t really about your DNS records — it’s a response‑format mismatch. Look at the body embedded in the error: it’s JSON ({"request":{"operation":"dnsListRecords"...}). But Stalwart’s NameSilo driver parses the response with an XML deserializer (quick_xml::de::from_str into a NameSiloEnvelope struct). When quick‑xml is handed a JSON document, it can’t find the <namesilo>/<reply> elements it expects, the whole payload collapses to a single text node, and serde reports exactly what you see: invalid type: string … expected struct NameSiloEnvelope.

So: NameSilo returned JSON, Stalwart demanded XML. Every “Failed to set … RRSet” line is the same failure — before setting any record, the driver calls dnsListRecords to diff existing records, that list call comes back JSON, and the parse blows up, so nothing downstream ever runs.

Why NameSilo is sending JSON despite type=xml

This is the interesting part. Stalwart’s driver (the dns-update crate, src/providers/namesilo.rs) does send type=xml on every request — I confirmed it in the current main and in released 0.4.1 / 0.5.0 / 0.5.4, so it’s not a version regression:

version=1&type=xml&key=…&domain=emytesting.net

Per NameSilo’s own API reference, type=xml should yield XML, and every other real‑world NameSilo client (the Go nrdcg/namesilo lib, the common PowerShell/curl DDNS scripts) sends exactly that and gets XML back. So on paper this should work.

The one concrete difference: dns-update’s shared HTTP client sets a default header on every request —

rust

headers.append(CONTENT_TYPE, HeaderValue::from_static("application/json"));

— and the NameSilo provider builds on that default client without overriding it. So each request carries Content-Type: application/json while the query string says type=xml. NameSilo’s front end appears to be doing content negotiation off the header and overriding the query param, handing back JSON. That header is the only thing distinguishing Stalwart’s requests from all the working type=xml clients, and it produces precisely this symptom. It’s effectively a bug in the dns-update NameSilo provider.

Idea that probably has been tried:

Change the

into

https://support.stalw.art/u/ken_emy if you fear cargo build, say so.

Fixed in v0.16.16 (yet to be released). Note that we do not have a Namesilo API key to test the fix, which was guided by the published API documentation.

I shall test it, and report back on this thread! Thank you very much!!

Upgraded to 0.16.16, I didnt see the fix in the change list. But I tried again.

Failed to set DNS RRSet for v1-rsa-20260730.domainkey.emytesting.net./TXT: Failed to set DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000; Failed to set DNS RRSet for mta-sts.emytesting.net./CNAME: Failed to set DNS RRSet: API error: NameSilo error 280: Field \u0022Target hostname\u0022 should be valid. Please use only letters (A-Z, case-insensitive), numbers (0-9), and hyphens (-).; Failed to set DNS RRSet for _pop3s._tcp.emytesting.net./SRV: Failed to set DNS RRSet: API error: NameSilo error 280: target:stalwart-mx-1.upwardmail.us. must be a valid host; Failed to set DNS RRSet for _carddavs._tcp.emytesting.net./SRV: Failed to set DNS RRSet: API error: NameSilo error 280: target:stalwart-mx-1.upwardmail.us. must be a valid host; Failed to set DNS RRSet for _dmarc.emytesting.net./TXT: Failed to set DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000; Failed to set DNS RRSet for emytesting.net./TXT: Failed to set DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000; Failed to set DNS RRSet for v1-ed25519-20260730.domainkey.emytesting.net./TXT: Failed to set DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000; Failed to set DNS RRSet for ua-auto-config.emytesting.net./CNAME: Failed to set DNS RRSet: API error: NameSilo error 280: Field \u0022Target hostname\u0022 should be valid. Please use only letters (A-Z, case-insensitive), numbers (0-9), and hyphens (-).; Failed to set DNS RRSet for _caldavs._tcp.emytesting.net./SRV: Failed to set DNS RRSet: API error: NameSilo error 280: target:stalwart-mx-1.upwardmail.us. must be a valid host; Failed to set DNS RRSet for _mta-sts.emytesting.net./TXT: Failed to set DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000; Failed to set DNS RRSet for _submissions._tcp.emytesting.net./SRV: Failed to set DNS RRSet: API error: NameSilo error 280: target:stalwart-mx-1.upwardmail.us. must be a valid host; Failed to set DNS RRSet for _ua-auto-config.emytesting.net./TXT: Failed to set DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000; Failed to set DNS RRSet for _smtp.tls.emytesting.net./TXT: Failed to set DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000; Failed to set DNS RRSet for autodiscover.emytesting.net./CNAME: Failed to set DNS RRSet: API error: NameSilo error 280: Field \u0022Target hostname\u0022 should be valid. Please use only letters (A-Z, case-insensitive), numbers (0-9), and hyphens (-).; Failed to set DNS RRSet for emytesting.net./MX: Failed to set DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000; Failed to set DNS RRSet for _imaps.tcp.emytesting.net./SRV: Failed to set DNS RRSet: API error: NameSilo error 280: target:stalwart-mx-1.upwardmail.us. must be a valid host; Failed to set DNS RRSet for autoconfig.emytesting.net./CNAME: Failed to set DNS RRSet: API error: NameSilo error 280: Field \u0022Target hostname\u0022 should be valid. Please use only letters (A-Z, case-insensitive), numbers (0-9), and hyphens (-).; Failed to set DNS RRSet for _jmap._tcp.emytesting.net./SRV: Failed to set DNS RRSet: API error: NameSilo error 280: target:stalwart-mx-1.upwardmail.us. must be a valid host

Looks like JSON/XML issue is solved. But we’re onto new issues now.

  1. Looks to be an issue setting the TTL. Guessing that its set too low by default in Stalwart. Needs to be at least 3600 in NameSilo.
    DNS RRSet: API error: NameSilo error 280: ttl: You must be between 3600 and 2592000;

  2. Something is out of line with the host name. I think the trailing dot at the end of the full hostname needs to be removed from the api submission.
    Failed to set DNS RRSet for _submissions._tcp.emytesting.net./SRV: Failed to set DNS RRSet: API error: NameSilo error 280: target:stalwart-mx-1.upwardmail.us. must be a valid host;

AI Says:

the crate does already do this stripping elsewhere — list_at() (line 218) uses fqdn.trim_end_matches('.') when comparing hostnames — so the pattern for handling this exists in the file, it’s just not applied to the values sent to add_record for CNAME/MX/SRV.

I’d be willing to take a crack at a fix for this and compile the binary myself. If fixed, then deliver a pull request if that would be allowed???

Ken

We have just fixed those errors on the dns-update crate. If you have the possibility, please test the main branch of dns-update against your NameSilo account. If the fix works we’ll include it in v0.16.17.

Funny, I fixed them too and compiled my code and it worked. I will test the “official fixes” as well. More soon.

I no longer “fear cargo build”.

I can confirm that the latest dns-update v0.5.6 and it’s changes fix integration with NameSilo. This was tested with a valid API key and a valid domain.

Thanks, we’ll include the fix in v0.16.17.