Last active
May 27, 2019 08:00
-
-
Save dam1/209e5ed7e8e9fcad0a46157a1c724735 to your computer and use it in GitHub Desktop.
Create an email with multiple attachment with resumable upload with Google Gmail Api
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fs = require('fs'); | |
var request = require('request'); | |
var EventEmitter = require('events').EventEmitter; | |
var mime = require('mime'); | |
var util = require('util'); | |
function gmailResumableUpload() { | |
this.byteCount = 0; //init variables | |
this.tokens = {}; | |
this.filepath = ''; | |
this.metadata = {}; | |
this.query = ''; | |
this.userId = ''; | |
this.retry = -1; | |
this.host = 'www.googleapis.com'; | |
this.api = '/upload/gmail/v1/users/'; | |
this.api2 = '/drafts'; | |
}; | |
util.inherits(gmailResumableUpload, EventEmitter); | |
//Init the upload by POSTing google for an upload URL (saved to self.location) | |
gmailResumableUpload.prototype.upload = function () { | |
var self = this; | |
var options = { | |
url: 'https://' + self.host + self.api + self.userId + self.api2 + '?uploadType=resumable' + self.query, | |
headers: { | |
'Host': self.host, | |
'Authorization': 'Bearer ' + self.tokens.access_token, | |
'Content-Length': 0, | |
'X-Upload-Content-Length': fs.statSync(self.filepath).size, | |
'X-Upload-Content-Type': 'message/rfc822' | |
}, | |
body: JSON.stringify(self.metadata) | |
}; | |
//Send request and start upload if success | |
request.post(options, function (err, res, body) { | |
if (err || !res.headers.location) { | |
self.emit('error', new Error(err)); | |
self.emit('progress', 'Retrying ...'); | |
if ((self.retry > 0) || (self.retry <= -1)) { | |
self.retry--; | |
self.upload(); // retry | |
} else { | |
return; | |
} | |
} | |
self.location = res.headers.location; | |
self.send(); | |
}); | |
} | |
//Pipes uploadPipe to self.location (Google's Location header) | |
gmailResumableUpload.prototype.send = function () { | |
var self = this; | |
var options = { | |
url: self.location, //self.location becomes the Google-provided URL to PUT to | |
headers: { | |
'Authorization': 'Bearer ' + self.tokens.access_token, | |
'Content-Length': fs.statSync(self.filepath).size - self.byteCount, | |
'Content-Type': 'message/rfc822' | |
} | |
}; | |
try { | |
//creates file stream, pipes it to self.location | |
var uploadPipe = fs.createReadStream(self.filepath, { | |
start: self.byteCount, | |
end: fs.statSync(self.filepath).size | |
}); | |
} catch (e) { | |
self.emit('error', new Error(e)); | |
return; | |
} | |
var health = setInterval(function () { | |
self.getProgress(function (err, res, body) { | |
if (!err && typeof res.headers.range !== 'undefined') { | |
self.emit('progress', res.headers.range.substring(8)); | |
} | |
}); | |
}, 5000); | |
uploadPipe.pipe(request.put(options, function (error, response, body) { | |
clearInterval(health); | |
if (!error) { | |
self.emit('success', body); | |
return; | |
} | |
self.emit('error', new Error(error)); | |
if ((self.retry > 0) || (self.retry <= -1)) { | |
self.retry--; | |
self.getProgress(function (err, res, b) { | |
if (typeof res.headers.range !== 'undefined') { | |
self.byteCount = res.headers.range.substring(8); //parse response | |
} else { | |
self.byteCount = 0; | |
} | |
self.send(); | |
}); | |
} | |
})); | |
} | |
gmailResumableUpload.prototype.getProgress = function (handler) { | |
var self = this; | |
var options = { | |
url: self.location, | |
headers: { | |
'Authorization': 'Bearer ' + self.tokens.access_token, | |
'Content-Length': 0, | |
'Content-Range': 'bytes */' + fs.statSync(self.filepath).size | |
} | |
}; | |
request.put(options, handler); | |
} | |
module.exports = gmailResumableUpload; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var GmailResumableUpload = require('./GmailResumableUpload'); | |
exports.createDraftWithClient = function (client, emailFileMailPath, cb) { | |
var gmailResumableUpload = new GmailResumableUpload(); | |
gmailResumableUpload.tokens = client.credentials; //Google OAuth2 tokens | |
gmailResumableUpload.userId = client.userId; // the gmail email | |
gmailResumableUpload.filepath = emailFileMailPath; // file path of the email, since it's a large email containing attachment you should safe it as a file | |
gmailResumableUpload.metadata = null; | |
// some optional parameters | |
gmailResumableUpload.query = '&supportsTeamDrives=true&'; | |
gmailResumableUpload.retry = 3; | |
gmailResumableUpload.upload(); | |
gmailResumableUpload.on('success', function (success) { | |
cb(null, JSON.parse(success)) | |
}); | |
gmailResumableUpload.on('error', function (error) { | |
cb(error); | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Use Nodemailer to compose the email with the attachments, save the result to a file, then upload it with this.