diff --git a/packages/helpers/classes/mail.d.ts b/packages/helpers/classes/mail.d.ts index f3246b804..65ba9329f 100644 --- a/packages/helpers/classes/mail.d.ts +++ b/packages/helpers/classes/mail.d.ts @@ -155,6 +155,8 @@ export interface MailData { dynamicTemplateData?: { [key: string]: any }, hideWarnings?: boolean, + + replyToList?: EmailJSON | EmailJSON[], } export type MailDataRequired = MailData & ( @@ -179,6 +181,7 @@ export interface MailJSON { batch_id?: string; template_id?: string; ip_pool_name?: string; + reply_to_list?: EmailJSON[]; } export default class Mail { @@ -353,4 +356,9 @@ export default class Mail { * Create a Mail instance from given data */ static create(data: MailData[]): Mail[]; + + /** + * Set reply_to_list header from given data + */ + setReplyToList(replyToList: EmailJSON[]): void; } diff --git a/packages/helpers/classes/mail.js b/packages/helpers/classes/mail.js index ac47128dc..9fdf93374 100644 --- a/packages/helpers/classes/mail.js +++ b/packages/helpers/classes/mail.js @@ -68,7 +68,7 @@ class Mail { templateId, personalizations, attachments, ipPoolName, batchId, sections, headers, categories, category, customArgs, asm, mailSettings, trackingSettings, substitutions, substitutionWrappers, dynamicTemplateData, isMultiple, - hideWarnings, + hideWarnings, replyToList, } = data; //Set data @@ -90,6 +90,7 @@ class Mail { this.setMailSettings(mailSettings); this.setTrackingSettings(trackingSettings); this.setHideWarnings(hideWarnings); + this.setReplyToList(replyToList); if (this.isDynamic) { this.setDynamicTemplateData(dynamicTemplateData); @@ -504,7 +505,7 @@ class Mail { from, replyTo, sendAt, subject, content, templateId, personalizations, attachments, ipPoolName, batchId, asm, sections, headers, categories, customArgs, mailSettings, - trackingSettings, + trackingSettings, replyToList, } = this; //Initialize with mandatory values @@ -560,6 +561,9 @@ class Mail { if (typeof ipPoolName !== 'undefined') { json.ipPoolName = ipPoolName; } + if(typeof replyToList !== 'undefined') { + json.replyToList = replyToList; + } //Return as snake cased object return toSnakeCase(json, ['substitutions', 'dynamicTemplateData', 'customArgs', 'headers', 'sections']); @@ -667,6 +671,19 @@ class Mail { value, [this._checkUndefined, this._createCheckThatThrows(Array.isArray, 'Array expected for`' + propertyName + '`')]); } + + /** + * Set the replyToList from email body + */ + setReplyToList(replyToList) { + if (this._doArrayCheck('replyToList', replyToList) && replyToList.length) { + if (!replyToList.every(replyTo => replyTo && typeof replyTo.email === 'string')) { + throw new Error('Expected each replyTo to contain a `email` string'); + } + // this.replyToList = EmailAddress.create(replyToList); + this.replyToList = replyToList; + } + } } //Export class diff --git a/packages/mail/src/mail.spec.js b/packages/mail/src/mail.spec.js index 936b799a2..ec517e7c7 100644 --- a/packages/mail/src/mail.spec.js +++ b/packages/mail/src/mail.spec.js @@ -17,7 +17,7 @@ before(() => { * Default mock header */ beforeEach(() => { - sgClient.setDefaultHeader('X-Mock', 200); + sgClient.setDefaultHeader('X-Mock', 202); }); /** @@ -38,12 +38,12 @@ describe('sgMail.send()', () => { return expect(sgMail.send()).to.eventually.be.rejectedWith(Error); }); - it('should send a basic email', () => { - sgClient.setDefaultHeader('X-Mock', 201); + it('should send a basic email', async () => { + sgClient.setDefaultHeader('X-Mock', 202); return sgMail .send(data) .then(([response, body]) => { - expect(response.statusCode).to.equal(201); + expect(response.statusCode).to.equal(202); }); }); @@ -53,13 +53,13 @@ describe('sgMail.send()', () => { }).to.throw(Error); }); - it('should include custom headers to the request', () => { - sgClient.setDefaultHeader('X-Mock', 201); + it('should include custom headers to the request', async () => { + sgClient.setDefaultHeader('X-Mock', 202); const clientSpy = sinon.spy(sgClient, "request") return sgMail .send(Object.assign(data, { headers: { customHeader: "Custom Header Content" } })) .then(([response, body]) => { - expect(response.statusCode).to.equal(201); + expect(response.statusCode).to.equal(202); expect(clientSpy).to.have.been.calledWith(sinon.match({ url: "/v3/mail/send", method: "POST", @@ -67,5 +67,70 @@ describe('sgMail.send()', () => { })); }); }); + + it('should send email with correct replyToList format', async () => { + sgClient.setDefaultHeader('X-Mock', 202); + data["replyToList"] = [ + { + "name": "Test Team", + "email": "test@example.org" + }, + { + "name": "Support Test Team", + "email": "support.test@example.org" + } + ]; + return sgMail + .send(data) + .then(([response, body]) => { + expect(response.statusCode).to.equal(202); + }); + }); + + it('should throw error with wrong replyToList format', async () => { + sgClient.setDefaultHeader('X-Mock', 202); + data["replyToList"] = { + "name": "Support Test Team", + "email": "support.test@example.org" + }; + return expect(function() { + sgMail.send(data, false, {}); + }).to.throw(Error); + }); + + it('should throw error if any record in replyToList is without email', async () => { + data["replyToList"] = [ + { + "name": "Test Team", + "email": "test@example.org" + }, + { + "name": "Support Test Team" + } + ]; + return expect(function() { + sgMail.send(data, false, {}); + }).to.throw(Error); + }); + + it('should throw error if both replyTo and replyToList are mentioned', async () => { + data["replyTo"] = { + "name": "Manual Tester", + "email": "manual.test@example.org" + }; + data["replyToList"] = [ + { + "name": "Test Team", + "email": "test@example.org" + }, + { + "name": "Support Test Team", + "email": "support.test@example.org" + } + ]; + return expect(function() { + sgMail.send(data, false, {}); + }).to.throw(Error); + }); });