Skip to content

Commit 2717f24

Browse files
authored
feat: support MAIL_SMTP_URL (#12296)
Signed-off-by: Matt Krick <matt.krick@gmail.com>
1 parent 7dff6c3 commit 2717f24

File tree

4 files changed

+61
-78
lines changed

4 files changed

+61
-78
lines changed

.env.example

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,21 @@ MAIL_PROVIDER='debug'
163163
# MAILGUN_DOMAIN='key_MAILGUN_DOMAIN'
164164
# MAIL_GOOGLE_USER='key_MAIL_GOOGLE_USER'
165165
# MAIL_GOOGLE_PASS='key_MAIL_GOOGLE_PASS'
166+
167+
# For SMTP, MAIL_SMTP_URL is mutually exclusive to the other env vars with the MAIL_SMTP_ prefix
168+
# Use it when custom configs are required
169+
# MAIL_SMTP_URL='smtps://username:password@smtp.example.com/?pool=true&tls.rejectUnauthorized=false'
170+
166171
# MAIL_SMTP_HOST='key_MAIL_SMTP_HOST'
167172
# MAIL_SMTP_PORT=587
168173
# MAIL_SMTP_USER='key_MAIL_SMTP_USER'
169174
# MAIL_SMTP_PASSWORD='key_MAIL_SMTP_PASSWORD'
170175
# MAIL_SMTP_USE_TLS='1' # set to '0' for false
171176
# MAIL_SMTP_CIPHERS='HIGH:MEDIUM:!aNULL:!eNULL:@STRENGTH:!DH:!kEDH'
172177

178+
# When true, verifies DNS resolution, TCP handshake, and authentication on server startup
179+
# MAIL_SMTP_DEBUG=false
180+
173181
# GLOBAL BANNER
174182
# GLOBAL_BANNER_ENABLED='true'
175183
# GLOBAL_BANNER_TEXT='UNCLASSIFIED CUI (IL4)'

packages/server/email/MailManagerSMTP.ts

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,36 @@
11
import nodemailer from 'nodemailer'
2+
import {isNotNull} from '../../client/utils/predicates'
23
import logError from '../utils/logError'
34
import MailManager, {type MailManagerOptions} from './MailManager'
45

5-
export default class MailManagerSMTP extends MailManager {
6-
transport = nodemailer.createTransport({
6+
const composeConfig = () => {
7+
const {
8+
MAIL_SMTP_URL,
9+
MAIL_SMTP_HOST,
10+
MAIL_SMTP_PORT,
11+
MAIL_SMTP_USER,
12+
MAIL_SMTP_PASSWORD,
13+
MAIL_SMTP_USE_TLS,
14+
MAIL_SMTP_CIPHERS
15+
} = process.env
16+
if (MAIL_SMTP_URL) {
17+
const oldVars = [
18+
MAIL_SMTP_HOST,
19+
MAIL_SMTP_PORT,
20+
MAIL_SMTP_USER,
21+
MAIL_SMTP_PASSWORD,
22+
MAIL_SMTP_USE_TLS,
23+
MAIL_SMTP_CIPHERS
24+
]
25+
const usedOldVars = oldVars.filter(isNotNull)
26+
if (usedOldVars.length > 0) {
27+
console.warn(
28+
`Using MAIL_SMTP_URL. The following ENV Vars are ignored and can be removed: ${usedOldVars.join(', ')}`
29+
)
30+
}
31+
return MAIL_SMTP_URL
32+
}
33+
return {
734
host: process.env.MAIL_SMTP_HOST,
835
port: Number(process.env.MAIL_SMTP_PORT) || 0,
936
auth: process.env.MAIL_SMTP_USER
@@ -23,7 +50,24 @@ export default class MailManagerSMTP extends MailManager {
2350
ciphers: process.env.MAIL_SMTP_CIPHERS
2451
}
2552
: undefined
26-
})
53+
}
54+
}
55+
56+
if (process.env.MAIL_SMTP_DEBUG === 'true') {
57+
const verifyTransport = async () => {
58+
const manager = new MailManagerSMTP()
59+
try {
60+
await manager.transport.verify()
61+
console.log('SMTP Verification Complete. You may safely remove ENV Var MAIL_SMTP_DEBUG')
62+
} catch (err) {
63+
console.error('SMTP Verification Failed', err)
64+
}
65+
}
66+
verifyTransport()
67+
}
68+
69+
export default class MailManagerSMTP extends MailManager {
70+
transport = nodemailer.createTransport(composeConfig())
2771

2872
async sendEmail(options: MailManagerOptions) {
2973
const {subject, body, to, attachments, html} = options

packages/server/package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@
9696
"jsdom": "^20.0.0",
9797
"jsonwebtoken": "^9.0.0",
9898
"lib0": "^0.2.114",
99-
"mailcomposer": "^4.0.1",
10099
"mailgun.js": "^9.3.0",
101100
"md-to-adf": "^0.6.4",
102101
"mime-types": "^2.1.16",
@@ -105,7 +104,7 @@
105104
"node-env-flag": "0.1.0",
106105
"node-html-markdown-cloudflare": "^1.3.0",
107106
"node-html-parser": "^7.0.1",
108-
"nodemailer": "^7.0.9",
107+
"nodemailer": "^7.0.10",
109108
"oauth-1.0a": "^2.2.6",
110109
"object-hash": "^3.0.0",
111110
"oy-vey": "^0.12.1",

pnpm-lock.yaml

Lines changed: 5 additions & 73 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)