<|start_filename|>test/resources/testEmail.html<|end_filename|>
<div dir="ltr">
    <img src="https://mailosaur.com/favicon.ico" />
    <div style="font-family:arial,sans-serif;font-size:13px;color:rgb(80,0,80)">this is a test.</div>
    <div style="font-family:arial,sans-serif;font-size:13px;color:rgb(80,0,80)">
        <br>this is a link:
        <a href="https://mailosaur.com/" target="_blank">mailosaur</a>
        <br>
    </div>
    <div class="gmail_quote" style="font-family:arial,sans-serif;font-size:13px;color:rgb(80,0,80)">
        <div dir="ltr">
            <div>
                REPLACED_DURING_TEST html
                <br>
            </div>
            <div>this is an image:
                <a href="https://mailosaur.com/" target="_blank">
                    <img src="cid:ii_1435fadb31d523f6" alt="Inline image 1">
                </a>
            </div>
            <div>
                <br>
            </div>
            <div>this is an invalid link:
                <a href="http://invalid/" target="_blank">invalid</a>
            </div>
        </div>
    </div>
</div>

<|start_filename|>lib/request.js<|end_filename|>
const https = require('https');
const HttpsProxyAgent = require('https-proxy-agent');
const url = require('url');
const pkg = require('../package.json');

class Request {
  constructor(options) {
    this.baseUrl = options.baseUrl || 'https://mailosaur.com/';
    const encodedKey = Buffer.from(`${options.apiKey}:`).toString('base64');
    this.headers = {
      Accept: 'application/json',
      Authorization: `Basic ${encodedKey}`,
      'User-Agent': options.agent || `mailosaur-node/${pkg.version}`
    };
    const httpProxy = process.env.https_proxy || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.HTTP_PROXY;
    if (httpProxy) {
      this.proxyAgent = new HttpsProxyAgent(httpProxy);
    }
  }

  buildOptions(method, path, options = {}) {
    const result = {
      method,
      url: `${this.baseUrl}${path}`,
      headers: {
        Accept: this.headers.Accept,
        Authorization: this.headers.Authorization,
        'User-Agent': this.headers['User-Agent']
      }
    };

    if (options.buffer) {
      result.buffer = true;
    }

    if (options.qs) {
      Object.keys(options.qs).forEach((key, index) => {
        let value = options.qs[key];
        if (!value) {
          return;
        }
        if (value instanceof Date) {
          value = value.toISOString();
        }
        const prefix = !index ? '?' : '&';
        result.url += `${prefix}${key}=${value}`;
      });
    }

    if (options.body) {
      const data = JSON.stringify(options.body);
      result.data = Buffer.from(data);
      result.headers['Content-Type'] = 'application/json';
      result.headers['Content-Length'] = Buffer.byteLength(result.data);
    }

    if (this.proxyAgent) {
      result.agent = this.proxyAgent;
    }
    return result;
  }

  invoke(options, callback) {
    let urlResult;

    // Fallback to legacy parsing if `URL` not a constructor
    try {
      urlResult = new url.URL(options.url);
    } catch (e) {
      urlResult = url.parse(options.url);
    }

    // Ignoring as spread is not compatible with Node 6
    // eslint-disable-next-line prefer-object-spread
    const spread = Object.assign({}, options, {
      protocol: urlResult.protocol,
      hostname: urlResult.hostname,
      path: urlResult.pathname + urlResult.search
    });
    const req = https.request(spread, (res) => {
      const data = [];
      res.on('data', (chunk) => data.push(chunk));
      res.on('end', () => {
        try {
          if (data) {
            res.body = options.buffer ?
              Buffer.concat(data) :
              JSON.parse(Buffer.concat(data).toString());
          }
        } catch (e) {
          res.body = data;
        }

        callback(null, res, res.body);
      });
    });

    req.on('error', (e) => callback(e));

    if (options.data) {
      req.write(options.data);
    }

    req.end();
  }

  request(method, path, options, callback) {
    /* eslint-disable no-param-reassign */
    if (typeof options === 'function') {
      callback = options;
      options = undefined;
    }
    /* eslint-enable no-param-reassign */

    const requestOptions = this.buildOptions(method, path, options);
    this.invoke(requestOptions, callback);
  }

  get(path, options, callback) {
    this.request('GET', path, options, callback);
  }

  put(path, options, callback) {
    this.request('PUT', path, options, callback);
  }

  post(path, options, callback) {
    this.request('POST', path, options, callback);
  }

  del(path, options, callback) {
    this.request('DELETE', path, options, callback);
  }
}

module.exports = Request;
