diff --git a/packages/component-invite/src/routes/collectionsInvitations/patch.js b/packages/component-invite/src/routes/collectionsInvitations/patch.js
index 6850b04fe8756c965ffdf8e61d6db1e7f9e04098..19e95891cbedfb9e8ec0f0309986e78fe404803b 100644
--- a/packages/component-invite/src/routes/collectionsInvitations/patch.js
+++ b/packages/component-invite/src/routes/collectionsInvitations/patch.js
@@ -27,19 +27,30 @@ module.exports = models => async (req, res) => {
       })
       return
     }
-
-    await collectionHelper.updateHandlingEditor(collection, isAccepted)
+    if (invitation.userId !== user.id) {
+      res.status(403).json({
+        error: `User ${user.email} is not allowed to modify invitation ${
+          invitation.id
+        }`,
+      })
+      return
+    }
+    if (invitation.role === 'handlingEditor')
+      await collectionHelper.updateHandlingEditor(collection, isAccepted)
     invitation.timestamp = Date.now()
     invitation.hasAnswer = true
     const eic = await userHelper.getEditorInChief(models.User)
     if (isAccepted === true) {
       invitation.isAccepted = true
+      let toEmail = eic.email
+      if (invitation.role === 'reviewer')
+        toEmail = collection.handlingEditor.email
       await collection.save()
       try {
-        await mailService.setupHandlingEditorAgreedEmail(
-          eic.email,
+        await mailService.setupAgreeEmail(
+          toEmail,
           user,
-          'handling-editor-agreed',
+          invitation.role,
           `${req.protocol}://${req.get('host')}`,
           collection.customId,
         )
diff --git a/packages/component-invite/src/tests/collectionsInvitations/patch.test.js b/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
index 3a1bec6bb8a6c41358a291ae60247143198db47d..62c4332bd2fbadaba33ceda8f3cfa2a98c6eed90 100644
--- a/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
+++ b/packages/component-invite/src/tests/collectionsInvitations/patch.test.js
@@ -9,7 +9,7 @@ const cloneDeep = require('lodash/cloneDeep')
 const models = Model.build()
 jest.mock('pubsweet-component-mail-service', () => ({
   setupAssignEmail: jest.fn(),
-  setupHandlingEditorAgreedEmail: jest.fn(),
+  setupAgreeEmail: jest.fn(),
   setupDeclineEmail: jest.fn(),
 }))
 
@@ -32,7 +32,26 @@ describe('Patch collections invitations route handler', () => {
     })
     req.user = handlingEditor.id
     req.params.collectionId = collection.id
-    req.params.invitationId = collection.invitations[0].id
+    const heInv = collection.invitations.find(
+      inv => inv.role === 'handlingEditor',
+    )
+    req.params.invitationId = heInv.id
+    const res = httpMocks.createResponse()
+    await require(patchPath)(models)(req, res)
+    expect(res.statusCode).toBe(200)
+  })
+  it('should return success when the reviewer agrees work on a collection', async () => {
+    const { reviewer } = testFixtures.users
+    const { collection } = testFixtures.collections
+    const req = httpMocks.createRequest({
+      body,
+    })
+    req.user = reviewer.id
+    req.params.collectionId = collection.id
+    const reviewerInv = collection.invitations.find(
+      inv => inv.role === 'reviewer',
+    )
+    req.params.invitationId = reviewerInv.id
     const res = httpMocks.createResponse()
     await require(patchPath)(models)(req, res)
     expect(res.statusCode).toBe(200)
@@ -99,4 +118,24 @@ describe('Patch collections invitations route handler', () => {
     const data = JSON.parse(res._getData())
     expect(data.error).toEqual('Invitation invalid-id not found')
   })
+  it("should return an error when a user tries to patch another user's invitation", async () => {
+    const { reviewer } = testFixtures.users
+    const { collection } = testFixtures.collections
+    const req = httpMocks.createRequest({
+      body,
+    })
+    req.user = reviewer.id
+    req.params.collectionId = collection.id
+    const inv = collection.invitations.find(
+      inv => inv.role === 'handlingEditor',
+    )
+    req.params.invitationId = inv.id
+    const res = httpMocks.createResponse()
+    await require(patchPath)(models)(req, res)
+    expect(res.statusCode).toBe(403)
+    const data = JSON.parse(res._getData())
+    expect(data.error).toEqual(
+      `User ${reviewer.email} is not allowed to modify invitation ${inv.id}`,
+    )
+  })
 })
diff --git a/packages/component-invite/src/tests/fixtures/collections.js b/packages/component-invite/src/tests/fixtures/collections.js
index b0dba9b453dfd87051819890335cd5e82f0b1e8a..78920b4aa04df9a88ae59d850cf3daa0fb95d4bb 100644
--- a/packages/component-invite/src/tests/fixtures/collections.js
+++ b/packages/component-invite/src/tests/fixtures/collections.js
@@ -1,5 +1,5 @@
 const Chance = require('chance')
-const { user, handlingEditor, author } = require('./userData')
+const { user, handlingEditor, author, reviewer } = require('./userData')
 const { fragment } = require('./fragments')
 
 const chance = new Chance()
@@ -27,6 +27,14 @@ const collections = {
         userId: handlingEditor.id,
         timestamp: chance.timestamp(),
       },
+      {
+        id: chance.guid(),
+        role: 'reviewer',
+        hasAnswer: false,
+        isAccepted: false,
+        userId: reviewer.id,
+        timestamp: chance.timestamp(),
+      },
     ],
     handlingEditor: {
       id: handlingEditor.id,
diff --git a/packages/component-invite/src/tests/fixtures/userData.js b/packages/component-invite/src/tests/fixtures/userData.js
index de7459c0deabe1dc45b725d355bb609394fef0fc..a7046079c834babe37fbf2524fd9349b4368f04a 100644
--- a/packages/component-invite/src/tests/fixtures/userData.js
+++ b/packages/component-invite/src/tests/fixtures/userData.js
@@ -1,27 +1,17 @@
 const Chance = require('chance')
 
 const chance = new Chance()
+const generateUserData = () => ({
+  id: chance.guid(),
+  email: chance.email(),
+  firstName: chance.first(),
+  lastName: chance.last(),
+})
+
 module.exports = {
-  handlingEditor: {
-    id: chance.guid(),
-    email: chance.email(),
-    firstName: chance.first(),
-    lastName: chance.last(),
-  },
-  user: {
-    id: chance.guid(),
-    email: chance.email(),
-    firstName: chance.first(),
-    lastName: chance.last(),
-  },
-  admin: {
-    id: chance.guid(),
-    email: chance.email(),
-  },
-  author: {
-    id: chance.guid(),
-    email: chance.email(),
-    firstName: chance.first(),
-    lastName: chance.last(),
-  },
+  handlingEditor: generateUserData(),
+  user: generateUserData(),
+  admin: generateUserData(),
+  author: generateUserData(),
+  reviewer: generateUserData(),
 }
diff --git a/packages/component-invite/src/tests/fixtures/users.js b/packages/component-invite/src/tests/fixtures/users.js
index c36f0a74c4b33715e771c53c2798f3614b06fe99..c474cfc7ad10a44ef6d65e7d1b4665d42ce074d9 100644
--- a/packages/component-invite/src/tests/fixtures/users.js
+++ b/packages/component-invite/src/tests/fixtures/users.js
@@ -1,5 +1,5 @@
 const { heTeamID } = require('./teamIDs')
-const { handlingEditor, user, admin, author } = require('./userData')
+const { handlingEditor, user, admin, author, reviewer } = require('./userData')
 const Chance = require('chance')
 
 const chance = new Chance()
@@ -8,6 +8,8 @@ const users = {
     type: 'user',
     username: 'admin',
     email: admin.email,
+    firstName: admin.firstName,
+    lastName: admin.lastName,
     password: 'test',
     admin: true,
     id: admin.id,
@@ -71,6 +73,20 @@ const users = {
     save: jest.fn(() => users.author),
     isConfirmed: true,
   },
+  reviewer: {
+    type: 'user',
+    username: chance.word(),
+    email: reviewer.email,
+    password: 'password',
+    admin: false,
+    id: reviewer.id,
+    firstName: reviewer.firstName,
+    lastName: reviewer.lastName,
+    affiliation: chance.company(),
+    title: 'Mr',
+    save: jest.fn(() => users.reviewer),
+    isConfirmed: true,
+  },
 }
 
 module.exports = users
diff --git a/packages/component-mail-service/src/Mail.js b/packages/component-mail-service/src/Mail.js
index 6e53819af265a36240a1878f8d369c1f2f868a04..3f051acb65a7ba87425e201c2b788ea1beca1021 100644
--- a/packages/component-mail-service/src/Mail.js
+++ b/packages/component-mail-service/src/Mail.js
@@ -91,22 +91,24 @@ module.exports = {
     }
     return Email.send(mailData)
   },
