smtp-fetch
Advanced tools
Comparing version 1.0.3 to 1.0.4
@@ -1,34 +0,4 @@ | ||
/// <reference types="node" /> | ||
/// <reference types="node" /> | ||
import net from "net"; | ||
import tls from "tls"; | ||
export type ISocket = net.Socket | tls.TLSSocket; | ||
export type IExtension = { | ||
[key: string]: string; | ||
}; | ||
export type IResponse = { | ||
code: number; | ||
message: string; | ||
}; | ||
export default class SMTP { | ||
private readonly host; | ||
private readonly port; | ||
private tls; | ||
private localName; | ||
private socket; | ||
private ext; | ||
private auth; | ||
private didHello; | ||
constructor(host: string, port: number, tls?: boolean, localName?: string); | ||
connect(options?: {}): Promise<IResponse>; | ||
close(): void; | ||
cmd(expectCode: number, format: string, ...args: any[]): Promise<IResponse>; | ||
verify(addr: string): Promise<IResponse>; | ||
noop(): Promise<IResponse>; | ||
hello(name?: string): Promise<void>; | ||
helo(name?: string): Promise<IResponse>; | ||
ehlo(name?: string): Promise<IResponse>; | ||
quit(): Promise<IResponse>; | ||
private parseCodeLine; | ||
} | ||
export { default as Client } from "./core/client"; | ||
export * from "./core/client"; | ||
export * from "./core/errors"; | ||
//# sourceMappingURL=index.d.ts.map |
"use strict"; | ||
var __assign = (this && this.__assign) || function () { | ||
__assign = Object.assign || function(t) { | ||
for (var s, i = 1, n = arguments.length; i < n; i++) { | ||
s = arguments[i]; | ||
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) | ||
t[p] = s[p]; | ||
} | ||
return t; | ||
}; | ||
return __assign.apply(this, arguments); | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (g && (g = 0, op[0] && (_ = 0)), _) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); | ||
}; | ||
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -62,225 +20,7 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var util_1 = __importDefault(require("util")); | ||
var net_1 = __importDefault(require("net")); | ||
var tls_1 = __importDefault(require("tls")); | ||
var debug_1 = __importDefault(require("debug")); | ||
var error_1 = require("./error"); | ||
var log = (0, debug_1.default)("smtp"); | ||
var SMTP = /** @class */ (function () { | ||
function SMTP(host, port, tls, localName) { | ||
if (tls === void 0) { tls = false; } | ||
if (localName === void 0) { localName = "localhost"; } | ||
this.host = host; | ||
this.port = port; | ||
this.tls = tls; | ||
this.localName = localName; | ||
this.ext = {}; | ||
this.auth = []; | ||
this.didHello = false; | ||
} | ||
SMTP.prototype.connect = function (options) { | ||
var _this = this; | ||
if (options === void 0) { options = {}; } | ||
var select = (this.tls ? tls_1.default.connect : net_1.default.connect); | ||
this.socket = select(__assign({ port: this.port, host: this.host }, options)); | ||
return new Promise(function (resolve, reject) { | ||
_this.socket.on("connect", function () { | ||
_this.socket.once("data", function (data) { | ||
try { | ||
log("connect: " + data.toString()); | ||
resolve(_this.parseCodeLine(data.toString(), 220)); | ||
} | ||
catch (err) { | ||
log("connect error: " + err.message); | ||
reject(err); | ||
} | ||
}); | ||
}); | ||
_this.socket.on("timeout", function () { | ||
log("timeout error"); | ||
_this.socket.emit("error", new error_1.SMTPError("timeout")); | ||
}); | ||
_this.socket.on("error", function (err) { | ||
log("connect error: " + err); | ||
reject(err); | ||
}); | ||
}); | ||
}; | ||
// Close closes the connection. | ||
SMTP.prototype.close = function () { | ||
if (!this.socket) { | ||
throw new error_1.SMTPServerDisconnected("please run connect() first"); | ||
} | ||
this.socket.destroy(); | ||
this.socket = null; | ||
}; | ||
SMTP.prototype.cmd = function (expectCode, format) { | ||
var _this = this; | ||
var args = []; | ||
for (var _i = 2; _i < arguments.length; _i++) { | ||
args[_i - 2] = arguments[_i]; | ||
} | ||
if (!this.socket) { | ||
throw new error_1.SMTPServerDisconnected("please run connect() first"); | ||
} | ||
var line = util_1.default.format.apply(util_1.default, __spreadArray(["".concat(format, "\r\n")], args, false)); | ||
return new Promise(function (resolve) { | ||
log(">> " + line); | ||
_this.socket.write(line, "utf-8", function () { | ||
_this.socket.once("data", function (data) { | ||
resolve(_this.parseCodeLine(data.toString(), expectCode)); | ||
}); | ||
}); | ||
}); | ||
}; | ||
SMTP.prototype.verify = function (addr) { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
// ehlo or ehlo first | ||
return [4 /*yield*/, this.hello()]; | ||
case 1: | ||
// ehlo or ehlo first | ||
_a.sent(); | ||
return [2 /*return*/, this.cmd(250, "VRFY %s", addr)]; | ||
} | ||
}); | ||
}); | ||
}; | ||
SMTP.prototype.noop = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
// ehlo or ehlo first | ||
return [4 /*yield*/, this.hello()]; | ||
case 1: | ||
// ehlo or ehlo first | ||
_a.sent(); | ||
return [2 /*return*/, this.cmd(250, "NOOP")]; | ||
} | ||
}); | ||
}); | ||
}; | ||
// hello runs a hello exchange if needed. | ||
SMTP.prototype.hello = function (name) { | ||
if (name === void 0) { name = "hi"; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var resp; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
if (!!this.didHello) return [3 /*break*/, 3]; | ||
this.didHello = true; | ||
return [4 /*yield*/, this.ehlo(name)]; | ||
case 1: | ||
resp = _a.sent(); | ||
if (!!(200 <= resp.code && resp.code < 300)) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, this.helo(name)]; | ||
case 2: | ||
resp = _a.sent(); | ||
if (!(200 <= resp.code && resp.code < 300)) { | ||
throw new error_1.SMTPError("smtp hello error: " + resp); | ||
} | ||
_a.label = 3; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
// helo sends the HELO greeting to the server. It should be used only when the | ||
// server does not support ehlo. | ||
SMTP.prototype.helo = function (name) { | ||
if (name === void 0) { name = "hi"; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
return [2 /*return*/, this.cmd(220, "HELO %s", name || this.localName)]; | ||
}); | ||
}); | ||
}; | ||
// ehlo sends the EHLO (extended hello) greeting to the server. It | ||
// should be the preferred greeting for servers that support it. | ||
SMTP.prototype.ehlo = function (name) { | ||
if (name === void 0) { name = "hi"; } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _a, code, message, ext, extList, _i, extList_1, line, _b, k, v; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: return [4 /*yield*/, this.cmd(250, "EHLO %s", name || this.localName)]; | ||
case 1: | ||
_a = _c.sent(), code = _a.code, message = _a.message; | ||
ext = {}; | ||
extList = message.split("\n"); | ||
if (extList.length > 1) { | ||
if (extList.length > 1) { | ||
extList.shift(); // remove first line | ||
for (_i = 0, extList_1 = extList; _i < extList_1.length; _i++) { | ||
line = extList_1[_i]; | ||
_b = line.split(" "), k = _b[0], v = _b.slice(1); | ||
ext[k] = v.join(" "); | ||
} | ||
} | ||
if (this.ext["AUTH"]) { | ||
this.auth = this.ext["AUTH"].split(" "); | ||
} | ||
this.ext = ext; | ||
} | ||
return [2 /*return*/, { code: code, message: message }]; | ||
} | ||
}); | ||
}); | ||
}; | ||
// StartTLS sends the STARTTLS command and encrypts all further communication. | ||
// Only servers that advertise the STARTTLS extension support this function. | ||
// public async startTLS(tlsOptions = {}): Promise<IResponse> { | ||
// // ehlo or ehlo first | ||
// await this.hello(); | ||
// const { code, message } = await this.cmd(220, "STARTTLS"); | ||
// this.tls = true; | ||
// await this.connect(); | ||
// return this.ehlo(); | ||
// } | ||
// public async login(user: string, password: string): Promise<IResponse> {} | ||
// public async sendMail( | ||
// from: string, | ||
// to: string, | ||
// msg: string | ||
// ): Promise<IResponse> {} | ||
// Quit sends QUIT command and closes the connection to the server. | ||
SMTP.prototype.quit = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
// ehlo or ehlo first | ||
return [4 /*yield*/, this.hello()]; | ||
case 1: | ||
// ehlo or ehlo first | ||
_a.sent(); | ||
return [2 /*return*/, this.cmd(221, "QUIT")]; | ||
} | ||
}); | ||
}); | ||
}; | ||
SMTP.prototype.parseCodeLine = function (reply, expectCode) { | ||
var lines = reply.split("\r\n"); | ||
var code; | ||
var resp = []; | ||
for (var _i = 0, lines_1 = lines; _i < lines_1.length; _i++) { | ||
var line = lines_1[_i]; | ||
resp.push(line.substring(4).trim()); | ||
code = parseInt(line.substring(0, 3), 10); | ||
if (line.substring(3, 4) != "-") { | ||
break; | ||
} | ||
} | ||
if (expectCode !== code) { | ||
throw new error_1.SMTPError("unexpected code: " + code); | ||
} | ||
return { code: code, message: resp.join("\n") }; | ||
}; | ||
return SMTP; | ||
}()); | ||
exports.default = SMTP; | ||
exports.Client = void 0; | ||
var client_1 = require("./core/client"); | ||
Object.defineProperty(exports, "Client", { enumerable: true, get: function () { return __importDefault(client_1).default; } }); | ||
__exportStar(require("./core/client"), exports); | ||
__exportStar(require("./core/errors"), exports); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "smtp-fetch", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"main": "dist/index.js", | ||
@@ -5,0 +5,0 @@ "types": "dist/index.d.ts", |
200
src/index.ts
@@ -1,197 +0,3 @@ | ||
import util from "util"; | ||
import net from "net"; | ||
import tls from "tls"; | ||
import debug from "debug"; | ||
import { SMTPError, SMTPServerDisconnected } from "./error"; | ||
const log = debug("smtp"); | ||
export type ISocket = net.Socket | tls.TLSSocket; | ||
export type IExtension = { [key: string]: string }; | ||
export type IResponse = { code: number; message: string }; | ||
export default class SMTP { | ||
// A Client represents a client connection to an SMTP server. | ||
private socket: ISocket | undefined; | ||
private ext: IExtension | undefined = {}; | ||
private auth: string[] | undefined = []; | ||
private didHello: boolean = false; | ||
constructor( | ||
private readonly host: string, | ||
private readonly port: number, | ||
private tls: boolean = false, | ||
private localName = "localhost" | ||
) {} | ||
public connect(options = {}): Promise<IResponse> { | ||
const select = (this.tls ? tls.connect : net.connect) as Function; | ||
this.socket = select({ port: this.port, host: this.host, ...options }); | ||
return new Promise((resolve, reject) => { | ||
this.socket.on("connect", () => { | ||
this.socket.once("data", (data) => { | ||
try { | ||
log("connect: " + data.toString()); | ||
resolve(this.parseCodeLine(data.toString(), 220)); | ||
} catch (err) { | ||
log("connect error: " + err.message); | ||
reject(err); | ||
} | ||
}); | ||
}); | ||
this.socket.on("timeout", () => { | ||
log("timeout error"); | ||
this.socket.emit("error", new SMTPError("timeout")); | ||
}); | ||
this.socket.on("error", (err) => { | ||
log("connect error: " + err); | ||
reject(err); | ||
}); | ||
}); | ||
} | ||
// Close closes the connection. | ||
public close() { | ||
if (!this.socket) { | ||
throw new SMTPServerDisconnected("please run connect() first"); | ||
} | ||
this.socket.destroy(); | ||
this.socket = null; | ||
} | ||
public cmd( | ||
expectCode: number, | ||
format: string, | ||
...args: any[] | ||
): Promise<IResponse> { | ||
if (!this.socket) { | ||
throw new SMTPServerDisconnected("please run connect() first"); | ||
} | ||
const line = util.format(`${format}\r\n`, ...args); | ||
return new Promise((resolve) => { | ||
log(">> " + line); | ||
this.socket.write(line, "utf-8", () => { | ||
this.socket.once("data", (data) => { | ||
resolve(this.parseCodeLine(data.toString(), expectCode)); | ||
}); | ||
}); | ||
}); | ||
} | ||
public async verify(addr: string): Promise<IResponse> { | ||
// ehlo or ehlo first | ||
await this.hello(); | ||
return this.cmd(250, "VRFY %s", addr); | ||
} | ||
public async noop(): Promise<IResponse> { | ||
// ehlo or ehlo first | ||
await this.hello(); | ||
return this.cmd(250, "NOOP"); | ||
} | ||
// hello runs a hello exchange if needed. | ||
public async hello(name: string = "hi") { | ||
if (!this.didHello) { | ||
this.didHello = true; | ||
let resp = await this.ehlo(name); | ||
if (!(200 <= resp.code && resp.code < 300)) { | ||
resp = await this.helo(name); | ||
if (!(200 <= resp.code && resp.code < 300)) { | ||
throw new SMTPError("smtp hello error: " + resp); | ||
} | ||
} | ||
} | ||
} | ||
// helo sends the HELO greeting to the server. It should be used only when the | ||
// server does not support ehlo. | ||
public async helo(name: string = "hi"): Promise<IResponse> { | ||
return this.cmd(220, "HELO %s", name || this.localName); | ||
} | ||
// ehlo sends the EHLO (extended hello) greeting to the server. It | ||
// should be the preferred greeting for servers that support it. | ||
public async ehlo(name: string = "hi"): Promise<IResponse> { | ||
const { code, message } = await this.cmd( | ||
250, | ||
"EHLO %s", | ||
name || this.localName | ||
); | ||
const ext = {}; | ||
const extList = message.split("\n"); | ||
if (extList.length > 1) { | ||
if (extList.length > 1) { | ||
extList.shift(); // remove first line | ||
for (const line of extList) { | ||
const [k, ...v] = line.split(" "); | ||
ext[k] = v.join(" "); | ||
} | ||
} | ||
if (this.ext["AUTH"]) { | ||
this.auth = this.ext["AUTH"].split(" "); | ||
} | ||
this.ext = ext; | ||
} | ||
return { code, message }; | ||
} | ||
// StartTLS sends the STARTTLS command and encrypts all further communication. | ||
// Only servers that advertise the STARTTLS extension support this function. | ||
// public async startTLS(tlsOptions = {}): Promise<IResponse> { | ||
// // ehlo or ehlo first | ||
// await this.hello(); | ||
// const { code, message } = await this.cmd(220, "STARTTLS"); | ||
// this.tls = true; | ||
// await this.connect(); | ||
// return this.ehlo(); | ||
// } | ||
// public async login(user: string, password: string): Promise<IResponse> {} | ||
// public async sendMail( | ||
// from: string, | ||
// to: string, | ||
// msg: string | ||
// ): Promise<IResponse> {} | ||
// Quit sends QUIT command and closes the connection to the server. | ||
public async quit(): Promise<IResponse> { | ||
// ehlo or ehlo first | ||
await this.hello(); | ||
return this.cmd(221, "QUIT"); | ||
} | ||
private parseCodeLine(reply: string, expectCode: number): IResponse { | ||
const lines = reply.split("\r\n"); | ||
let code: number; | ||
const resp = []; | ||
for (const line of lines) { | ||
resp.push(line.substring(4).trim()); | ||
code = parseInt(line.substring(0, 3), 10); | ||
if (line.substring(3, 4) != "-") { | ||
break; | ||
} | ||
} | ||
if (expectCode !== code) { | ||
throw new SMTPError("unexpected code: " + code); | ||
} | ||
return { code, message: resp.join("\n") }; | ||
} | ||
} | ||
export { default as Client } from "./core/client"; | ||
export * from "./core/client"; | ||
export * from "./core/errors"; |
import * as net from "net"; | ||
import SMTP from "../src/index"; | ||
import { SMTPError } from "../src/error"; | ||
import { Client, SMTPError } from "../src/index"; | ||
@@ -23,6 +22,6 @@ type IMockServer = net.Server & { start: Function; stop: Function }; | ||
let server: IMockServer; | ||
let client: SMTP; | ||
let client: Client; | ||
beforeEach(() => { | ||
client = new SMTP("127.0.0.1", PORT); | ||
client = new Client("127.0.0.1", PORT); | ||
}); | ||
@@ -29,0 +28,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
39218
20
631
3