Uses /messages.mime endpoint
Opened this issue · 4 comments
gabegorelick commented
It seems like a more robust approach would be to use Mailgun's /messages.mime
endpoint to send raw emails. This is what the nodemailer-ses-transport does, for example: nodemailer already gives you the mime-formatted email, and all you need to do is pipe that to Mailgun.
orliesaurus commented
Would you like to send a pull request with that feature please? It sounds like a nice thing to have
duanefields commented
here's an implementation of just that (coffeescript)
axios = require 'axios'
FormData = require 'form-data'
module.exports = class MailgunMIMETransport
name: "MailgunMIMETransport"
version: "1.0.0"
constructor: (@options={}) ->
send: (mail, callback) =>
mailStream = mail.message.createReadStream()
this.readStream mailStream, (err, raw) =>
if err?
return typeof callback is 'function' and callback(err)
this.handleMessage mail, raw, callback
readStream: (mailStream, callback) ->
chunks = []
totalLength = 0
mailStream.on 'data', (chunk) ->
chunks.push chunk
totalLength += chunk.length
mailStream.on 'end', ->
callback null, Buffer.concat(chunks, totalLength).toString()
handleMessage: (mail, raw, callback) ->
envelope = mail.message.getEnvelope()
form = new FormData()
form.append "to", envelope.to.join ','
form.append "message", raw, 'message.eml'
requestOptions =
baseURL: "https://api.mailgun.net/v3/#{@options.domain}"
headers: form.getHeaders()
auth:
username: 'api'
password: @options.apiKey
axios.post '/messages.mime', form, requestOptions
.then (result) ->
response = result.data
info =
envelope: envelope
response: response.message
messageId: response.id
if typeof callback is 'function' then callback(null, info) else info
.catch (err) ->
return typeof callback is 'function' and callback(err)
gabegorelick commented
Here's a JS version:
const nodemailer = require('nodemailer');
const mailgun = require('mailgun-js')();
class MailgunTransport {
constructor (options) {
this.name = 'Mailgun';
this.version = '1.0.0';
this.mailgun = mailgun(options);
}
send (mail, callback) {
const envelope = mail.data.envelope || mail.message.getEnvelope();
const stream = mail.message.createReadStream();
stream.once('error', callback);
const chunks = [];
let chunkLength = 0;
stream.on('readable', () => {
let chunk;
while ((chunk = stream.read()) !== null) {
chunks.push(chunk);
chunkLength += chunk.length;
}
});
stream.on('end', () => {
const mimeMessage = Buffer.concat(chunks, chunkLength);
this.mailgun.messages().sendMime({
to: envelope.to.join(','), // envelope.to contains the message's To, CC, and BCC
message: mimeMessage.toString('ascii') // nodemailer encodes with quoted-printable, so it's already ASCII
}, (err, body) => {
if (err) {
return callback(err);
}
return callback(null, {
envelope: {
from: envelope.from,
to: envelope.to
},
response: body,
messageId: body.id
});
});
});
}
}
Happy to throw up a PR, but this would potentially be a breaking change.
orliesaurus commented
Mmmh I don't know about this one ultimately - I don't want to upset all the people - unless it was properly documented and unit tests are added, it'll have to wait :)