S/MIME Part 3: Plug and Play for On-Premises Secure Email
Bird
1 Dec 2019
1 min read

Key Takeaways
S/MIME integration for on-premises MTAs: learn how to inject signed and encrypted email streams into PowerMTA, Momentum, or SparkPost SMTP while preserving existing DKIM and compliance setups.
Hybrid security model: combine S/MIME encryption + DKIM signing to guarantee both message authenticity and content privacy in regulated environments.
Deployment flow: configure environment variables (SMTP_HOST, credentials, keys), run the --sign --encrypt --send_smtp workflow, and validate delivery reports.
Performance insight: tests show near-identical speed for SMTP vs API injection (~60 ms per message, 200–280 ms for larger files).
Security best practices: store private keys and API passwords in restricted files (chmod 0700), use STARTTLS and authenticated SMTP sessions.
Use cases: enterprises modernizing legacy mail systems can extend encryption end-to-end without abandoning existing infrastructure.
Q&A Highlights
Why adapt S/MIME for on-prem servers instead of cloud APIs?
Many regulated industries (bank and healthcare sectors) must retain mail on-site. This approach keeps control over message flow while adding modern cryptographic protection.
How does SMTP injection work with PowerMTA or Momentum?
You inject fully formed S/MIME messages to the local listener (port 25 or private VLAN). These MTAs then handle DKIM signing and delivery as usual.
Is S/MIME compatible with DKIM?
Yes — DKIM signs the message after S/MIME encryption, so authentication and integrity checks remain intact.
How do I protect my SMTP credentials and keys?
Export environment variables only in locked-down scripts and use file permissions to restrict access to yourself (
chmod 0700 my_envs.sh).What should I monitor after setup?
Delivery latency (API vs SMTP), TLS handshake success rate, DKIM/S-MIME validation results, and error logs for “relaying denied” or missing auth.
Who benefits most from this configuration?
Organizations running self-hosted mail gateways that require compliance-grade encryption yet want plug-and-play tooling without rewriting mail pipelines.
In this part, we’ll look at how the tool can be adapted to inject mail streams into on-premises platforms such as PowerMTA and Momentum.
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. For organizations implementing S/MIME encryption, understanding how to collect recipient public keys efficiently becomes crucial for scalable secure email operations. Part 2 took us through a simple command-line tool to sign and encrypt emails, then send them through SparkPost.
In this part, we’ll look at how the tool can be adapted to inject mail streams into on-premises platforms such as Port25 PowerMTA and Momentum.
OK – let’s get started!
1. Getting Started
Installing the tool, getting your keys etc. is exactly the same as before. When you’re using an on-premises email system such as PowerMTA or Momentum, you’re already responsible for setting up sending domains, DKIM keys etc. Organizations running on-premises systems also often need to address email archiving system challenges for regulatory compliance and data retention requirements. What we need to do now, is to provide some way of injecting the fully-formed S/MIME messages into your servers.
2. SMTP injection towards Port25 PowerMTA
3. SMTP Injection Towards Momentum
Momentum supports various means of message injection, including API and SMTP. SMTP is the method used here, towards a host already running Momentum. We’ll leave its configuration unchanged, as it already has a capability to accept incoming injections from other approved hosts.
This is a smaller version of a production setup, where “generation” nodes and MTA nodes are separate, yet closely coupled via a private VLAN and load-balancers, carrying internal SMTP injection traffic.

The S/MIME tools are installed as before, and we will inject messages to the address of the SMTP host (MTA):
export SMTP_HOST=xx.xx.xx.xx # set your own MTA / VIP address here
As before, we have the sender’s private key (steve@thetucks.com.pem) and the recipient’s public key (steve.tuck@sparkpost.com.crt) already present on the “generation” node. The first few lines of the message file match these addresses.
We send the message from the “generation” node with exactly the same command as before, and the message shows up in the inbox.
./sparkpostSMIME.py tests/fancy-HTML-to-smt.eml --sign --encrypt --send_smtp
As you’d expect, S/MIME also happily coexists with Momentum’s DKIM signing.
4. SMTP injection towards SparkPost
In part 2 we used the SparkPost transmissions REST API to inject messages. Of course, it’s also possible to inject messages into SparkPost using SMTP. We set the environment variables like this:
If you’re using SparkPost EU-hosted service then set SMTP_HOST as smtp.eu.sparkpostmail.com.
(See here for more options – for example you can inject on port 2525 rather than 587.)
The output below shows STARTTLS is used, along with the username and password.
./sparkpostSMIME.py tests/fancy-HTML-to-smt.eml --sign --encrypt --send_smtp
You’ll see:
The password is printed with substitute *** characters, so you’re not compromising the privacy of your key if someone’s looking over your shoulder.
Securing Your Credentials
Note that environment variables could be set up in a shell script file or similar, to save retyping. If you do, please look after your passwords/API keys by limiting access to that file to yourself only. For example, if your credentials setup file is named my_envs.sh, then run:
chmod 0700 my_envs.sh
SMTP-Related Warnings You May See
SparkPost’s SMTP injection is pretty strict, as you would expect from a public service. If you haven’t set the SMTP port number, you’ll see a warning:
{'bob.lumreeker@gmail.com': (550, b'5.7.1 relaying denied')}
If you haven’t set the SMTP username or haven’t set the password, you’ll see:
These error messages are simply reported as-is from the Python SMTP library, hence the formatting.
Which one’s faster – SMTP or API?
Frankly, S/MIME is unlikely to be a high-volume use-case, but having the same tool with two output options was just asking for us to run a race!
The “Avocado” email test file used here is approx 19KB. Repeating the tests 10 times via a bash loop showed the average times to be similar for SMTP and API, around 60 milliseconds per message, which is pretty fast. In this case, we injected from a medium EC2 instance in the same hosting region as SparkPost.com, which is a good way to keep network round-trip times low.
Repeating this with a larger test file (577KB), the API took roughly 200 milliseconds, while SMTP took 280 milliseconds per message – still impressive for a file size 30x larger. Of course, your mileage may vary depending on location, internet congestion etc, but performance is unlikely to be an issue.
If you really need maximum performance, a good starting point would be to launch a set number of concurrent injection processes/sessions as per our transmission best practices recommendations – e.g. from a supervisor task.





