Get started
On this page
Sending email from your app
Testlie speaks plain SMTP, so your app keeps its normal mail code: change the SMTP settings in the environment you want to capture (development, staging, CI) and every message lands in an inbox instead of reaching real people.
SMTP settings
Each inbox has its own credentials, on its SMTP settings tab:
| Setting | Value |
|---|---|
| Host | smtp.testlie.com |
| Port | 587, 2525, 465 |
| Username | the inbox's username (14 hex characters) |
| Password | the inbox's password (shown to team members; admins can rotate it) |
| Authentication | PLAIN or LOGIN |
| Encryption | STARTTLS on the plain ports when the server has a certificate; implicit TLS on 465 if it is listed |
The credentials decide the inbox, not the recipient: mail sent with an inbox's username lands in that inbox whatever the To, Cc and Bcc addresses are. Bcc recipients are shown in the viewer from the SMTP envelope.
When the server has TLS configured, it only offers and accepts AUTH on a connection that has been upgraded with STARTTLS (unless the operator set SMTP_ALLOW_INSECURE_AUTH=true). Most clients upgrade automatically; the snippets below enable it where they do not.
Tip: an empty inbox in the app shows all of these snippets already filled in with its real host, port and credentials.
Inbound address
If the server has an inbound domain, each inbox also has its own address, <alias>@in.testlie.com, shown on the SMTP settings tab. Mail sent to it from anywhere (no credentials needed) lands in the inbox. Use it to test flows where a real third party sends you mail, such as a sign-up confirmation from a SaaS vendor.
Node.js (nodemailer)
import nodemailer from "nodemailer";
const transport = nodemailer.createTransport({
host: "smtp.testlie.com",
port: 587,
secure: false, // true only for port 465; STARTTLS is used automatically when offered
auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASS },
});
await transport.sendMail({
from: "app@example.com",
to: "new-user@example.com",
subject: "Welcome aboard",
html: "<h1>Hi!</h1><a href='https://app.example.com/verify'>Verify</a>",
});Python (smtplib)
import os, smtplib
from email.message import EmailMessage
msg = EmailMessage()
msg["From"] = "app@example.com"
msg["To"] = "new-user@example.com"
msg["Subject"] = "Welcome aboard"
msg.set_content("Hi! Verify your account: https://app.example.com/verify")
msg.add_alternative("<h1>Hi!</h1><a href='https://app.example.com/verify'>Verify</a>", subtype="html")
with smtplib.SMTP("smtp.testlie.com", 587) as smtp:
smtp.starttls() # omit if the server has no TLS certificate
smtp.login(os.environ["SMTP_USER"], os.environ["SMTP_PASS"])
smtp.send_message(msg)Django
# settings/staging.py
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "smtp.testlie.com"
EMAIL_PORT = 587
EMAIL_HOST_USER = os.environ["SMTP_USER"]
EMAIL_HOST_PASSWORD = os.environ["SMTP_PASS"]
EMAIL_USE_TLS = True # STARTTLS; set False if the server has no certificate
# For port 465 use EMAIL_USE_SSL = True instead (and EMAIL_USE_TLS = False).send_mail(...), EmailMessage and password-reset emails from django.contrib.auth all go through this backend.
Ruby on Rails (Action Mailer)
# config/environments/staging.rb
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
address: "smtp.testlie.com",
port: 587,
user_name: ENV["SMTP_USER"],
password: ENV["SMTP_PASS"],
authentication: :plain,
enable_starttls_auto: true
}
config.action_mailer.default_url_options = { host: "staging.example.com" }PHP (Laravel)
# .env
MAIL_MAILER=smtp
MAIL_HOST=smtp.testlie.com
MAIL_PORT=587
MAIL_USERNAME=your-inbox-username
MAIL_PASSWORD=your-inbox-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=app@example.comUse MAIL_ENCRYPTION=null when the server has no certificate, or ssl with port 465. Plain PHP with PHPMailer works the same way: $mail->isSMTP(); $mail->Host = 'smtp.testlie.com'; $mail->Port = 587; $mail->SMTPAuth = true;.
Java (Spring Boot)
# application-staging.properties
spring.mail.host=smtp.testlie.com
spring.mail.port=587
spring.mail.username=${SMTP_USER}
spring.mail.password=${SMTP_PASS}
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=trueInject JavaMailSender and send as usual:
@Autowired JavaMailSender mailSender;
var message = new SimpleMailMessage();
message.setFrom("app@example.com");
message.setTo("new-user@example.com");
message.setSubject("Welcome aboard");
message.setText("Hi! Verify your account: https://app.example.com/verify");
mailSender.send(message);.NET (MailKit)
System.Net.Mail.SmtpClient still works, but Microsoft recommends MailKit:
// dotnet add package MailKit
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
var message = new MimeMessage();
message.From.Add(MailboxAddress.Parse("app@example.com"));
message.To.Add(MailboxAddress.Parse("new-user@example.com"));
message.Subject = "Welcome aboard";
message.Body = new TextPart("html") { Text = "<h1>Hi!</h1>" };
using var client = new SmtpClient();
await client.ConnectAsync("smtp.testlie.com", 587, SecureSocketOptions.StartTlsWhenAvailable);
await client.AuthenticateAsync(Environment.GetEnvironmentVariable("SMTP_USER"), Environment.GetEnvironmentVariable("SMTP_PASS"));
await client.SendAsync(message);
await client.DisconnectAsync(true);Go (net/smtp)
package main
import (
"net/smtp"
"os"
)
func main() {
// SendMail upgrades with STARTTLS when the server offers it. PlainAuth refuses to send a
// password over an unencrypted connection, except to localhost.
auth := smtp.PlainAuth("", os.Getenv("SMTP_USER"), os.Getenv("SMTP_PASS"), "smtp.testlie.com")
msg := []byte("From: app@example.com\r\n" +
"To: new-user@example.com\r\n" +
"Subject: Welcome aboard\r\n\r\n" +
"Hi! Verify your account: https://app.example.com/verify\r\n")
err := smtp.SendMail("smtp.testlie.com:587", auth, "app@example.com", []string{"new-user@example.com"}, msg)
if err != nil {
panic(err)
}
}Limits and errors
| SMTP reply | Meaning |
|---|---|
535 |
Wrong username or password. Copy them again from the inbox, or check whether an admin rotated the password. |
538 |
The server requires STARTTLS before AUTH. Enable STARTTLS in your client. |
530 |
The client did not authenticate, and the recipient is not an inbox's inbound address. Set the username and password. |
552 |
The message is larger than the plan's (or the server's) maximum size. |
451 |
The inbox received more messages per minute than the plan allows. Retry shortly; most mail libraries do. |
550 |
The team's monthly message quota is used up (or the inbox was deleted). See Plans & limits. |
421 |
Too many connections, concurrent sessions or failed logins from your IP address. Wait a minute and retry. |