qmail은 구조적으로 파일 시스템( /var/qmail/queue )에 강하게 의존하도록 C언어로 하드코딩되어 있습니다. 메일 유실을 막기 위해 파일 시스템의 원자성(Atomic rename)과 아이노드(Inode) 생성 방식을 활용하므로, qmail 코어 소스를 처음부터 다시 작성하지 않는 이상 queue 자체를 KeyDB로 직접 대체할 수는 없습니다. 하지만 QMAILQUEUE 환경 변수 를 활용하여 메일 수신(I/O)을 KeyDB로 먼저 넘기고, 백그라운드 워커가 KeyDB에서 데이터를 꺼내어 실제 qmail-queue로 밀어넣는 아키텍처를 구성하면 원하시는 "수신 속도 극대화(I/O 병목 해소)"를 이룰 수 있습니다. 요청하신 기준에 맞춰 누락 없이 바로 사용할 수 있는 전체 소스 코드와 설정 방법을 제공합니다. 1. qmail-queue 원본 백업 가장 먼저 원래의 qmail-queue 실행 파일을 백업하고 이름을 변경해야 합니다. 워커 프로그램이 이 원본 파일을 호출하게 됩니다. Bash mv /var/qmail/bin/qmail-queue /var/qmail/bin/qmail-queue.orig 2. KeyDB 인젝터 스크립트 작성 ( /var/qmail/bin/qmail-queue ) qmail-smtpd가 호출할 새로운 qmail-queue 파일입니다. qmail의 표준 규격인 파일 디스크립터 0(메시지 본문)과 1(인벨로프)을 읽어 즉시 KeyDB로 밀어넣고 종료하여 I/O 속도를 극대화합니다. /var/qmail/bin/qmail-queue 경로에 아래 코드를 작성하고 실행 권한( chmod 755 /var/qmail/bin/qmail-queue )을 부여하십시오. Python #!/usr/bin/env python3 import sys import os import redis import json import uuid def read_envelope(fd): data = b"" while True: try: chunk = os.read(fd, 4096) if not chunk: break data += chunk if b"\x00\x00" in data: break except OSError: break return data def main(): msg_data = sys.stdin.buffer.read() env_data = read_envelope(1) r = redis.Redis(host='127.0.0.1', port=6379, db=0) job_id = str(uuid.uuid4()) payload = { "id": job_id, "msg": msg_data.hex(), "env": env_data.hex() } r.lpush("qmail_keydb_queue", json.dumps(payload)) sys.exit(0) if __name__ == "__main__": main() 3. KeyDB 처리 워커 스크립트 작성 ( /usr/local/bin/keydb-qmail-worker.py ) 이 워커는 백그라운드에서 상시 실행되며, KeyDB에 쌓인 메일을 꺼내 원본 qmail-queue.orig 로 전달합니다. /usr/local/bin/keydb-qmail-worker.py 경로에 아래 코드를 작성하고 실행 권한( chmod 755 /usr/local/bin/keydb-qmail-worker.py )을 부여하십시오. Python #!/usr/bin/env python3 import os import sys import redis import json import time QMAIL_QUEUE_BIN = "/var/qmail/bin/qmail-queue.orig" def process_job(job_json): job = json.loads(job_json) msg_data = bytes.fromhex(job["msg"]) env_data = bytes.fromhex(job["env"]) pipe_msg_r, pipe_msg_w = os.pipe() pipe_env_r, pipe_env_w = os.pipe() pid = os.fork() if pid == 0: os.close(pipe_msg_w) os.close(pipe_env_w) os.dup2(pipe_msg_r, 0) os.dup2(pipe_env_r, 1) os.close(pipe_msg_r) os.close(pipe_env_r) os.execv(QMAIL_QUEUE_BIN, [QMAIL_QUEUE_BIN]) sys.exit(111) else: os.close(pipe_msg_r) os.close(pipe_env_r) os.write(pipe_msg_w, msg_data) os.close(pipe_msg_w) os.write(pipe_env_w, env_data) os.close(pipe_env_w) _, status = os.waitpid(pid, 0) if os.WIFEXITED(status): return os.WEXITSTATUS(status) else: return 111 def main(): r = redis.Redis(host='127.0.0.1', port=6379, db=0) print("Starting KeyDB qmail worker...") while True: try: result = r.brpop("qmail_keydb_queue", timeout=0) if result: _, job_json = result exit_code = process_job(job_json) if exit_code != 0: print(f"qmail-queue exited with code {exit_code}. Re-queueing...") r.rpush("qmail_keydb_queue", job_json) time.sleep(1) except Exception as e: print(f"Worker Error: {e}") time.sleep(1) if __name__ == "__main__": main() 4. 파이썬 라이브러리 설치 및 서비스 구동 위 소스를 실행하기 위해 KeyDB(Redis) 클라이언트 라이브러리를 설치하고 워커를 백그라운드 서비스로 등록해야 합니다. Bash pip3 install redis 워커 스크립트를 systemd 또는 daemontools를 통해 구동하십시오. systemd를 사용하는 경우 아래의 서비스 파일을 생성하여 적용합니다. /etc/systemd/system/keydb-qmail-worker.service Ini, TOML [Unit] Description=KeyDB qmail queue worker After=network.target [Service] Type=simple ExecStart=/usr/local/bin/keydb-qmail-worker.py Restart=always RestartSec=3 User=qmaild [Install] WantedBy=multi-user.target Bash systemctl daemon-reload systemctl enable keydb-qmail-worker systemctl start keydb-qmail-worker