-  setupHandlingEditorAgreedEmail: async (
-    toEmail,
-    user,
-    emailType,
-    url,
-    collectionId,
-  ) => {
-    const { htmlBody, textBody } = getEmailBody(emailType, {
+  setupAgreeEmail: async (toEmail, user, invRole, url, collectionId) => {
+    let role = 'Handling Editor'
+    let subject = 'Handling Editor Agreed'
+    if (invRole === 'reviewer') {
+      subject = 'Reviewer Agreed'
+      role = 'Reviewer'
+    }
+    const { htmlBody, textBody } = getEmailBody('agree', {
       url,
+      role,
       name: `${user.firstName} ${user.lastName}`,
       collectionId,
     })
+
     const mailData = {
       from: config.get('mailer.from'),
       to: toEmail,
-      subject: 'Handling Editor Agreed',
+      subject,
       text: textBody,
       html: htmlBody,
     }
@@ -152,6 +154,8 @@ module.exports = {
       agreeUrl = `${baseUrl}${resetPath}?${querystring.encode({
         email: invitedUser.email,
         token: invitedUser.passwordResetToken,
+        collectionId: collection.id,
+        agree: true,
       })}`
     }
 
diff --git a/packages/component-mail-service/src/templates/handling-editor-agreed.html b/packages/component-mail-service/src/templates/agree.html
similarity index 98%
rename from packages/component-mail-service/src/templates/handling-editor-agreed.html
rename to packages/component-mail-service/src/templates/agree.html
index 3f24b1f4216f3d8554def6a0bc63fc80fb4afa36..edf453b48652d2035e12eda8b4a8a64aea03868b 100644
--- a/packages/component-mail-service/src/templates/handling-editor-agreed.html
+++ b/packages/component-mail-service/src/templates/agree.html
@@ -145,7 +145,7 @@
                                 width="100%" style="display: none !important; mso-hide: all; visibility: hidden; opacity: 0; color: transparent; height: 0; width: 0;">
                                 <tr>
                                   <td role="module-content">
-                                    <p>handling editor agreed</p>
+                                    <p>a user has agreed</p>
                                   </td>
                                 </tr>
                               </table>
@@ -163,7 +163,7 @@
                               <table class="module" role="module" data-type="text" border="0" cellpadding="0" cellspacing="0" width="100%" style="table-layout: fixed;">
                                 <tr>
                                   <td style="padding:30px 23px 0px 23px;background-color:#ffffff;" height="100%" valign="top" bgcolor="#ffffff">
-                                    <h1 style="text-align: center;">{{ name }} has agreed to be Handling Editor on manuscript {{ collectionId }}</h1>
+                                    <h1 style="text-align: center;">{{ name }} has agreed to be a {{ role }} on manuscript {{ collectionId }}.</h1>
 
                                     <div style="text-align: center;">Please click on the link below to access your dashboard.</div>
 
diff --git a/packages/component-mail-service/src/templates/handling-editor-agreed.txt b/packages/component-mail-service/src/templates/agree.txt
similarity index 68%
rename from packages/component-mail-service/src/templates/handling-editor-agreed.txt
rename to packages/component-mail-service/src/templates/agree.txt
index 550581b4489de9dca0da675eb4c3da2db498d815..ea941f3dd075d300a0d769130ad7698e165508c2 100644
--- a/packages/component-mail-service/src/templates/handling-editor-agreed.txt
+++ b/packages/component-mail-service/src/templates/agree.txt
@@ -1,4 +1,4 @@
-{{ name }} has agreed to be Handling Editor on manuscript {{ collectionId }}
+{{ name }} has agreed to be a {{ role }} on manuscript {{ collectionId }}
 Please click on the link below to access your dashboard
 {{ url }} VIEW DASHBOARD
 Hindawi Publishing Corporation