Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

πŸ› Bug Report β€” Runtime APIs cloudflare:sockets - Unable to use startTls for SMTP #2712

Open
manybond opened this issue Sep 14, 2024 · 0 comments

Comments

@manybond
Copy link

manybond commented Sep 14, 2024

Hey all, been having an issue getting startTls working with sockets. This issue has been going on a while now, so I'll break it down into a few scenarios. In all these examples, I am running the API from cloudflare workers, while the website is hosted with pages.

  1. Tried sending an SMTP message to smtp.protonmail.ch on port 587 using startTls. Was weirdly unable to get it to work. For this use case, protonmail allowed communication on port 465 with { secureTransport: 'on' } (TLS enabled). It worked beautifully, so I forgot about it and moved on.
  2. This go around, using outlook smtp-mail.outlook.com which isn't playing nicely on port 465. Documentation requires explicit startTls on 587.
  3. The reproducible example attached, using the https://ethereal.email/ service to communicate with. Same issues - no dice with startTls().

I'll preface this with the fact that I don't have a deep understanding of TCP or TLS. My best guess at the moment is that I simply have something misconfigured (DNS/certificate related most likely). But I'm reaching the point where I've tried seemingly every permutation of settings / DNS records / code with nothing to show for it.

Here's the sample code snippet which I'm calling from within a route on my worker:

export async function testEmail(env: Env) {
	const encoder = new TextEncoder()
	const decoder = new TextDecoder()
        
        // Using service https://ethereal.email/ for a test SMTP server
	const socket = connect({ hostname: env.SMTP_HOST, port: 587 }, { secureTransport: 'starttls' })
	
        // Socket does not hang
	await socket.opened
	const writer = socket.writable.getWriter()
	const reader = socket.readable.getReader()
	async function writeAndRead(command: string, writer: any, reader: any) {
		console.log(`Sending: ${command.trim()}`)
		// In practice this is not needed, but with ethereal, I receive
		// 421 smtp.ethereal.email You talk too soon without a delay
		await new Promise((resolve) => {setTimeout(resolve, 500)})
		await writer.write(encoder.encode(command))
		const { value } = await reader.read()
		const response = decoder.decode(value)
		console.log(`Response: ${response.trim()}`)
		return response
	}

	// On insecure socket, these have no issues.
	await writeAndRead('EHLO domain.com\r\n', writer, reader)
	await writeAndRead('STARTTLS\r\n', writer, reader)

	/**
         * Have tried moving these before and after startTls call
	 * Before startTls() => This WritableStream writer has been released
	 * After  startTls() => This WritableStream is currently locked to a writer
	 */
	writer.releaseLock()
	await writer.close()

	const secureSocket = socket.startTls()
	// This call hangs, albeit unsure if it's needed/valid to call.
	// await secureSocket.opened

	const secureWriter = secureSocket.writable.getWriter()
	const secureReader = secureSocket.readable.getReader()

	//  Will error out (After)
	await writeAndRead('EHLO domain.com\r\n', secureWriter, secureReader)
}

Finally, just to dig into the settings for DNS and cloudflare TLS:

Redacted DNS
image

Custom SSL/TLS set to Full (Strict) although tried with flexible & full
Always Use HTTPS: Enabled
Minimum TLS version: Currently 1.1, but outlook requires >=1.2. I bumped this up sequentially during testing and no luck.
TLS 1.3: Enabled
Automatic HTTPS Rewrites: Enabled
Authenticated Origin Pulls: Disabled

Again, unsure if this is entirely a bug, but I'm at wit's end. At the very least, I'd recommend a logging improvement to help track down the error πŸ˜…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant