S/MIME Part 4: Collecting Recipient Public Keys the Easy Way – with SparkPost Inbound Relay Webhooks. Sending S/MIME encrypted mail is more complex, requiring recipient public keys. Learn how to handle this in app-generated email streams.

Key Takeaways
-
Premise: Sending S/MIME-encrypted email isn't hard once you can automatically collect each recipient's public key. This post closes that gap by using SparkPost Inbound Relay Webhooks to receive signed emails, extract certificates, and store them for later encryption.
-
Goal: Build a Flask-based webhook service that listens for incoming signed messages, validates them (DKIM + certificate checks), and safely writes each public key to disk for use in outbound secure mail.
-
**Highlights:**Problem: Manual key exchange doesn't scale for app-generated email.
-
Solution: Invite users to send a signed email; the inbound webhook automatically parses and stores their PEM certificate.
-
**Setup steps:**Configure an Inbound Domain and MX records (e.g., inbound.yourdomain.com).
-
Create an Inbound Relay Webhook via the SparkPost API pointing to your app endpoint.
-
Deploy a small Flask app (webapp.py) using configuration from webapp.ini.
-
Log extensively for transparency; integrate Pytest + Travis CI for automated validation.
-
**Security measures:**Verify DKIM signatures and message authenticity.
-
Validate certificate trust chain before storing.
-
Use a secret auth token in webhook headers.
-
**Output:**Each valid inbound message creates a certificate file such as bob.lumreeker@gmail.com.crt.
-
Once stored, these keys enable encrypted replies using earlier scripts from parts 2 and 3.
Q&A Highlights
- Why is collecting recipient keys so critical for S/MIME?Because encryption requires each recipient's public key; automating this step lets any app send secure mail without manual exchange.
- How does SparkPost Inbound Relay Webhook simplify key collection?It converts any signed inbound email into a structured JSON payload, allowing your app to parse and persist certificates programmatically.
- What safeguards prevent spoofing or junk submissions?The service validates DKIM signatures, enforces authentication tokens, and rejects malformed or unsigned messages.
- Where are certificates stored and in what format?They're written to disk in PEM format (.crt files), ready for use by the signing/encryption toolchain built in previous parts.
- What's the developer workflow?Run the Flask app, verify with Postman using the provided sample payload, then connect it to SparkPost's live webhook for continuous operation.
- Overall takeaway?S/MIME key management can be fully automated with a few lines of Python and SparkPost APIs—bringing scalable encryption to any app-generated email workflow.
In part 1, we had a quick tour of S/MIME, looking at signing and encryption of our message streams across a range of mail clients. Part 2 took us through a simple command-line tool to sign and encrypt emails, then send them through SparkPost. Part 3 showed how to inject secure mail streams into on-premises platforms such as Port25 PowerMTA and Momentum.
- What’s the developer workflow? Run the Flask app, verify with Postman using the provided sample payload, then connect it to SparkPost’s live webhook for continuous operation.
1. Solution overview
Here's what the overall solution will look like.
Diagram depicting a secure email flow illustrating how emails are verified using certificates for secure transmission.
2. Installing, configuring and starting the web app
We'll start with this part, so we have it fully tested before plumbing the inbound relay webhooks.
The web app is included in the same GitHub project as parts 1 – 3, so if you've followed those parts, you already have it. Here are the new bits:
- Program readSMIMEsig.py – read an email and parse out intermediate and user certificates.
- Program webapp.py – simple Flask-compatible web application for use with SparkPost Inbound Relay Webhooks.
- webapp.ini – configuration file for the above. A config file enables the same values to be passed in easily to both command-line and web applications.
You need to ensure your host has the correct TCP port number open to inbound requests from the outside world so that SparkPost can POST messages to your app. If you're hosted on AWS EC2, for example, you'll need to configure the Security Group of your instance.
Instructions for configuring and starting the web app are provided in our setup guide – it's quite easy. To check your app is running and accessible from the outside world, you can send (blank) requests from another host using curl, for example:
curl -X POST https://app.trymsys.net:8855/
Expected response:
{"message":"Unknown Content-Type in request headers"}
3. SparkPost inbound relay webhooks setup
Firstly, we select a domain to use as our inbound message address – here, it will be inbound.thetucks.com. Set your domain up following this guide. Here are the steps I used in detail:
3.1 Add MX Records
You'll need access to your specific Internet Service Provider account. When done, you can check them with dig – here's the command for my domain.
dig +short MX inbound.thetucks.com
4. Internals: DKIM checking, certificate validation
The app checks received emails have valid DKIM and checks that the certificates themselves are valid, as described here. There are implementation notes in there too, and ideas for further work.
Summing up…
We've seen how recipient public keys can be gathered easily using an email to an inbound relay webhooks address. Once done, those recipients can receive their messages in S/MIME encrypted form.
That's it for now! Happy sending.
Other news
Read more from this category
Feb 12, 201815 Email Deliverability Best Practices For Gmail