milter 2.0.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +593 -121
- package/dist/constants.cjs +105 -0
- package/dist/constants.cjs.map +1 -0
- package/dist/constants.d.cts +63 -0
- package/dist/constants.d.ts +63 -0
- package/dist/constants.js +73 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.cjs +976 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +187 -0
- package/dist/index.d.ts +187 -0
- package/dist/index.js +914 -0
- package/dist/index.js.map +1 -0
- package/package.json +116 -22
- package/res/maail-logo.svg +11 -0
- package/res/milterjs-logo.svg +79 -0
- package/.npmignore +0 -7
- package/binding.gyp +0 -13
- package/lib/milter.js +0 -1
- package/src/envelope.cc +0 -602
- package/src/envelope.h +0 -94
- package/src/events.cc +0 -429
- package/src/events.h +0 -303
- package/src/forward.h +0 -10
- package/src/milter.cc +0 -732
- package/src/milter.h +0 -76
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/frames.ts","../src/context.ts","../src/decisions.ts","../src/dkim.ts","../src/logger.ts","../src/server.ts","../src/spf.ts","../src/utils.ts"],"sourcesContent":["export const SMFI_VERSION = 6;\n\nexport const SMFIA = {\n UNKNOWN: 'U',\n UNIX: 'L',\n INET: '4',\n INET6: '6',\n} as const;\n\nexport const SMFIC = {\n CONNECT: 'C',\n OPTNEG: 'O',\n HELO: 'H',\n HEADER: 'L',\n EOH: 'N',\n BODY: 'B',\n BODYEOB: 'E',\n MAIL: 'M',\n RCPT: 'R',\n ABORT: 'A',\n MACRO: 'D',\n QUIT: 'Q',\n DATA: 'T',\n UNKNOWN: 'U',\n} as const;\n\nexport const SMFIR = {\n ACCEPT: 'a',\n CONTINUE: 'c',\n DISCARD: 'd',\n REJECT: 'r',\n TEMPFAIL: 't',\n REPLYCODE: 'y',\n ADDRCPT: '+',\n DELRCPT: '-',\n REPLBODY: 'b',\n ADDHEADER: 'h',\n INSHEADER: 'i',\n CHGHEADER: 'm',\n PROGRESS: 'p',\n QUARANTINE: 'q',\n SETSENDER: 's',\n} as const;\n\nexport const SMFIF = {\n ADDHDRS: 0x01,\n CHGBODY: 0x02,\n ADDRCPT: 0x04,\n DELRCPT: 0x08,\n CHGHDRS: 0x10,\n QUARANTINE: 0x20,\n SETSENDER: 0x40,\n} as const;\n\nexport const ACTION_ALL\n = SMFIF.ADDHDRS\n | SMFIF.CHGBODY\n | SMFIF.ADDRCPT\n | SMFIF.DELRCPT\n | SMFIF.CHGHDRS\n | SMFIF.QUARANTINE\n | SMFIF.SETSENDER;\n\nexport const SMFIP = {\n NOCONNECT: 0x00000001,\n NOHELO: 0x00000002,\n NOMAIL: 0x00000004,\n NORCPT: 0x00000008,\n NOBODY: 0x00000010,\n NOHDRS: 0x00000020,\n NOEOH: 0x00000040,\n NONE: 0x0000007f,\n} as const;\n\nexport const DISABLE_ALL_CALLBACKS\n = SMFIP.NOCONNECT\n | SMFIP.NOHELO\n | SMFIP.NOMAIL\n | SMFIP.NORCPT\n | SMFIP.NOBODY\n | SMFIP.NOHDRS\n | SMFIP.NOEOH;\n","import type net from 'node:net';\n\nexport function frame(command: string, data: Buffer = Buffer.alloc(0)): Buffer {\n\n const len = Buffer.alloc(4);\n\n len.writeUInt32BE(data.length + 1, 0);\n return Buffer.concat([len, Buffer.from(command, 'ascii'), data]);\n}\n\nexport function send(socket: net.Socket | null, command: string, data?: Buffer): void {\n\n if (!socket) {\n return;\n }\n\n socket.write(frame(command, data ?? Buffer.alloc(0)));\n}\n","import type net from 'node:net';\n\nimport { SMFIF, SMFIR } from './constants.js';\nimport type { DkimVerifyResult } from './dkim.js';\nimport { send } from './frames.js';\nimport type { SpfResult } from './spf.js';\nimport type { ConnectInfo, MilterActionFlag, MilterPhase } from './types.js';\n\nexport class MilterActionError extends Error {\n\n readonly code: 'E_MILTER_ACTION_STAGE' | 'E_MILTER_ACTION_CAPABILITY';\n\n constructor(code: 'E_MILTER_ACTION_STAGE' | 'E_MILTER_ACTION_CAPABILITY', message: string) {\n\n super(message);\n this.name = 'MilterActionError';\n this.code = code;\n }\n}\n\nconst EOM_ONLY_PHASES = new Set<MilterPhase>(['bodyEnd']);\n\nexport class MilterContext {\n\n readonly id: number;\n private readonly collectBody: boolean;\n private readonly maxBodyBytes: number;\n private readonly enforceActionStages: boolean;\n private chunks: Buffer[] = [];\n private bodyBytes = 0;\n private phase: MilterPhase = 'connect';\n private negotiatedActions = 0;\n socket: net.Socket | null;\n headers: Record<string, string[]> = {};\n headerLines: Array<[string, string]> = [];\n macros: Record<string, Record<string, string>> = {};\n connection: ConnectInfo | null = null;\n helo: string | null = null;\n dkim: DkimVerifyResult | null = null;\n spf: SpfResult | null = null;\n from: string[] | null = null;\n to: string[] | null = null;\n\n constructor(\n id: number,\n socket: net.Socket,\n collectBody: boolean,\n maxBodyBytes: number,\n enforceActionStages: boolean,\n ) {\n\n this.id = id;\n this.socket = socket;\n this.collectBody = collectBody;\n this.maxBodyBytes = maxBodyBytes;\n this.enforceActionStages = enforceActionStages;\n }\n\n setPhase(phase: MilterPhase): void {\n\n this.phase = phase;\n }\n\n getPhase(): MilterPhase {\n\n return this.phase;\n }\n\n setNegotiatedActions(actions: number): void {\n\n this.negotiatedActions = actions >>> 0;\n }\n\n can(action: MilterActionFlag): boolean {\n\n return (this.negotiatedActions & action) === action;\n }\n\n appendHeader(name: string, value: string): void {\n\n const key = name.toLowerCase();\n\n this.headerLines.push([name, value]);\n if (!this.headers[key]) {\n this.headers[key] = [];\n }\n this.headers[key].push(value);\n }\n\n appendBody(chunk: Buffer): void {\n\n if (!this.collectBody) {\n return;\n }\n\n this.bodyBytes += chunk.length;\n if (this.bodyBytes > this.maxBodyBytes) {\n throw new Error(\n `Body limit exceeded for connection ${this.id}: ${this.bodyBytes} > ${this.maxBodyBytes}`,\n );\n }\n\n this.chunks.push(Buffer.from(chunk));\n }\n\n getBody(): Buffer {\n\n return Buffer.concat(this.chunks);\n }\n\n resetMessage(): void {\n\n this.headers = {};\n this.headerLines = [];\n this.macros = {};\n this.dkim = null;\n this.spf = null;\n this.from = null;\n this.to = null;\n this.chunks = [];\n this.bodyBytes = 0;\n this.phase = 'connect';\n }\n\n private requireAction(action: MilterActionFlag, actionName: string, phases?: ReadonlySet<MilterPhase>): void {\n\n if ((this.negotiatedActions & action) !== action) {\n throw new MilterActionError(\n 'E_MILTER_ACTION_CAPABILITY',\n `${actionName} not permitted by negotiated action flags`,\n );\n }\n\n if (this.enforceActionStages && phases && !phases.has(this.phase)) {\n throw new MilterActionError(\n 'E_MILTER_ACTION_STAGE',\n `${actionName} is not allowed during phase '${this.phase}'`,\n );\n }\n }\n\n send(command: string, data?: Buffer): void {\n\n send(this.socket, command, data);\n }\n\n continue(): void {\n\n this.send(SMFIR.CONTINUE);\n }\n\n accept(): void {\n\n this.send(SMFIR.ACCEPT);\n }\n\n reject(): void {\n\n this.send(SMFIR.REJECT);\n }\n\n discard(): void {\n\n this.send(SMFIR.DISCARD);\n }\n\n tempfail(): void {\n\n this.send(SMFIR.TEMPFAIL);\n }\n\n progress(): void {\n\n this.send(SMFIR.PROGRESS);\n }\n\n addHeader(name: string, value: string): void {\n\n this.requireAction(SMFIF.ADDHDRS, 'addHeader', EOM_ONLY_PHASES);\n this.send(SMFIR.ADDHEADER, Buffer.from(`${name}\\0${value}\\0`, 'utf8'));\n }\n\n insertHeader(index: number, name: string, value: string): void {\n\n this.requireAction(SMFIF.ADDHDRS, 'insertHeader', EOM_ONLY_PHASES);\n\n const suffix = Buffer.from(`${name}\\0${value}\\0`, 'utf8');\n const data = Buffer.alloc(4 + suffix.length);\n\n data.writeUInt32BE(index >>> 0, 0);\n suffix.copy(data, 4);\n this.send(SMFIR.INSHEADER, data);\n }\n\n changeHeader(name: string, index: number, value = ''): void {\n\n this.requireAction(SMFIF.CHGHDRS, 'changeHeader', EOM_ONLY_PHASES);\n\n const suffix = Buffer.from(`${name}\\0${value}\\0`, 'utf8');\n const data = Buffer.alloc(4 + suffix.length);\n\n data.writeUInt32BE(index >>> 0, 0);\n suffix.copy(data, 4);\n this.send(SMFIR.CHGHEADER, data);\n }\n\n addRecipient(address: string): void {\n\n this.requireAction(SMFIF.ADDRCPT, 'addRecipient', EOM_ONLY_PHASES);\n this.send(SMFIR.ADDRCPT, Buffer.from(`${address}\\0`, 'utf8'));\n }\n\n deleteRecipient(address: string): void {\n\n this.requireAction(SMFIF.DELRCPT, 'deleteRecipient', EOM_ONLY_PHASES);\n this.send(SMFIR.DELRCPT, Buffer.from(`${address}\\0`, 'utf8'));\n }\n\n replaceBody(chunk: Buffer | string): void {\n\n this.requireAction(SMFIF.CHGBODY, 'replaceBody', EOM_ONLY_PHASES);\n\n const payload = typeof chunk === 'string' ? Buffer.from(chunk, 'utf8') : chunk;\n\n this.send(SMFIR.REPLBODY, payload);\n }\n\n quarantine(reason = ''): void {\n\n this.requireAction(SMFIF.QUARANTINE, 'quarantine', EOM_ONLY_PHASES);\n this.send(SMFIR.QUARANTINE, Buffer.from(`${reason}\\0`, 'utf8'));\n }\n\n setSender(sender: string): void {\n\n this.requireAction(SMFIF.SETSENDER, 'setSender', EOM_ONLY_PHASES);\n this.send(SMFIR.SETSENDER, Buffer.from(`${sender}\\0`, 'utf8'));\n }\n\n replyCode(code: string, message: string, enhancedCode = '5.7.1'): void {\n\n this.send(SMFIR.REPLYCODE, Buffer.from(`${code} ${enhancedCode} ${message}\\0`, 'utf8'));\n }\n}\n","import { SMFIR } from './constants.js';\nimport type { MilterDecision, MilterDecisionKeyword, MilterReply } from './types.js';\n\nconst DECISION_TO_COMMAND: Record<MilterDecisionKeyword, string> = {\n continue: SMFIR.CONTINUE,\n accept: SMFIR.ACCEPT,\n reject: SMFIR.REJECT,\n discard: SMFIR.DISCARD,\n tempfail: SMFIR.TEMPFAIL,\n};\n\nexport const Decision = {\n continue(): MilterReply {\n\n return { command: SMFIR.CONTINUE };\n },\n accept(): MilterReply {\n\n return { command: SMFIR.ACCEPT };\n },\n reject(): MilterReply {\n\n return { command: SMFIR.REJECT };\n },\n discard(): MilterReply {\n\n return { command: SMFIR.DISCARD };\n },\n tempfail(): MilterReply {\n\n return { command: SMFIR.TEMPFAIL };\n },\n replyCode(code: string, message: string, enhancedCode = '5.7.1'): MilterReply {\n\n const payload = Buffer.from(`${code} ${enhancedCode} ${message}\\0`, 'utf8');\n\n return {\n command: SMFIR.REPLYCODE,\n data: payload,\n };\n },\n};\n\nexport function normalizeDecision(\n decision: MilterDecision,\n fallback: MilterDecisionKeyword,\n): MilterReply | null {\n\n if (decision === null) {\n return null;\n }\n\n if (decision === undefined) {\n return { command: DECISION_TO_COMMAND[fallback] };\n }\n\n if (typeof decision === 'string') {\n return { command: DECISION_TO_COMMAND[decision] };\n }\n\n if (decision.data === undefined) {\n return { command: decision.command };\n }\n\n return {\n command: decision.command,\n data: decision.data,\n };\n}\n","import type {\n DKIMSignOptions,\n DKIMSignResult,\n DKIMVerifyOptions,\n DKIMVerifyResult,\n MessageInput,\n} from 'mailauth';\nimport { dkimSign } from 'mailauth/lib/dkim/sign.js';\nimport { dkimVerify } from 'mailauth/lib/dkim/verify.js';\n\nimport type { MilterContext } from './context.js';\n\nexport type DkimSignOptions = DKIMSignOptions;\nexport type DkimSignResult = DKIMSignResult;\nexport type DkimVerifyOptions = DKIMVerifyOptions;\nexport type DkimVerifyResult = DKIMVerifyResult;\n\nfunction normalizeSender(from: readonly string[] | null): string | undefined {\n\n const value = from?.[0]?.trim();\n\n if (!value || value === '<>') {\n return undefined;\n }\n\n if (value.startsWith('<') && value.endsWith('>')) {\n return value.slice(1, -1).trim() || undefined;\n }\n\n return value;\n}\n\nfunction buildMessage(ctx: MilterContext, body: Buffer): Buffer {\n\n const headers = ctx.headerLines.map(([name, value]) => `${name}: ${value}`).join('\\r\\n');\n\n return Buffer.concat([\n Buffer.from(`${headers}\\r\\n\\r\\n`, 'utf8'),\n body,\n ]);\n}\n\nexport async function verifyDkim(\n body: Buffer,\n ctx: MilterContext,\n options: DkimVerifyOptions = {},\n): Promise<DkimVerifyResult> {\n\n const sender = options.sender ?? normalizeSender(ctx.from);\n const result = await dkimVerify(buildMessage(ctx, body), {\n ...options,\n ...(sender === undefined ? {} : { sender }),\n });\n\n ctx.dkim = result;\n return result;\n}\n\nexport async function signDkim(\n message: MessageInput,\n options: DkimSignOptions,\n): Promise<DkimSignResult> {\n\n const signatureData = options.signatureData?.length\n ? options.signatureData.map((entry) => ({ ...entry }))\n : [{\n signingDomain: options.signingDomain,\n selector: options.selector,\n privateKey: options.privateKey,\n ...(options.canonicalization === undefined ? {} : { canonicalization: options.canonicalization }),\n ...(options.algorithm === undefined ? {} : { algorithm: options.algorithm }),\n ...(options.maxBodyLength === undefined ? {} : { maxBodyLength: options.maxBodyLength }),\n ...(options.identity === undefined ? {} : { identity: options.identity }),\n }];\n\n return dkimSign(message, {\n ...options,\n signatureData,\n });\n}\n","import type { Logger } from './types.js';\n\nexport class ConsoleLogger implements Logger {\n\n private readonly prefix: string;\n\n constructor(prefix = '[MILTER]') {\n\n this.prefix = prefix;\n }\n\n debug(...args: unknown[]): void {\n\n console.debug(this.prefix, ...args);\n }\n\n info(...args: unknown[]): void {\n\n console.info(this.prefix, ...args);\n }\n\n warn(...args: unknown[]): void {\n\n console.warn(this.prefix, ...args);\n }\n\n error(...args: unknown[]): void {\n\n console.error(this.prefix, ...args);\n }\n}\n","import fs from 'node:fs';\nimport net from 'node:net';\n\nimport {\n ACTION_ALL,\n DISABLE_ALL_CALLBACKS,\n SMFIC,\n SMFIF,\n SMFI_VERSION,\n SMFIP,\n} from './constants.js';\nimport { MilterContext } from './context.js';\nimport { normalizeDecision } from './decisions.js';\nimport { verifyDkim } from './dkim.js';\nimport type { DkimVerifyOptions } from './dkim.js';\nimport { ConsoleLogger } from './logger.js';\nimport { send } from './frames.js';\nimport { checkSpf } from './spf.js';\nimport type { SpfOptions } from './spf.js';\nimport type {\n HeaderMap,\n Logger,\n MilterDecision,\n MilterEventMap,\n MilterEventName,\n MilterOptions,\n} from './types.js';\nimport {\n cloneHeaders, parseConnectInfo, readCString, readCStringList, readCStringPairs,\n} from './utils.js';\n\ntype GenericHandler = (...args: unknown[]) => unknown | Promise<unknown>;\ntype HandlerMap = Record<MilterEventName, Set<GenericHandler>>;\n\ninterface ResolvedOptions {\n socketPath: string | undefined;\n host: string;\n port: number | undefined;\n actions: number;\n unlinkOnStart: boolean;\n chmod: number | false;\n collectBody: boolean;\n maxBodyBytes: number;\n enforceActionStages: boolean;\n defaultDecision: 'continue' | 'accept' | 'reject' | 'discard' | 'tempfail';\n logger: Logger;\n}\n\nconst DEFAULT_OPTIONS: ResolvedOptions = {\n socketPath: undefined,\n host: '127.0.0.1',\n port: undefined,\n actions: SMFIF.ADDHDRS | SMFIF.CHGBODY | SMFIF.ADDRCPT,\n unlinkOnStart: true,\n chmod: 0o777,\n collectBody: true,\n maxBodyBytes: 32 * 1024 * 1024,\n enforceActionStages: true,\n defaultDecision: 'continue',\n logger: new ConsoleLogger('[MILTER]'),\n};\n\nfunction createHandlerMap(): HandlerMap {\n\n return {\n connect: new Set(),\n helo: new Set(),\n mail: new Set(),\n rcpt: new Set(),\n headerLine: new Set(),\n headers: new Set(),\n header: new Set(),\n bodyChunk: new Set(),\n bodyEnd: new Set(),\n data: new Set(),\n macro: new Set(),\n abort: new Set(),\n close: new Set(),\n unknown: new Set(),\n error: new Set(),\n };\n}\n\nexport class MilterServer {\n\n private readonly server: net.Server;\n private readonly handlers: HandlerMap;\n private readonly options: ResolvedOptions;\n private nextConnectionId = 1;\n private dkimOptions: DkimVerifyOptions | null = null;\n private spfOptions: SpfOptions | null = null;\n\n constructor(options: MilterOptions = {}) {\n\n this.options = {\n ...DEFAULT_OPTIONS,\n ...options,\n logger: options.logger ?? DEFAULT_OPTIONS.logger,\n };\n\n if (!this.options.socketPath && this.options.port === undefined) {\n throw new Error('Either socketPath or port must be provided.');\n }\n\n this.handlers = createHandlerMap();\n this.server = net.createServer((socket) => {\n\n this.handleConnection(socket);\n });\n\n this.server.on('error', (err) => {\n\n this.options.logger.error('Server error', err);\n this.emitInternalError(undefined, err);\n });\n }\n\n on<K extends MilterEventName>(event: K, handler: MilterEventMap[K]): this {\n\n this.handlers[event].add(handler as GenericHandler);\n return this;\n }\n\n off<K extends MilterEventName>(event: K, handler: MilterEventMap[K]): this {\n\n this.handlers[event].delete(handler as GenericHandler);\n return this;\n }\n\n once<K extends MilterEventName>(event: K, handler: MilterEventMap[K]): this {\n\n const wrap = (async (...args: unknown[]) => {\n\n this.off(event, wrap as MilterEventMap[K]);\n return (handler as GenericHandler)(...args);\n }) as MilterEventMap[K];\n\n this.on(event, wrap);\n return this;\n }\n\n useSpf(options: SpfOptions = {}): this {\n\n this.spfOptions = options;\n return this;\n }\n\n useDkim(options: DkimVerifyOptions = {}): this {\n\n if (!this.options.collectBody) {\n throw new Error('DKIM verification requires collectBody to be enabled.');\n }\n\n this.dkimOptions = options;\n return this;\n }\n\n async listen(socketPathOverride?: string): Promise<void> {\n\n if (socketPathOverride) {\n this.options.socketPath = socketPathOverride;\n }\n\n if (this.options.socketPath) {\n if (this.options.unlinkOnStart && fs.existsSync(this.options.socketPath)) {\n fs.unlinkSync(this.options.socketPath);\n }\n\n await new Promise<void>((resolve, reject) => {\n\n this.server.listen(this.options.socketPath, (err?: Error) => {\n\n if (err) {\n reject(err);\n return;\n }\n\n if (this.options.chmod !== false) {\n fs.chmodSync(this.options.socketPath as string, this.options.chmod);\n }\n\n this.options.logger.info('Listening on', this.options.socketPath);\n resolve();\n });\n });\n return;\n }\n\n await new Promise<void>((resolve, reject) => {\n\n this.server.listen(this.options.port, this.options.host, (err?: Error) => {\n\n if (err) {\n reject(err);\n return;\n }\n\n this.options.logger.info('Listening on', `${this.options.host}:${this.options.port}`);\n resolve();\n });\n });\n }\n\n async close(): Promise<void> {\n\n await new Promise<void>((resolve, reject) => {\n\n this.server.close((err?: Error) => {\n\n if (err) {\n reject(err);\n return;\n }\n resolve();\n });\n });\n }\n\n private handleConnection(socket: net.Socket): void {\n\n const ctx = new MilterContext(\n this.nextConnectionId++,\n socket,\n this.options.collectBody,\n this.options.maxBodyBytes,\n this.options.enforceActionStages,\n );\n\n this.options.logger.info('MTA connected', ctx.id);\n\n let closed = false;\n let buffer = Buffer.alloc(0);\n let pipeline: Promise<void> = Promise.resolve();\n const emitClose = () => {\n\n if (closed) {\n return;\n }\n closed = true;\n void this.emit('close', ctx);\n };\n\n socket.on('error', (err) => {\n\n this.options.logger.error('Socket error', ctx.id, err);\n this.emitInternalError(ctx, err);\n });\n\n socket.on('close', () => {\n\n ctx.socket = null;\n emitClose();\n });\n\n socket.on('end', () => {\n\n this.options.logger.info('MTA disconnected', ctx.id);\n ctx.socket = null;\n emitClose();\n });\n\n socket.on('data', (chunk) => {\n\n buffer = Buffer.concat([buffer, chunk]);\n\n while (buffer.length >= 5) {\n const len = buffer.readUInt32BE(0);\n\n if (len < 1) {\n this.options.logger.warn('Invalid frame length', len, 'connection', ctx.id);\n socket.destroy();\n return;\n }\n\n const total = 4 + len;\n\n if (buffer.length < total) {\n break;\n }\n\n const command = buffer.toString('ascii', 4, 5);\n const data = buffer.subarray(5, total);\n\n buffer = buffer.subarray(total);\n\n pipeline = pipeline\n .then(() => this.parsePacket(ctx, command, data))\n .catch((err) => {\n\n this.options.logger.error('Packet handling error', ctx.id, err);\n this.emitInternalError(ctx, err);\n send(ctx.socket, 't');\n });\n }\n });\n }\n\n private async parsePacket(ctx: MilterContext, command: string, data: Buffer): Promise<void> {\n\n switch (command) {\n case SMFIC.OPTNEG:\n {\n if (data.length < 12) {\n this.options.logger.warn('Invalid OPTNEG payload length', data.length, 'connection', ctx.id);\n return;\n }\n\n const mtaVersion = data.readUInt32BE(0);\n const mtaActions = data.readUInt32BE(4);\n const mtaProtocol = data.readUInt32BE(8);\n const version = Math.min(mtaVersion, SMFI_VERSION);\n const actions = (this.options.actions & mtaActions) >>> 0;\n const protocol = (this.computeProtocolMask() & mtaProtocol) >>> 0;\n\n ctx.setNegotiatedActions(actions);\n\n const payload = Buffer.alloc(12);\n\n payload.writeUInt32BE(version, 0);\n payload.writeUInt32BE(actions, 4);\n payload.writeUInt32BE(protocol, 8);\n send(ctx.socket, SMFIC.OPTNEG, payload);\n return;\n }\n\n case SMFIC.CONNECT:\n {\n ctx.setPhase('connect');\n\n const info = parseConnectInfo(data);\n\n ctx.connection = info;\n\n const decision = (await this.emit('connect', info, ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n case SMFIC.HELO:\n {\n ctx.setPhase('helo');\n\n const helo = readCString(data, 0).value;\n\n ctx.helo = helo;\n\n const decision = (await this.emit('helo', helo, ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n case SMFIC.MAIL:\n {\n ctx.setPhase('mail');\n\n const from = readCStringList(data);\n\n ctx.from = from;\n\n if (this.spfOptions) {\n await checkSpf(from, ctx, this.spfOptions);\n }\n\n const decision = (await this.emit('mail', from, ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n case SMFIC.RCPT:\n {\n ctx.setPhase('rcpt');\n\n const to = readCStringList(data);\n\n ctx.to = to;\n\n const decision = (await this.emit('rcpt', to, ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n case SMFIC.HEADER:\n {\n ctx.setPhase('headerLine');\n\n const p = readCString(data, 0);\n const q = readCString(data, p.next);\n\n if (p.value.length > 0) {\n ctx.appendHeader(p.value, q.value);\n\n const decision = (await this.emit('headerLine', p.value, q.value, ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n this.respond(ctx, undefined);\n return;\n }\n\n case SMFIC.EOH:\n {\n ctx.setPhase('eoh');\n\n const headers = cloneHeaders(ctx.headers) as HeaderMap;\n const legacy = (await this.emit('header', headers, ctx)) as MilterDecision;\n const modern = (await this.emit('headers', headers, ctx)) as MilterDecision;\n\n this.respond(ctx, modern ?? legacy);\n return;\n }\n\n case SMFIC.BODY:\n {\n ctx.setPhase('bodyChunk');\n try {\n ctx.appendBody(data);\n } catch (err) {\n this.emitInternalError(ctx, err);\n this.respond(ctx, 'tempfail');\n return;\n }\n\n const decision = (await this.emit('bodyChunk', Buffer.from(data), ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n case SMFIC.BODYEOB:\n {\n ctx.setPhase('bodyEnd');\n\n const body = ctx.getBody();\n\n if (this.dkimOptions) {\n await verifyDkim(body, ctx, this.dkimOptions);\n }\n\n const decision = (await this.emit('bodyEnd', body, ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n case SMFIC.DATA:\n {\n ctx.setPhase('data');\n\n const decision = (await this.emit('data', data.toString('utf8'), ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n case SMFIC.MACRO:\n {\n ctx.setPhase('macro');\n\n const cmd = data.toString('ascii', 0, 1);\n const map = readCStringPairs(data, 1);\n\n ctx.macros[cmd] = map;\n await this.emit('macro', cmd, map, ctx);\n return;\n }\n\n case SMFIC.ABORT:\n {\n ctx.setPhase('abort');\n ctx.resetMessage();\n await this.emit('abort', ctx);\n return;\n }\n\n case SMFIC.QUIT:\n {\n ctx.setPhase('close');\n await this.emit('close', ctx);\n if (ctx.socket) {\n ctx.socket.end();\n ctx.socket = null;\n }\n return;\n }\n\n case SMFIC.UNKNOWN:\n {\n ctx.setPhase('unknown');\n\n const decision = (await this.emit('unknown', command, data, ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n return;\n }\n\n default:\n {\n ctx.setPhase('unknown');\n this.options.logger.warn('Unknown command', command, 'connection', ctx.id);\n\n const decision = (await this.emit('unknown', command, data, ctx)) as MilterDecision;\n\n this.respond(ctx, decision);\n }\n }\n }\n\n private computeProtocolMask(): number {\n\n let flags = DISABLE_ALL_CALLBACKS;\n\n if (this.handlers.connect.size > 0) {\n flags &= ~SMFIP.NOCONNECT;\n }\n if (this.handlers.helo.size > 0) {\n flags &= ~SMFIP.NOHELO;\n }\n if (this.handlers.mail.size > 0 || this.spfOptions) {\n flags &= ~SMFIP.NOMAIL;\n }\n if (this.handlers.rcpt.size > 0) {\n flags &= ~SMFIP.NORCPT;\n }\n if (this.handlers.bodyChunk.size > 0 || this.handlers.bodyEnd.size > 0 || this.dkimOptions) {\n flags &= ~SMFIP.NOBODY;\n }\n if (\n this.handlers.headerLine.size > 0\n || this.handlers.headers.size > 0\n || this.handlers.header.size > 0\n || this.dkimOptions\n ) {\n flags &= ~SMFIP.NOHDRS;\n }\n if (this.handlers.headers.size > 0 || this.handlers.header.size > 0) {\n flags &= ~SMFIP.NOEOH;\n }\n\n return flags >>> 0;\n }\n\n private respond(ctx: MilterContext, decision: MilterDecision): void {\n\n const normalized = normalizeDecision(decision, this.options.defaultDecision);\n\n if (!normalized) {\n return;\n }\n send(ctx.socket, normalized.command, normalized.data);\n }\n\n private async emit<K extends MilterEventName>(\n event: K,\n ...args: Parameters<MilterEventMap[K]>\n ): Promise<unknown> {\n\n const callbacks = this.handlers[event];\n\n if (!callbacks || callbacks.size === 0) {\n return undefined;\n }\n\n let result: unknown;\n\n for (const fn of callbacks) {\n result = await fn(...(args as unknown[]));\n }\n\n return result;\n }\n\n private emitInternalError(ctx: MilterContext | undefined, err: unknown): void {\n\n const callbacks = this.handlers.error;\n\n if (callbacks.size === 0) {\n return;\n }\n\n for (const fn of callbacks) {\n Promise.resolve(fn(err, ctx)).catch(() => {\n\n this.options.logger.error('Error handler failed', err);\n });\n }\n }\n}\n\nexport class Milter extends MilterServer {\n\n constructor(options: MilterOptions = {}) {\n\n const resolved = {\n actions: ACTION_ALL,\n ...options,\n };\n\n super(resolved);\n }\n}\n","import type { DNSResolver, SPFResult } from 'mailauth';\nimport { spf as verifySpf } from 'mailauth/lib/spf/index.js';\n\nimport type { MilterContext } from './context.js';\nimport type { MilterDecisionKeyword } from './types.js';\n\nexport type SpfResultCode\n = | 'pass'\n | 'fail'\n | 'softfail'\n | 'neutral'\n | 'none'\n | 'temperror'\n | 'permerror';\n\nexport type SpfPolicy = Partial<Record<SpfResultCode, MilterDecisionKeyword>>;\n\nexport interface SpfOptions {\n mta?: string;\n maxResolveCount?: number;\n maxVoidCount?: number;\n resolver?: DNSResolver;\n}\n\nexport type SpfResult = SPFResult;\n\nconst DEFAULT_POLICY: Record<SpfResultCode, MilterDecisionKeyword> = {\n pass: 'continue',\n fail: 'reject',\n softfail: 'continue',\n neutral: 'continue',\n none: 'continue',\n temperror: 'tempfail',\n permerror: 'continue',\n};\n\nfunction normalizeSender(from: string | readonly string[]): string | undefined {\n\n const value = (typeof from === 'string' ? from : from[0])?.trim();\n\n if (!value || value === '<>') {\n return undefined;\n }\n\n if (value.startsWith('<') && value.endsWith('>')) {\n return value.slice(1, -1).trim() || undefined;\n }\n\n return value;\n}\n\nexport async function checkSpf(\n from: string | readonly string[],\n ctx: MilterContext,\n options: SpfOptions = {},\n): Promise<SpfResult> {\n\n const ip = ctx.connection?.address;\n\n if (!ip) {\n throw new Error('SPF requires the client IP from the Milter CONNECT event.');\n }\n\n const sender = normalizeSender(from);\n const helo = ctx.helo ?? ctx.connection?.hostname;\n const result = await verifySpf({\n ip,\n ...(sender === undefined ? {} : { sender }),\n ...(helo === undefined ? {} : { helo }),\n ...(options.mta === undefined ? {} : { mta: options.mta }),\n ...(options.maxResolveCount === undefined ? {} : { maxResolveCount: options.maxResolveCount }),\n ...(options.maxVoidCount === undefined ? {} : { maxVoidCount: options.maxVoidCount }),\n ...(options.resolver === undefined ? {} : { resolver: options.resolver }),\n });\n\n ctx.spf = result;\n return result;\n}\n\nexport function spfDecision(result: SpfResult, policy: SpfPolicy = {}): MilterDecisionKeyword {\n\n const code = result.status.result as SpfResultCode;\n\n return policy[code] ?? DEFAULT_POLICY[code] ?? 'continue';\n}\n","import { SMFIA } from './constants.js';\nimport type { ConnectInfo } from './types.js';\n\nexport function readCString(buf: Buffer, start = 0): { value: string;\n next: number; } {\n\n if (start >= buf.length) {\n return {\n value: '',\n next: buf.length,\n };\n }\n\n const end = buf.indexOf(0x00, start);\n\n if (end === -1) {\n return {\n value: buf.toString('utf8', start),\n next: buf.length,\n };\n }\n\n return {\n value: buf.toString('utf8', start, end),\n next: end + 1,\n };\n}\n\nexport function readCStringList(buf: Buffer, start = 0): string[] {\n\n const out: string[] = [];\n let offset = start;\n\n while (offset < buf.length) {\n const { value, next } = readCString(buf, offset);\n\n if (next === offset) {\n break;\n }\n\n offset = next;\n if (value.length === 0) {\n if (offset >= buf.length) {\n break;\n }\n continue;\n }\n\n out.push(value);\n }\n\n return out;\n}\n\nexport function readCStringPairs(buf: Buffer, start = 0): Record<string, string> {\n\n const list = readCStringList(buf, start);\n const map: Record<string, string> = {};\n\n for (let i = 0; i + 1 < list.length; i += 2) {\n const key = list[i];\n const value = list[i + 1];\n\n if (key && value) {\n map[key] = value;\n }\n }\n\n return map;\n}\n\nexport function parseConnectInfo(payload: Buffer): ConnectInfo {\n\n const host = readCString(payload, 0);\n const familyByte = payload.toString('ascii', host.next, host.next + 1);\n\n if (familyByte === SMFIA.UNKNOWN || host.next >= payload.length) {\n return {\n hostname: host.value,\n family: 'UNKNOWN',\n };\n }\n\n if (host.next + 3 > payload.length) {\n return {\n hostname: host.value,\n family: 'UNKNOWN',\n };\n }\n\n const port = payload.readUInt16BE(host.next + 1);\n const addr = readCString(payload, host.next + 3).value;\n const family\n = familyByte === SMFIA.UNIX\n ? 'UNIX'\n : familyByte === SMFIA.INET\n ? 'INET'\n : familyByte === SMFIA.INET6\n ? 'INET6'\n : 'UNKNOWN';\n\n return {\n hostname: host.value,\n family,\n address: addr,\n port,\n };\n}\n\nexport function cloneHeaders(headers: Record<string, string[]>): Record<string, string[]> {\n\n const out: Record<string, string[]> = {};\n\n for (const [name, values] of Object.entries(headers)) {\n out[name] = [...values];\n }\n return out;\n}\n"],"mappings":"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","names":["normalizeSender"]}
|
package/package.json
CHANGED
|
@@ -1,26 +1,120 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
"name": "milter",
|
|
3
|
+
"title": "Milter",
|
|
4
|
+
"version": "3.0.0",
|
|
5
|
+
"description": "Milter server for asynchronous Node.js mail filters and message mutation",
|
|
6
|
+
"homepage": "https://raw.org/software/libraries/milter-js/",
|
|
7
|
+
"bugs": {
|
|
8
|
+
"url": "https://github.com/rawify/Milter.js/issues"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"milter",
|
|
12
|
+
"protocol",
|
|
13
|
+
"smtp",
|
|
14
|
+
"mail",
|
|
15
|
+
"server",
|
|
16
|
+
"postfix",
|
|
17
|
+
"sendmail",
|
|
18
|
+
"opensmtpd",
|
|
19
|
+
"spam-filter",
|
|
20
|
+
"email-security"
|
|
21
|
+
],
|
|
22
|
+
"private": false,
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "./dist/index.cjs",
|
|
25
|
+
"module": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"files": [
|
|
28
|
+
"dist",
|
|
29
|
+
"res",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE"
|
|
32
|
+
],
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"import": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"default": "./dist/index.js"
|
|
38
|
+
},
|
|
39
|
+
"require": {
|
|
40
|
+
"types": "./dist/index.d.cts",
|
|
41
|
+
"default": "./dist/index.cjs"
|
|
42
|
+
},
|
|
43
|
+
"default": "./dist/index.js"
|
|
15
44
|
},
|
|
16
|
-
"
|
|
17
|
-
|
|
45
|
+
"./constants": {
|
|
46
|
+
"import": {
|
|
47
|
+
"types": "./dist/constants.d.ts",
|
|
48
|
+
"default": "./dist/constants.js"
|
|
49
|
+
},
|
|
50
|
+
"require": {
|
|
51
|
+
"types": "./dist/constants.d.cts",
|
|
52
|
+
"default": "./dist/constants.cjs"
|
|
53
|
+
},
|
|
54
|
+
"default": "./dist/constants.js"
|
|
18
55
|
},
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
56
|
+
"./package.json": "./package.json"
|
|
57
|
+
},
|
|
58
|
+
"repository": {
|
|
59
|
+
"type": "git",
|
|
60
|
+
"url": "git+https://github.com/rawify/Milter.js.git"
|
|
61
|
+
},
|
|
62
|
+
"funding": {
|
|
63
|
+
"type": "github",
|
|
64
|
+
"url": "https://github.com/sponsors/rawify"
|
|
65
|
+
},
|
|
66
|
+
"author": {
|
|
67
|
+
"name": "Robert Eisele",
|
|
68
|
+
"email": "robert@raw.org",
|
|
69
|
+
"url": "https://raw.org/"
|
|
70
|
+
},
|
|
71
|
+
"license": "MIT",
|
|
72
|
+
"engines": {
|
|
73
|
+
"node": ">=22.19.0"
|
|
74
|
+
},
|
|
75
|
+
"packageManager": "npm@10.9.7",
|
|
76
|
+
"sideEffects": false,
|
|
77
|
+
"scripts": {
|
|
78
|
+
"clean": "rm -rf dist",
|
|
79
|
+
"build": "tsup",
|
|
80
|
+
"typecheck": "tsc --noEmit",
|
|
81
|
+
"lint": "eslint .",
|
|
82
|
+
"lint:fix": "eslint . --fix",
|
|
83
|
+
"example:dmarc": "npm run build && node examples/dmarc-collector.mjs",
|
|
84
|
+
"example:dmarc:db": "npm run build && node examples/dmarc-collector-db.mjs",
|
|
85
|
+
"example:chatgpt-spamfilter": "npm run build && node examples/spamfilter/chatgpt-spamfilter.mjs",
|
|
86
|
+
"example:ollama-spamfilter": "npm run build && node examples/spamfilter/ollama-spamfilter.mjs",
|
|
87
|
+
"example:simple-spamfilter": "npm run build && node examples/spamfilter/simple-spamfilter.mjs",
|
|
88
|
+
"example:domaindata-holo-check": "npm run build && node examples/domaindata-holo-check.mjs",
|
|
89
|
+
"test": "npm run build && node --test tests/*.test.mjs",
|
|
90
|
+
"check": "npm run lint && npm run typecheck && npm run test",
|
|
91
|
+
"prepack": "npm run build",
|
|
92
|
+
"prepublishOnly": "npm run check"
|
|
93
|
+
},
|
|
94
|
+
"devDependencies": {
|
|
95
|
+
"@eslint/js": "^9.34.0",
|
|
96
|
+
"@stylistic/eslint-plugin": "^5.10.0",
|
|
97
|
+
"@types/node": "^22.18.0",
|
|
98
|
+
"dotenv": "^17.2.2",
|
|
99
|
+
"eslint": "^9.34.0",
|
|
100
|
+
"globals": "^16.4.0",
|
|
101
|
+
"mailparser": "^3.9.17",
|
|
102
|
+
"ollama": "^0.6.3",
|
|
103
|
+
"openai": "^5.20.3",
|
|
104
|
+
"tldts": "^7.0.13",
|
|
105
|
+
"tsup": "^8.5.0",
|
|
106
|
+
"typescript": "^5.9.2",
|
|
107
|
+
"typescript-eslint": "^8.41.0"
|
|
108
|
+
},
|
|
109
|
+
"overrides": {
|
|
110
|
+
"esbuild": "0.27.2",
|
|
111
|
+
"joi": "18.2.9",
|
|
112
|
+
"nodemailer": "10.0.10"
|
|
113
|
+
},
|
|
114
|
+
"publishConfig": {
|
|
115
|
+
"access": "public"
|
|
116
|
+
},
|
|
117
|
+
"dependencies": {
|
|
118
|
+
"mailauth": "^5.0.3"
|
|
119
|
+
}
|
|
26
120
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" role="img" aria-labelledby="title">
|
|
2
|
+
<title>Maail</title>
|
|
3
|
+
<defs>
|
|
4
|
+
<linearGradient id="background" x1="0" y1="0" x2="1" y2="1">
|
|
5
|
+
<stop offset="0" stop-color="#f4f6ef"/>
|
|
6
|
+
<stop offset="1" stop-color="#bbff72"/>
|
|
7
|
+
</linearGradient>
|
|
8
|
+
</defs>
|
|
9
|
+
<rect width="200" height="200" rx="24" fill="url(#background)"/>
|
|
10
|
+
<path fill="#10201a" d="M10 37.7h36.2l1.3 14.6C56.3 41.1 68.1 35.5 83 35.5c15.7 0 26.3 6.2 31.8 18.7 8.5-12.5 20.7-18.7 36.6-18.7 25.1 0 38 15.2 38.7 45.6V162h-38.7V83.6c0-6.4-1.1-11-3.2-13.9-2.2-2.9-6.1-4.4-11.8-4.4-7.7 0-13.4 3.4-17.1 10.2l.1 1.5v85h-38.8V83.8c0-6.5-1-11.1-3-14-2.1-2.9-6-4.4-11.9-4.4-7.4 0-13 3.4-16.9 10.2V162H10V37.7Z"/>
|
|
11
|
+
</svg>
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
2
|
+
<svg
|
|
3
|
+
width="900"
|
|
4
|
+
height="320"
|
|
5
|
+
viewBox="0 0 900 320"
|
|
6
|
+
role="img"
|
|
7
|
+
aria-labelledby="title desc"
|
|
8
|
+
version="1.1"
|
|
9
|
+
id="svg18"
|
|
10
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
11
|
+
xmlns:svg="http://www.w3.org/2000/svg">
|
|
12
|
+
<defs
|
|
13
|
+
id="defs22" />
|
|
14
|
+
<title
|
|
15
|
+
id="title">milter.js</title>
|
|
16
|
+
<g
|
|
17
|
+
fill="none"
|
|
18
|
+
stroke="#0b1020"
|
|
19
|
+
stroke-width="14"
|
|
20
|
+
stroke-linecap="round"
|
|
21
|
+
stroke-linejoin="round"
|
|
22
|
+
id="g8">
|
|
23
|
+
<path
|
|
24
|
+
d="m 196,231 h 63 c 18,0 31,-13 31,-31 V 95 C 290,77 277,64 259,64 H 61 C 43,64 30,77 30,95 v 105 c 0,18 13,31 31,31 h 63"
|
|
25
|
+
id="path4" />
|
|
26
|
+
<path
|
|
27
|
+
d="m 45,84 98,77 c 10,8 24,8 34,0 l 98,-77"
|
|
28
|
+
id="path6" />
|
|
29
|
+
</g>
|
|
30
|
+
|
|
31
|
+
<path
|
|
32
|
+
d="M160 174v31"
|
|
33
|
+
fill="none"
|
|
34
|
+
stroke="#FF4F2E"
|
|
35
|
+
stroke-width="14"
|
|
36
|
+
stroke-linecap="round"
|
|
37
|
+
id="path10" />
|
|
38
|
+
<path
|
|
39
|
+
d="M122 202h76l-28 35v29h-20v-29Z"
|
|
40
|
+
fill="#FF4F2E"
|
|
41
|
+
id="path12" />
|
|
42
|
+
<g
|
|
43
|
+
aria-label="milter"
|
|
44
|
+
id="text14"
|
|
45
|
+
style="font-weight:700;font-size:122px;font-family:'Nimbus Sans', Arial, sans-serif;letter-spacing:-5;fill:#0b1020">
|
|
46
|
+
<path
|
|
47
|
+
d="M 367.32,152.12 V 218 h 17.08 v -39.528 c 0,-8.174 4.392,-12.932 11.712,-12.932 5.734,0 9.272,3.294 9.272,8.54 V 218 h 17.08 v -39.528 c 0,-8.052 4.392,-12.932 11.712,-12.932 5.734,0 9.272,3.294 9.272,8.54 V 218 h 17.08 v -46.604 c 0,-12.81 -7.808,-20.374 -20.984,-20.374 -8.418,0 -14.152,2.928 -19.276,9.76 -3.172,-6.222 -9.76,-9.76 -17.934,-9.76 -7.564,0 -12.444,2.44 -18.056,9.272 v -8.174 z"
|
|
48
|
+
id="path24" />
|
|
49
|
+
<path
|
|
50
|
+
d="m 488.71199,152.12 h -17.08 V 218 h 17.08 z m 0,-23.058 h -17.08 v 15.25 h 17.08 z"
|
|
51
|
+
id="path26" />
|
|
52
|
+
<path
|
|
53
|
+
d="m 517.62798,129.062 h -17.08 V 218 h 17.08 z"
|
|
54
|
+
id="path28" />
|
|
55
|
+
<path
|
|
56
|
+
d="m 558.01196,153.462 h -9.516 v -17.69 h -17.08 v 17.69 h -8.418 v 11.346 h 8.418 v 40.504 c 0,10.37 5.49,15.494 16.714,15.494 3.904,0 6.71,-0.366 9.882,-1.342 v -11.956 c -1.708,0.244 -2.562,0.366 -3.904,0.366 -4.514,0 -5.612,-1.342 -5.612,-7.198 v -35.868 h 9.516 z"
|
|
57
|
+
id="path30" />
|
|
58
|
+
<path
|
|
59
|
+
d="m 620.35602,190.428 c 0.122,-1.464 0.122,-2.074 0.122,-2.928 0,-6.588 -0.976,-12.688 -2.562,-17.324 -4.392,-11.956 -15.006,-19.154 -28.304,-19.154 -18.91,0 -30.5,13.664 -30.5,35.746 0,21.106 11.468,34.038 30.134,34.038 14.762,0 26.718,-8.296 30.5,-21.35 h -16.836 c -2.074,5.246 -6.832,8.296 -13.054,8.296 -4.88,0 -8.784,-2.074 -11.224,-5.734 -1.586,-2.44 -2.196,-5.368 -2.44,-11.59 z m -43.92,-11.346 c 1.098,-10.126 5.368,-15.006 12.932,-15.006 7.808,0 12.444,5.246 13.298,15.006 z"
|
|
60
|
+
id="path32" />
|
|
61
|
+
<path
|
|
62
|
+
d="M 626.94598,152.12 V 218 h 17.08 v -35.014 c 0,-10.004 5.002,-15.006 15.006,-15.006 1.83,0 3.05,0.122 5.368,0.488 v -17.324 c -0.976,-0.122 -1.342,-0.122 -2.074,-0.122 -7.808,0 -14.518,5.124 -18.3,14.03 V 152.12 Z"
|
|
63
|
+
id="path34" />
|
|
64
|
+
</g>
|
|
65
|
+
<g
|
|
66
|
+
aria-label=".js"
|
|
67
|
+
id="text16"
|
|
68
|
+
style="font-weight:700;font-size:48px;font-family:'DejaVu Sans Mono', monospace;letter-spacing:-3;fill:#ff4f2e">
|
|
69
|
+
<path
|
|
70
|
+
d="m 675.52344,134.39844 h 7.80468 V 143 h -7.80468 z"
|
|
71
|
+
id="path37" />
|
|
72
|
+
<path
|
|
73
|
+
d="m 710.82031,141.99219 q 0,5.90625 -2.13281,8.41406 -2.10938,2.53125 -7.03125,2.53125 H 694.25 v -5.27344 h 5.48437 q 2.29688,0 3.25782,-1.28906 0.96093,-1.28906 0.96093,-4.38281 v -19.96875 h -6.96093 V 116.75 h 13.82812 z m 0,-30 h -6.86719 v -8.01563 h 6.86719 z"
|
|
74
|
+
id="path39" />
|
|
75
|
+
<path
|
|
76
|
+
d="m 740.02344,117.57031 v 6 q -1.89844,-1.21875 -3.96094,-1.82812 -2.03906,-0.63281 -4.10156,-0.63281 -2.29688,0 -3.46875,0.67968 -1.17188,0.65625 -1.17188,1.96875 0,1.875 5.01563,3.04688 l 0.25781,0.0703 1.96875,0.46875 q 3.75,0.89062 5.48437,2.88281 1.75782,1.96875 1.75782,5.34375 0,4.05469 -2.67188,6.09375 -2.64844,2.01563 -7.99219,2.01563 -2.36718,0 -4.85156,-0.42188 -2.48437,-0.39844 -5.03906,-1.21875 v -6 q 2.27344,1.28906 4.61719,1.96875 2.36718,0.67969 4.57031,0.67969 2.41406,0 3.65625,-0.70313 1.24219,-0.70312 1.24219,-2.03906 0,-1.3125 -0.89063,-2.01562 -0.86719,-0.70313 -4.17187,-1.5 l -1.89844,-0.42188 q -3.9375,-0.89062 -5.74219,-2.78906 -1.80469,-1.89844 -1.80469,-5.08594 0,-3.79687 2.74219,-5.90625 2.74219,-2.10937 7.71094,-2.10937 2.22656,0 4.42969,0.375 2.22656,0.35156 4.3125,1.07812 z"
|
|
77
|
+
id="path41" />
|
|
78
|
+
</g>
|
|
79
|
+
</svg>
|
package/.npmignore
DELETED
package/binding.gyp
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"targets": [
|
|
3
|
-
{
|
|
4
|
-
"target_name": "milter",
|
|
5
|
-
"sources": [ "src/envelope.cc", "src/events.cc", "src/milter.cc" ],
|
|
6
|
-
"include_dirs": [ "/usr/include/libmilter" ],
|
|
7
|
-
"cflags": [ "-g -Wall" ],
|
|
8
|
-
"cflags!": [ "-O3" ],
|
|
9
|
-
"ldflags": [ "-L/usr/lib/libmilter" ],
|
|
10
|
-
"libraries" : [ "-lmilter" ]
|
|
11
|
-
}
|
|
12
|
-
]
|
|
13
|
-
}
|
package/lib/milter.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('../build/Release/milter');
|