You have a side project that needs to send a few emails from your custom domain. A signup confirmation, a password reset, the occasional notification. Nothing fancy. You do not want to embed your personal Gmail credentials in the code, you do not want to set up a full transactional email account for 200 emails a month, and you already have a KaiMail account doing your inbound forwarding.
Good news. You can use the same KaiMail account to send email via our SMTP functionality. This guide shows you how, in Python, Ruby and PHP, with the smallest amount of code I could get away with.
| Setting | Value |
|---|---|
| SMTP Server | mail.kaimail.net |
| Port | 587 |
| Security | STARTTLS |
| Username | Your KaiMail email |
| Password | Your SMTP password |
This is plain SMTP submission. Nothing proprietary. Any reasonable SMTP library in any language will work. The two examples below use the most ordinary tools you would reach for in Python and Ruby.
Python's standard library has everything you need. No pip install required.
import os
import smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["From"] = "[email protected]"
msg["To"] = "[email protected]"
msg["Subject"] = "Hello from KaiMail"
msg.set_content("Sent via KaiMail SMTP.")
with smtplib.SMTP("mail.kaimail.net", 587) as smtp:
smtp.starttls()
smtp.login(os.environ["KAIMAIL_USER"], os.environ["KAIMAIL_PASS"])
smtp.send_message(msg)
Save it, export KAIMAIL_USER and KAIMAIL_PASS in your shell, and run it. That is the whole thing.
Two details that bite people the first time:
starttls() before login(). If you call them in the other order, you are sending your password over an unencrypted connection. KaiMail will reject the login, but you should not rely on the server to save you from that mistake. Always upgrade the connection first.From address must be a domain you own on KaiMail. The server validates this on every send. If you try to send as [email protected] or as a domain you have not added to your account, the send is rejected. This is the feature, not the bug. It is how we stop your account from being used to spoof other people.If you want HTML email, use msg.add_alternative(html, subtype="html") after set_content(). The rest of the code stays the same.
Ruby's standard library does have net/smtp, but the mail gem is the de-facto choice and it is much less awkward to use. One dependency is a fair price.
require "mail"
Mail.defaults do
delivery_method :smtp,
address: "mail.kaimail.net",
port: 587,
user_name: ENV["KAIMAIL_USER"],
password: ENV["KAIMAIL_PASS"],
authentication: :plain,
enable_starttls_auto: true
end
Mail.deliver do
from "[email protected]"
to "[email protected]"
subject "Hello from KaiMail"
body "Sent via KaiMail SMTP."
end
gem install mail, set the same two environment variables, and run it.
The Ruby gotchas are essentially the same ones as Python, just with different keyword names:
enable_starttls_auto: true is doing the work smtp.starttls() did in Python. Without it, the gem will happily try to send your credentials in the clear.authentication: :plain is correct here. STARTTLS handles the encryption; PLAIN auth runs over the encrypted channel. Do not switch to :login or :cram_md5 looking for "more security". You will not find it.From validation applies. A domain you do not own on KaiMail will fail.If you are inside Rails, you can drop the Mail.defaults block straight into config/environments/production.rb as config.action_mailer.smtp_settings. ActionMailer uses the same gem under the hood, so the keys are identical.
PHP's built-in mail() function is famously painful for SMTP. It expects a configured local sendmail, it does not handle authentication, and the error reporting is minimal. Skip it. Use PHPMailer, which is the de-facto choice and has been for a decade.
<?php
require "vendor/autoload.php";
use PHPMailer\PHPMailer\PHPMailer;
$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host = "mail.kaimail.net";
$mail->Port = 587;
$mail->SMTPAuth = true;
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
$mail->Username = getenv("KAIMAIL_USER");
$mail->Password = getenv("KAIMAIL_PASS");
$mail->setFrom("[email protected]");
$mail->addAddress("[email protected]");
$mail->Subject = "Hello from KaiMail";
$mail->Body = "Sent via KaiMail SMTP.";
$mail->send();
composer require phpmailer/phpmailer, set the same two environment variables, and run it with php send.php.
The PHP gotchas:
SMTPSecure = ENCRYPTION_STARTTLS is the equivalent of starttls() in Python. The other constant is ENCRYPTION_SMTPS, which is implicit TLS on 465. We do not run 465, so do not use that one.new PHPMailer(true) with the boolean argument turns on exceptions. Without it, errors are silently stored on the object and send() just returns false. You will lose hours debugging "why did nothing happen" the first time. Always pass true.From validation applies. Spoofed sender domains are rejected by the server.If you are inside Laravel, you do not need PHPMailer at all. Symfony Mailer ships with the framework; set MAIL_MAILER=smtp, MAIL_HOST=mail.kaimail.net, MAIL_PORT=587, MAIL_ENCRYPTION=tls, and MAIL_USERNAME / MAIL_PASSWORD in your .env, and Laravel does the rest.
A few more things worth flagging, drawn from actual support tickets:
From domain must be one you own on KaiMail. The server rejects spoofed senders. Adding a new domain in the dashboard is a one-minute job, but you do have to do it before you can send from it.This script is the smallest thing that works. For production code, three additions are worth doing:
If you also need to receive email and pipe it into your application, the webhook integration guide is the companion piece to this one. Together they cover both directions.
For the full feature description, see the SMTP sending feature page. If you have not enabled SMTP on your account yet, the original announcement has the dashboard walkthrough. And if you are still on the "Send mail as" Gmail workaround, the setup guide for that explains why programmatic SMTP is the cleaner option once you are writing code anyway.