• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

haraka / Haraka / 26107975229

19 May 2026 03:39PM UTC coverage: 71.554% (-0.05%) from 71.6%
26107975229

push

github

web-flow
change: replace forEach with es6 style for...of (#3569)

1719 of 2239 branches covered (76.78%)

33 of 52 new or added lines in 6 files covered. (63.46%)

3 existing lines in 1 file now uncovered.

7682 of 10736 relevant lines covered (71.55%)

21.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

30.93
/plugins/queue/qmail-queue.js
1
// Queue to qmail-queue
5✔
2

5✔
3
const childproc = require('node:child_process')
5✔
4
const fs = require('node:fs')
5✔
5

5✔
6
exports.register = function () {
5✔
7
    this.queue_exec = this.config.get('qmail-queue.path') || '/var/qmail/bin/qmail-queue'
1✔
8
    if (!fs.existsSync(this.queue_exec)) {
1✔
9
        throw new Error(`Cannot find qmail-queue binary (${this.queue_exec})`)
1✔
10
    }
1✔
11

1✔
12
    this.load_qmail_queue_ini()
1!
13

×
14
    if (this.cfg.main.enable_outbound) {
×
15
        this.register_hook('queue_outbound', 'hook_queue')
×
16
    }
×
17
}
×
18

×
19
exports.load_qmail_queue_ini = function () {
5✔
20
    this.cfg = this.config.get(
4✔
21
        'qmail-queue.ini',
4✔
22
        {
4✔
23
            booleans: ['+main.enable_outbound'],
4✔
24
        },
4✔
25
        () => {
4✔
26
            this.load_qmail_queue_ini()
4✔
27
        },
×
28
    )
×
29
}
×
30

×
31
exports.hook_queue = function (next, connection) {
5✔
32
    const plugin = this
3✔
33

3✔
34
    const txn = connection?.transaction
3✔
35
    if (!txn) return next()
3✔
36

1✔
37
    const q_wants = txn.notes.get('queue.wants')
3✔
38
    if (q_wants && q_wants !== 'qmail-queue') return next()
3✔
39

2✔
40
    const qmail_queue = childproc.spawn(
3!
41
        this.queue_exec, // process name
×
42
        [], // arguments
×
43
        { stdio: ['pipe', 'pipe', process.stderr] },
×
44
    )
×
45

×
46
    qmail_queue.on('exit', function finished(code) {
×
47
        if (code !== 0) {
×
48
            connection.logerror(plugin, `Unable to queue message to qmail-queue: ${code}`)
×
49
            next()
×
50
        } else {
×
51
            next(OK, 'Queued!')
×
52
        }
×
53
    })
×
54

×
55
    connection.transaction.message_stream.pipe(qmail_queue.stdin, {
×
56
        line_endings: '\n',
×
57
    })
×
58

×
59
    qmail_queue.stdin.on('close', () => {
×
60
        if (!connection?.transaction) {
×
61
            plugin.logerror('Transaction went away while delivering mail to qmail-queue')
×
62
            try {
×
63
                qmail_queue.stdout.end()
×
64
            } catch (err) {
×
65
                if (err.code !== 'ENOTCONN') {
×
66
                    // Ignore ENOTCONN and re throw anything else
×
67
                    throw err
×
68
                }
×
69
            }
×
70

×
71
            connection.results.add(plugin, { err: 'dead sender' })
×
72
            return
×
73
        }
×
74
        plugin.loginfo('Message Stream sent to qmail. Now sending envelope')
×
75
        // now send envelope
×
76
        // Hope this will be big enough...
×
77
        const buf = Buffer.alloc(4096)
×
78
        let p = 0
×
79
        buf[p++] = 70
×
80
        const mail_from = connection.transaction.mail_from.address()
×
81
        for (let i = 0; i < mail_from.length; i++) {
×
82
            buf[p++] = mail_from.charCodeAt(i)
×
83
        }
×
84
        buf[p++] = 0
×
NEW
85
        for (const rcpt of connection.transaction.rcpt_to) {
×
86
            buf[p++] = 84
×
87
            const rcpt_to = rcpt.address()
×
88
            for (let j = 0; j < rcpt_to.length; j++) {
×
89
                buf[p++] = rcpt_to.charCodeAt(j)
×
90
            }
×
91
            buf[p++] = 0
×
NEW
92
        }
×
93
        buf[p++] = 0
×
94
        qmail_queue.stdout.on('error', (err) => {}) // stdout throws an error on close
×
95
        qmail_queue.stdout.end(buf)
×
96
    })
×
97
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc