Why I Moved Crash Report Delivery Behind an API
The real problem was not the SMTP error itself. It was release clients depending on mail configuration baked into the shipped application.
- SMTP
- API
- WPF
- .NET
- Release Engineering
What the problem looked like
The visible symptom was an SMTP authentication failure. Release users could no longer send crash reports or suggestion messages from the application.
At first glance, that looks like a normal mail settings problem. But the deeper issue was that the delivery configuration lived inside the shipped client. Once that configuration became outdated, every installed release inherited the same broken behavior.
Why the DLL boundary was the real issue
When SMTP details are embedded directly in client-side desktop code, mail delivery becomes tied to the exact version already deployed to users. If credentials, auth rules, sender policy, or provider-side behavior changes, old releases keep trying to send with stale assumptions.
- Release users cannot benefit from a server-side mail fix unless they install a new client build.
- SMTP credentials and provider behavior become part of the release compatibility surface.
- Crash and suggestion delivery become harder to debug because the problem sits inside the distributed app.
- A mail provider change should not require updating every installed client.
Why an API became necessary
Moving to an API gave the application a stable contract: the desktop client only needs to submit a report payload, while the server owns SMTP, credentials, retries, and any future provider changes.
That was the key reason for the change. The goal was not to make the system bigger. The goal was to stop mail delivery rules from being locked into old release binaries.
The desktop client should only submit a report
After the change, the client no longer needs to know SMTP host, port, TLS, or auth details. It just sends the report body, recipients, and optional attachments to one server endpoint.
csharp
MailService.cs
The important change is that the released client now talks to one API contract instead of owning the mail transport details itself.
using MultipartFormDataContent requestContent = new();
requestContent.Add(new StringContent(subject, Encoding.UTF8), "Subject");
requestContent.Add(new StringContent(body, Encoding.UTF8), "Body");
foreach (string address in toAddresses)
{
requestContent.Add(new StringContent(address, Encoding.UTF8), "ToAddresses");
}
using HttpRequestMessage request = new(HttpMethod.Post, reportApiUrl)
{
Content = requestContent
};
request.Headers.Add("X-Api-Key", reportApiKey);
using HttpResponseMessage response = await httpClient.SendAsync(request, cancellationToken);The API owns mail delivery
On the server side, the endpoint receives the report payload and forwards it through the real mail infrastructure. That means SMTP settings can change without touching the desktop release.
csharp
ReportsController.cs
This keeps the client transport simple and makes SMTP a server concern instead of a release concern.
[HttpPost("submit")]
public async Task<IActionResult> Submit([FromForm] ReportRequestForm request, CancellationToken cancellationToken)
{
await _reportEmailService.SendAsync(new ReportEmailMessage
{
Subject = request.Subject,
Body = request.Body,
ToAddresses = request.ToAddresses,
Attachments = request.Attachments
}, cancellationToken);
return Ok(new { message = "Report submitted successfully." });
}Configuration still matters, but in the right place
The API endpoint and API key can still live in configuration, but that is a much better boundary than embedding raw SMTP behavior into the client assembly. The mutable part of the system moves to the server, where it can be fixed without waiting for every customer to update.
xml
App.config
Client configuration becomes a stable API address instead of a full mail transport definition.
<appSettings>
<add key="CrashReportApiUrl" value="https://your-server/api/reports/submit" />
<add key="CrashReportApiKey" value="PUT_A_LONG_RANDOM_API_KEY_HERE" />
</appSettings>What changed after that decision
After moving the flow behind an API, crash and suggestion delivery stopped being tightly coupled to stale mail configuration inside old release clients.
That was the real win. SMTP auth errors were only the symptom. The actual fix was moving the unstable delivery logic out of the shipped client boundary.
Share