Skip to content

Commit

Permalink
refactor: add some methods to reuse code; in DATA mode don't await (#47)
Browse files Browse the repository at this point in the history
  • Loading branch information
mathe42 authored Oct 21, 2022
1 parent 70d464b commit be8fbc0
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 77 deletions.
132 changes: 55 additions & 77 deletions client/basic/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { QUE } from "./QUE.ts";

const CommandCode = {
READY: 220,
AUTHO_NEXT: 334,
AUTHO_SUCCESS: 235,
OK: 250,
BEGIN_DATA: 354,
Expand Down Expand Up @@ -58,102 +59,90 @@ export class SMTPClient {
try {
await this.#que.que();

await this.#connection.writeCmd("MAIL", "FROM:", `<${config.from.mail}>`);
this.#connection.assertCode(
await this.#connection.readCmd(),
await this.#connection.writeCmdAndAssert(
CommandCode.OK,
"MAIL",
"FROM:",
`<${config.from.mail}>`,
);

for (let i = 0; i < config.to.length; i++) {
await this.#connection.writeCmd(
await this.#connection.writeCmdAndAssert(
CommandCode.OK,
"RCPT",
"TO:",
`<${config.to[i].mail}>`,
);
this.#connection.assertCode(
await this.#connection.readCmd(),
CommandCode.OK,
);
}

for (let i = 0; i < config.cc.length; i++) {
await this.#connection.writeCmd(
await this.#connection.writeCmdAndAssert(
CommandCode.OK,
"RCPT",
"TO:",
`<${config.cc[i].mail}>`,
);
this.#connection.assertCode(
await this.#connection.readCmd(),
CommandCode.OK,
);
}

for (let i = 0; i < config.bcc.length; i++) {
await this.#connection.writeCmd(
await this.#connection.writeCmdAndAssert(
CommandCode.OK,
"RCPT",
"TO:",
`<${config.bcc[i].mail}>`,
);
this.#connection.assertCode(
await this.#connection.readCmd(),
CommandCode.OK,
);
}

dataMode = true;
await this.#connection.writeCmd("DATA");
this.#connection.assertCode(
await this.#connection.readCmd(),
CommandCode.BEGIN_DATA,
);
await this.#connection.writeCmdAndAssert(CommandCode.BEGIN_DATA, "DATA");

await this.#connection.writeCmd("Subject: ", config.subject);
await this.#connection.writeCmd(
this.#connection.writeCmd("Subject: ", config.subject);
this.#connection.writeCmd(
"From: ",
`${config.from.name} <${config.from.mail}>`,
);
if (config.to.length > 0) {
await this.#connection.writeCmd(
this.#connection.writeCmd(
"To: ",
config.to.map((m) => `${m.name} <${m.mail}>`).join(";"),
);
}
if (config.cc.length > 0) {
await this.#connection.writeCmd(
this.#connection.writeCmd(
"Cc: ",
config.cc.map((m) => `${m.name} <${m.mail}>`).join(";"),
);
}

await this.#connection.writeCmd("Date: ", config.date);
this.#connection.writeCmd("Date: ", config.date);

const obj = Object.entries(config.headers);

for (let i = 0; i < obj.length; i++) {
const [name, value] = obj[i];
await this.#connection.writeCmd(name + ": ", value);
this.#connection.writeCmd(name + ": ", value);
}

if (config.inReplyTo) {
await this.#connection.writeCmd("InReplyTo: ", config.inReplyTo);
this.#connection.writeCmd("InReplyTo: ", config.inReplyTo);
}

if (config.references) {
await this.#connection.writeCmd("Refrences: ", config.references);
this.#connection.writeCmd("Refrences: ", config.references);
}

if (config.replyTo) {
await this.#connection.writeCmd(
this.#connection.writeCmd(
"ReplyTo: ",
`${config.replyTo.name} <${config.replyTo.name}>`,
);
}

if (config.priority) {
await this.#connection.writeCmd("Priority:", config.priority);
this.#connection.writeCmd("Priority:", config.priority);
}

await this.#connection.writeCmd("MIME-Version: 1.0");
this.#connection.writeCmd("MIME-Version: 1.0");

let boundaryAdditionAtt = 100;
// calc msg boundary
Expand Down Expand Up @@ -187,11 +176,11 @@ export class SMTPClient {

const attachmentBoundary = `attachment${boundaryAdditionAtt}`;

await this.#connection.writeCmd(
this.#connection.writeCmd(
`Content-Type: multipart/mixed; boundary=${attachmentBoundary}`,
"\r\n",
);
await this.#connection.writeCmd(`--${attachmentBoundary}`);
this.#connection.writeCmd(`--${attachmentBoundary}`);

let boundaryAddition = 100;
// calc msg boundary
Expand All @@ -207,54 +196,54 @@ export class SMTPClient {

const messageBoundary = `message${boundaryAddition}`;

await this.#connection.writeCmd(
this.#connection.writeCmd(
`Content-Type: multipart/alternative; boundary=${messageBoundary}`,
"\r\n",
);

