Skip to content

Commit

Permalink
Merge pull request #26 from JimiC/starttls_support
Browse files Browse the repository at this point in the history
Add support for STARTTLS
  • Loading branch information
dangrie158 authored Nov 23, 2024
2 parents d3a0af9 + 68c7450 commit 6201a13
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
8 changes: 5 additions & 3 deletions lib/notifiers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SmtpClient } from "./smtp.ts";
import { ConnectConfigWithAuthentication, SmtpClient } from "./smtp.ts";
import { getLogger } from "@std/log";
import { DockerApiContainerEvent } from "./docker-api.ts";
import { CheckedConfiguration, ConfigOption } from "./env.ts";
Expand Down Expand Up @@ -107,8 +107,10 @@ export class SmtpNotifier extends Notifier {
port: SmtpNotifier.config.port,
username: SmtpNotifier.config.username,
password: SmtpNotifier.config.password,
};
if (SmtpNotifier.config.use_tls) {
} as ConnectConfigWithAuthentication;
if (!SmtpNotifier.config.use_tls && connection_config.username !== undefined) {
await client.connect_starttls(connection_config);
} else if (SmtpNotifier.config.use_tls) {
await client.connect_tls(connection_config);
} else {
await client.connect_plain(connection_config);
Expand Down
35 changes: 34 additions & 1 deletion lib/smtp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type ConnectConfig = {
port?: number;
};

type ConnectConfigWithAuthentication = ConnectConfig & {
export type ConnectConfigWithAuthentication = ConnectConfig & {
username: string;
password: string;
};
Expand Down Expand Up @@ -64,6 +64,14 @@ export class SmtpClient {
await this.connect(connection, config);
}

async connect_starttls(config: ConnectConfigWithAuthentication) {
const connection = await Deno.connect({
hostname: config.hostname,
port: config.port || 587,
});
await this.connect(connection, config);
}

private async connect(connection: Deno.Conn, config: ConnectConfig) {
this.connection = connection;
this.reader = this.connection.readable
Expand All @@ -74,11 +82,32 @@ export class SmtpClient {
this.assert_code(await this.read_command(), CommandCode.READY);

await this.write_command(`EHLO ${config.hostname}\r\n`);

let supports_starttls = false;

while (true) {
const command = await this.read_command();
if (!command || !command.args.startsWith("-")) break;
if (command.args.includes("STARTTLS")) {
supports_starttls = true;
}
}

if (this.use_authentication(config)) {
if (!this.is_tls_conn(this.connection)) {
if (!supports_starttls) {
throw new Error("STARTTLS is not supported by the server");
}
await this.write_command(`STARTTLS\r\n`);
this.assert_code(await this.read_command(), CommandCode.READY);
this.reader.cancel();
this.connection = await Deno.startTls(this.connection as Deno.TcpConn, { hostname: config.hostname });
this.reader = this.connection.readable
.pipeThrough(new TextDecoderStream())
.pipeThrough(new TextLineStream())
.getReader();
}

await this.write_command(`AUTH LOGIN\r\n`);
this.assert_code(await this.read_command(), CommandCode.SERVER_CHALLENGE);

Expand All @@ -90,6 +119,10 @@ export class SmtpClient {
}
}

is_tls_conn(arg: Deno.Conn): arg is Deno.TlsConn {
return (arg as Deno.TlsConn).handshake !== undefined;
}

close() {
if (!this.connection) {
return;
Expand Down

0 comments on commit 6201a13

Please sign in to comment.