{"id":14408,"library":"Haraka","title":"Haraka SMTP Server","description":"Haraka is a highly scalable Node.js email server designed for modularity and high performance. It features a robust plugin architecture, enabling developers to easily extend its functionality for tasks such as spam protection, custom routing, and authentication. Haraka excels as a filtering Message Transfer Agent (MTA) or a Mail Submission Agent (MSA) on port 587 with authentication, complementing traditional mail systems like Postfix or Exchange without attempting to be a mail store or IMAP server. The current stable version is 3.1.5, with frequent releases addressing bug fixes, dependency updates, and minor enhancements. Its key differentiators include an asynchronous, event-driven design for speed, excellent built-in spam protection capabilities through plugins, and an easily extensible system for handling complex mail flow scenarios with minimal code.","status":"active","version":"3.1.5","language":"javascript","source_language":"en","source_url":"git://github.com/haraka/Haraka","tags":["javascript","haraka","smtp","server","email"],"install":[{"cmd":"npm install Haraka","lang":"bash","label":"npm"},{"cmd":"yarn add Haraka","lang":"bash","label":"yarn"},{"cmd":"pnpm add Haraka","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Haraka is primarily a command-line application. While the main script (`haraka.js`) can be required, it's not designed to export a programmatic API for embedding. Its typical use is via the `haraka` CLI command.","wrong":"import Haraka from 'Haraka'","symbol":"Haraka CLI Execution","correct":"haraka -c /path/to/haraka_instance"},{"note":"Plugins are loaded by Haraka and interact through predefined hook functions (e.g., `hook_data`, `hook_rcpt_to`). Core objects like `connection` and `transaction` are passed as arguments to these hooks, not imported directly.","wrong":"import { hook_data } from 'Haraka/plugin_api'","symbol":"Plugin System Integration","correct":"// Within a Haraka plugin file (e.g., my_plugin.js):\n// module.exports.hook_data = function (next, connection, transaction) { ... };"},{"note":"For advanced plugin development or internal scripting, Haraka's configuration system can be accessed directly using CommonJS `require` paths relative to the Haraka installation. This is not a public API but is a common pattern for internal modules and power users.","wrong":"import { config } from 'Haraka';","symbol":"Configuration Access (Internal)","correct":"const config = require('Haraka/config');"}],"quickstart":{"code":"#!/usr/bin/env node\n\n// 1. Install Haraka globally (recommended for CLI usage)\n// npm install -g Haraka\n\n// 2. Create a directory for your Haraka instance and initialize it\nconst { execSync } = require('child_process');\nconst path = require('path');\nconst fs = require('fs');\n\nconst instancePath = path.join(__dirname, 'haraka_test_instance');\n\nconsole.log(`Initializing Haraka instance at ${instancePath}...`);\nexecSync(`haraka -i ${instancePath}`, { stdio: 'inherit' });\n\n// 3. (Optional) Configure accepted domains (e.g., 'example.com')\n//    Edit config/host_list within haraka_test_instance to add your domain.\n//    For example: echo 'example.com' > ${instancePath}/config/host_list\n\n// 4. (Optional) Configure outbound forwarding (smtp_forward plugin is default)\n//    Edit config/smtp_forward.ini to specify destination SMTP server.\n//    Example: echo '[main]\\nforward_to=localhost:25000' > ${instancePath}/config/smtp_forward.ini\n\n// 5. Start Haraka (requires root permissions for ports below 1024, like 25)\nconsole.log(`Starting Haraka server (may require sudo for port 25)...`);\nconsole.log(`To stop, use Ctrl+C or kill the process.`);\n// In a real scenario, you'd run this from your terminal with 'sudo haraka -c haraka_test_instance'\n// For demonstration, we'll just log the command.\nconsole.log(`\nRun this command in your terminal: sudo haraka -c ${instancePath}`);\n\n// Example of waiting and then showing how to potentially stop for a script\n// In a real application, you'd use a process manager like PM2.\n// setTimeout(() => {\n//   console.log('Demonstration complete. Exiting.');\n//   // In a real script, you'd send a signal to stop the process.\n// }, 15000);\n","lang":"javascript","description":"Demonstrates the typical workflow for installing Haraka globally, initializing a new server instance, and preparing it for startup as an SMTP server, including notes on configuration and permissions."},"warnings":[{"fix":"Review your existing configuration files (e.g., `haproxy_hosts`, `smtpgreeting.ini`, `databytes.ini`) and migrate their settings to the appropriate sections within `config/connection.ini`. Refer to the `connection.ini` documentation for the new structure.","message":"Haraka v3.1.0 introduced a significant breaking change by consolidating several disparate configuration files (e.g., `haproxy_hosts`, `smtpgreeting`, `databytes`) into a single `connection.ini` file. Existing installations on older versions will need to migrate their settings.","severity":"breaking","affected_versions":">=3.1.0"},{"fix":"Upgrade your Node.js environment to version 20 or newer. It is recommended to use an LTS (Long Term Support) release of Node.js.","message":"As of Haraka v3.1.2, the minimum required Node.js version is 20 or higher. Running Haraka on older Node.js versions (e.g., Node.js 18) will result in errors.","severity":"breaking","affected_versions":">=3.1.2"},{"fix":"Remove `graph` from your `config/plugins` file. Explore alternative monitoring and logging solutions that integrate with Haraka's standard logging (e.g., by piping logs to external analysis tools).","message":"The `graph` plugin was removed in Haraka v3.1.3 due to its dependency on the unmaintained `sqlite3` library. If you relied on this plugin for metrics or visualization, it is no longer available.","severity":"deprecated","affected_versions":">=3.1.3"},{"fix":"Always use `sudo haraka -c /path/to/instance` when running Haraka on ports below 1024. Alternatively, configure Haraka to listen on a non-privileged port (e.g., 2525) for testing, or use capabilities/setuid wrappers in production if direct root is undesired.","message":"To bind to privileged ports (e.g., standard SMTP port 25), Haraka must be run with root privileges. Starting Haraka without sufficient permissions will result in `EACCES` errors.","severity":"gotcha","affected_versions":">=3.0.0"},{"fix":"Ensure that all domains for which Haraka should accept or process mail are listed one per line in the `config/host_list` file within your Haraka instance directory. Restart Haraka after making changes to configuration files.","message":"Haraka will only accept mail for domains explicitly listed in `config/host_list`. If mail for a domain is rejected or not routed correctly, it's often due to the domain missing from this file.","severity":"gotcha","affected_versions":">=3.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Run Haraka with `sudo`: `sudo haraka -c /path/to/haraka_instance`.","cause":"Haraka is attempting to listen on a privileged port (like 25) without sufficient user permissions (e.g., not run as root).","error":"Error: listen EACCES: permission denied 0.0.0.0:25"},{"fix":"Stop the conflicting process, or configure Haraka to listen on a different port by editing `config/smtp.ini`'s `listen` setting.","cause":"Another process (e.g., Postfix, Sendmail, another Haraka instance) is already listening on the configured SMTP port.","error":"Error: listen EADDRINUSE: address already in use :::25"},{"fix":"If installed globally, ensure your `PATH` includes npm's global bin directory. If installing locally for development, ensure you run `npm install` in the project root. For CLI usage, `npm install -g Haraka` is usually sufficient.","cause":"The `haraka` package is not installed or not discoverable in the current Node.js environment/path.","error":"Error: Cannot find module 'Haraka' or Error: Cannot find module 'haraka'"},{"fix":"Add the recipient's domain (e.g., `example.com`) to the `config/host_list` file in your Haraka instance directory and restart Haraka.","cause":"Haraka is configured to accept mail only for domains listed in `config/host_list`, and the recipient's domain is not present in that file.","error":"550 5.7.1 Relaying denied (or similar 'Mailbox unavailable' error for valid recipient)"}],"ecosystem":"npm"}