for (let i = 0; i < config.mimeContent.length; i++) {
await this.#connection.writeCmd(`--${messageBoundary}`);
await this.#connection.writeCmd(
this.#connection.writeCmd(`--${messageBoundary}`);
this.#connection.writeCmd(
"Content-Type: " + config.mimeContent[i].mimeType,
);
if (config.mimeContent[i].transferEncoding) {
await this.#connection.writeCmd(
this.#connection.writeCmd(
`Content-Transfer-Encoding: ${
config.mimeContent[i].transferEncoding
}` + "\r\n",
);
} else {
// Send new line
await this.#connection.writeCmd("");
this.#connection.writeCmd("");
}

await this.#connection.writeCmd(config.mimeContent[i].content, "\r\n");
this.#connection.writeCmd(config.mimeContent[i].content, "\r\n");
}

await this.#connection.writeCmd(`--${messageBoundary}--\r\n`);
this.#connection.writeCmd(`--${messageBoundary}--\r\n`);

for (let i = 0; i < config.attachments.length; i++) {
const attachment = config.attachments[i];

await this.#connection.writeCmd(`--${attachmentBoundary}`);
await this.#connection.writeCmd(
this.#connection.writeCmd(`--${attachmentBoundary}`);
this.#connection.writeCmd(
"Content-Type:",
attachment.contentType + ";",
"name=" + attachment.filename,
);

if (attachment.contentID) {
await this.#connection.writeCmd(
this.#connection.writeCmd(
`Content-ID: <${attachment.contentID}>`,
);
}

await this.#connection.writeCmd(
this.#connection.writeCmd(
"Content-Disposition: attachment; filename=" + attachment.filename,
);

if (attachment.encoding === "base64") {
await this.#connection.writeCmd(
this.#connection.writeCmd(
"Content-Transfer-Encoding: base64",
"\r\n",
);
Expand All @@ -269,7 +258,7 @@ export class SMTPClient {
(line + 1) * 75,
);

await this.#connection.writeCmd(lineOfBase64);
this.#connection.writeCmd(lineOfBase64);
}

// if (
Expand All @@ -283,25 +272,22 @@ export class SMTPClient {
// await this.#connection.writeCmdBinary(attachment.content);
// }

await this.#connection.writeCmd("\r\n");
this.#connection.writeCmd("\r\n");
} else if (attachment.encoding === "text") {
await this.#connection.writeCmd(
this.#connection.writeCmd(
"Content-Transfer-Encoding: quoted-printable",
"\r\n",
);

await this.#connection.writeCmd(attachment.content, "\r\n");
this.#connection.writeCmd(attachment.content, "\r\n");
}
}

await this.#connection.writeCmd(`--${attachmentBoundary}--\r\n`);
this.#connection.writeCmd(`--${attachmentBoundary}--\r\n`);

await this.#connection.writeCmd(".\r\n");
// Wait for all writes to finish
await this.#connection.writeCmdAndAssert(CommandCode.OK, ".\r\n");

this.#connection.assertCode(
await this.#connection.readCmd(),
CommandCode.OK,
);
dataMode = false;
await this.#cleanup();
this.#que.next();
Expand Down Expand Up @@ -342,21 +328,15 @@ export class SMTPClient {
if (
this.#supportedFeatures.has("STARTTLS") && !this.config.debug.noStartTLS
) {
await this.#connection.writeCmd("STARTTLS");
this.#connection.assertCode(
await this.#connection.readCmd(),
CommandCode.READY,
);
this.#connection.writeCmdAndAssert(CommandCode.READY, "STARTTLS");

const conn = await Deno.startTls(this.#connection.conn, {
hostname: this.config.connection.hostname,
});
this.#connection = new SMTPConnection(conn, this.config);
this.secure = true;

await this.#connection.writeCmd("EHLO", this.config.connection.hostname);

await this.#connection.readCmd();
this.#connection.writeCmdAndRead("EHLO", this.config.connection.hostname);
}

if (!this.config.debug.allowUnsecure && !this.secure) {
Expand All @@ -368,20 +348,18 @@ export class SMTPClient {
}

if (this.config.connection.auth) {
await this.#connection.writeCmd("AUTH", "LOGIN");
this.#connection.assertCode(await this.#connection.readCmd(), 334);

await this.#connection.writeCmd(
btoa(this.config.connection.auth.username),
await this.#connection.writeCmdAndAssert(
CommandCode.AUTHO_NEXT,
"AUTH",
"LOGIN",
);
this.#connection.assertCode(await this.#connection.readCmd(), 334);

await this.#connection.writeCmd(
btoa(this.config.connection.auth.password),
await this.#connection.writeCmdAndAssert(
CommandCode.AUTHO_NEXT,
btoa(this.config.connection.auth.username),
);
this.#connection.assertCode(
await this.#connection.readCmd(),
await this.#connection.writeCmdAndAssert(
CommandCode.AUTHO_SUCCESS,
btoa(this.config.connection.auth.password),
);
}

Expand Down
11 changes: 11 additions & 0 deletions client/basic/connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,15 @@ export class SMTPConnection {

return this.write(args);
}

public async writeCmdAndRead(...args: string[]) {
await this.writeCmd(...args);
return this.readCmd();
}

public async writeCmdAndAssert(code: number, ...args: string[]) {
const res = await this.writeCmdAndRead(...args);
this.assertCode(res, code);
return res;
}
}

0 comments on commit be8fbc0

Please sign in to comment.