populate_bounce_message_with_headers (from, to, reason, header, cb) {
        const CRLF = '\r\n';

        const originalMessageId = header.get('Message-Id');

        const bounce_msg_ = config.get('outbound.bounce_message', 'data');
        const bounce_msg_html_ = config.get('outbound.bounce_message_html', 'data');
        const bounce_msg_image_ = config.get('outbound.bounce_message_image', 'data');

        const bounce_header_lines = [];
        const bounce_body_lines = [];
        const bounce_html_lines = [];
        const bounce_image_lines = [];
        let bounce_headers_done = false;

        const values = {
            date: utils.date_to_str(new Date()),
            me:   net_utils.get_primary_host_name(),
            from,
            to,
            subject: header.get_decoded('Subject').trim(),
            recipients: this.todo.rcpt_to.join(', '),
            reason,
            extended_reason: this.todo.rcpt_to.map(recip => {
                if (recip.reason) {
                    return `${recip.original}: ${recip.reason}`;
                }
            }).join('\n'),
            pid: process.pid,
            msgid: `<${utils.uuid()}@${net_utils.get_primary_host_name()}>`,
        };

        bounce_msg_.forEach(line => {
            line = line.replace(/\{(\w+)\}/g, (i, word) => values[word] || '?');

            if (bounce_headers_done == false && line == '') {
                bounce_headers_done = true;
            }
            else if (bounce_headers_done == false) {
                bounce_header_lines.push(line);
            }
            else if (bounce_headers_done == true) {
                bounce_body_lines.push(line);
            }
        });

        const escaped_chars = {
            "&": "amp",
            "<": "lt",
            ">": "gt",
            '"': 'quot',
            "'": 'apos',
            "\r": '#10',
            "\n": '#13'
        };
        const escape_pattern = new RegExp(`[${Object.keys(escaped_chars).join('')}]`, 'g');

        bounce_msg_html_.forEach(line => {
            line = line.replace(/\{(\w+)\}/g, (i, word) => {
                if (word in values) {
                    return String(values[word]).replace(escape_pattern, m => `&${escaped_chars[m]};`);
                }
                else {
                    return '?';
                }
            });

            bounce_html_lines.push(line);
        });

        bounce_msg_image_.forEach(line => {
            bounce_image_lines.push(line)
        });

        const boundary = `boundary_${utils.uuid()}`;
        const bounce_body = [];

        bounce_header_lines.forEach(line => {
            bounce_body.push(`${line}${CRLF}`);
        });
        bounce_body.push(`Content-Type: multipart/report; report-type=delivery-status;${CRLF}    boundary="${boundary}"${CRLF}`);
        // Adding references to original msg id
        if (originalMessageId != '') {
            bounce_body.push(`References: ${originalMessageId.replace(/(\r?\n)*$/, '')}${CRLF}`);
        }

        bounce_body.push(CRLF);
        bounce_body.push(`This is a MIME-encapsulated message.${CRLF}`);
        bounce_body.push(CRLF);

        let boundary_incr = '';
        if (bounce_html_lines.length > 1) {
            boundary_incr = 'a';
            bounce_body.push(`--${boundary}${CRLF}`);
            bounce_body.push(`Content-Type: multipart/related; boundary="${boundary}${boundary_incr}"${CRLF}`);
            bounce_body.push(CRLF);
            bounce_body.push(`--${boundary}${boundary_incr}${CRLF}`);
            boundary_incr = 'b';
            bounce_body.push(`Content-Type: multipart/alternative; boundary="${boundary}${boundary_incr}"${CRLF}`);
            bounce_body.push(CRLF);
        }

        bounce_body.push(`--${boundary}${boundary_incr}${CRLF}`);
        bounce_body.push(`Content-Type: text/plain; charset=us-ascii${CRLF}`);
        bounce_body.push(CRLF);
        bounce_body_lines.forEach(line => {
            bounce_body.push(`${line}${CRLF}`);
        });
        bounce_body.push(CRLF);

        if (bounce_html_lines.length > 1) {
            bounce_body.push(`--${boundary}${boundary_incr}${CRLF}`);
            bounce_body.push(`Content-Type: text/html; charset=us-ascii${CRLF}`);
            bounce_body.push(CRLF);
            bounce_html_lines.forEach(line => {
                bounce_body.push(`${line}${CRLF}`);
            });
            bounce_body.push(CRLF);
            bounce_body.push(`--${boundary}${boundary_incr}--${CRLF}`);

            if (bounce_image_lines.length > 1) {
                boundary_incr = 'a';
                bounce_body.push(`--${boundary}${boundary_incr}${CRLF}`);
                //bounce_body.push(`Content-Type: text/html; charset=us-ascii${CRLF}`);
                //bounce_body.push(CRLF);
                bounce_image_lines.forEach(line => {
                    bounce_body.push(`${line}${CRLF}`);
                });
                bounce_body.push(CRLF);
                bounce_body.push(`--${boundary}${boundary_incr}--${CRLF}`);
            }
        }

        bounce_body.push(`--${boundary}${CRLF}`);
        bounce_body.push(`Content-type: message/delivery-status${CRLF}`);
        bounce_body.push(CRLF);
        if (originalMessageId != '') {
            bounce_body.push(`Original-Envelope-Id: ${originalMessageId.replace(/(\r?\n)*$/, '')}${CRLF}`);
        }
        bounce_body.push(`Reporting-MTA: dns;${net_utils.get_primary_host_name()}${CRLF}`);
        if (this.todo.queue_time) {
            bounce_body.push(`Arrival-Date: ${utils.date_to_str(new Date(this.todo.queue_time))}${CRLF}`);
        }
        this.todo.rcpt_to.forEach(rcpt_to => {
            bounce_body.push(CRLF);
            bounce_body.push(`Final-Recipient: rfc822;${rcpt_to.address()}${CRLF}`);
            let dsn_action = null;
            if (rcpt_to.dsn_action) {
                dsn_action = rcpt_to.dsn_action;
            }
            else if (rcpt_to.dsn_code) {
                if (/^5/.exec(rcpt_to.dsn_code)) {
                    dsn_action = 'failed';
                }
                else if (/^4/.exec(rcpt_to.dsn_code)) {
                    dsn_action = 'delayed';
                }
                else if (/^2/.exec(rcpt_to.dsn_code)) {
                    dsn_action = 'delivered';
                }
            }
            else if (rcpt_to.dsn_smtp_code) {
                if (/^5/.exec(rcpt_to.dsn_smtp_code)) {
                    dsn_action = 'failed';
                }
                else if (/^4/.exec(rcpt_to.dsn_smtp_code)) {
                    dsn_action = 'delayed';
                }
                else if (/^2/.exec(rcpt_to.dsn_smtp_code)) {
                    dsn_action = 'delivered';
                }
            }
            if (dsn_action != null) {
                bounce_body.push(`Action: ${dsn_action}${CRLF}`);
            }
            if (rcpt_to.dsn_status) {
                let { dsn_status } = rcpt_to;
                if (rcpt_to.dsn_code || rcpt_to.dsn_msg) {
                    dsn_status += " (";
                    if (rcpt_to.dsn_code) {
                        dsn_status += rcpt_to.dsn_code;
                    }
                    if (rcpt_to.dsn_code || rcpt_to.dsn_msg) {
                        dsn_status += " ";
                    }
                    if (rcpt_to.dsn_msg) {
                        dsn_status += rcpt_to.dsn_msg;
                    }
                    dsn_status += ")";
                }
                bounce_body.push(`Status: ${dsn_status}${CRLF}`);
            }
            if (rcpt_to.dsn_remote_mta) {
                bounce_body.push(`Remote-MTA: ${rcpt_to.dsn_remote_mta}${CRLF}`);
            }
            let diag_code = null;
            if (rcpt_to.dsn_smtp_code || rcpt_to.dsn_smtp_extc || rcpt_to.dsn_smtp_response) {
                diag_code = "smtp;";
                if (rcpt_to.dsn_smtp_code) {
                    diag_code += `${rcpt_to.dsn_smtp_code} `;
                }
                if (rcpt_to.dsn_smtp_extc) {
                    diag_code += `${rcpt_to.dsn_smtp_extc} `;
                }
                if (rcpt_to.dsn_smtp_response) {
                    diag_code += `${rcpt_to.dsn_smtp_response} `;
                }
            }
            if (diag_code != null) {
                bounce_body.push(`Diagnostic-Code: ${diag_code}${CRLF}`);
            }
        });
        bounce_body.push(CRLF);

        bounce_body.push(`--${boundary}${CRLF}`);
        bounce_body.push(`Content-Description: Undelivered Message Headers${CRLF}`);
        bounce_body.push(`Content-Type: text/rfc822-headers${CRLF}`);
        bounce_body.push(CRLF);
        header.header_list.forEach(line => {
            bounce_body.push(line);
        });
        bounce_body.push(CRLF);

        bounce_body.push(`--${boundary}--${CRLF}`);

        cb(null, bounce_body);
    }
Generates a bounce message

hmail.todo.rcpt_to objects should be extended as follows:
- dsn_action
- dsn_status
- dsn_code
- dsn_msg

- dsn_remote_mta

Upstream code/message goes here:
- dsn_smtp_code
- dsn_smtp_extc
- dsn_smtp_response

@param from
@param to
@param reason
@param header
@param cb - a callback for fn(err, message_body_lines)