Sending through SMTP Relay from Node.js and Python: Nodemailer and smtplib, with STARTTLS

Node.js, Python & Docker·· 9 views· 3 min read

The short answer: in Node.js you use Nodemailer; in Python, the built-in smtplib (or the Django e-mail settings). On port 587, the connection starts unencrypted and switches to encrypted with STARTTLS; on 465, it is encrypted from the start. The credential details go in environment variables, never written in the code.

Node.js with Nodemailer

const nodemailer = require("nodemailer");
const t = nodemailer.createTransport({
host: process.env.SMTP_HOST, port: 587, secure: false, requireTLS: true,
auth: { user: process.env.SMTP_USER, pass: process.env.SMTP_PASSWORD },
});
await t.sendMail({ from: "no-reply@yourcompany.com", to: "ana@example.com",
subject: "Order confirmed", text: "Thank you for your order." });

On port 587, secure: false and requireTLS: true: Nodemailer performs STARTTLS and refuses to carry on unencrypted. On port 465, change to port: 465, secure: true.

Python with smtplib

import os, smtplib
from email.message import EmailMessage
m = EmailMessage()
m["From"], m["To"] = "no-reply@yourcompany.com", "ana@example.com"
m["Subject"] = "Order confirmed"
m.set_content("Thank you for your order.")
with smtplib.SMTP(os.environ["SMTP_HOST"], 587) as s:
s.starttls()
s.login(os.environ["SMTP_USER"], os.environ["SMTP_PASSWORD"])
s.send_message(m)

For port 465 use smtplib.SMTP_SSL(host, 465) and drop the starttls() line.

Django

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = os.environ["SMTP_HOST"]
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = os.environ["SMTP_USER"]
EMAIL_HOST_PASSWORD = os.environ["SMTP_PASSWORD"]
DEFAULT_FROM_EMAIL = "no-reply@yourcompany.com"

For port 465, EMAIL_PORT = 465 and EMAIL_USE_SSL = True instead of EMAIL_USE_TLS. Never both on at the same time.

Swapping port and encryption is the most common mistake here. secure: true on port 587, or starttls() on 465, gives a TLS error or a connection that never answers. The rule: 587 with STARTTLS, 465 with TLS.

Where to keep the details

For Node.js and Python applications on our hosting, environment variables are set on the application page in cPanel (Setup Node.js App or Setup Python App). On a VPS, in a .env file outside the public folder or in the service that starts the application. One credential per application: see one credential per program.

Automation tools speak SMTP too. In n8n, for example, the send e-mail node takes these same details: see connecting n8n to e-mail.

Application still not sending? Open a ticket with the full error message, without the password.

Open a support ticket

SEE ALSO

SMTP Relay in Laravel and other PHP frameworks: the .env settings and a first test e-mail

Testing an SMTP credential before going live: a test e-mail from the command line

SMTP Relay in any program: what Host, Port, Encryption, Username and From mean on each screen

Connecting n8n to e-mail: SMTP and IMAP

A scheduled report by e-mail: a script, a cron job and an SMTP account

SMTP Relay not sending: connection, TLS, login, sender and recipient problems, one by one

RECOMMENDED PRODUCT

Professional e-mail on your domain

Mailboxes in your company name, no adverts, with spam filtering. from ₦9.900,00/mo (3-year plan, with coupon)

See plans
Was this answer helpful? Your answer helps us improve this article.