Cannot change email address with patch user API

We have a web app which provides central control for our user’s Mattermost, Discourse and Nextcloud accounts.

The Mattermost instance is shared with our world wide organisation, and we in the UK do not have admin access to it.

We very much want our users to be able to change their email address in one place (on our web app system). We already use Mattermost’s OAuth2 facility to gain an access token to Mattermost on behalf of the user.

According to the Mattermost API documentation, we should be able to change the user’s email address by sending a PUT request to users/userid/patch with a payload containing a new email address in the email field.

While calling this method with the email field set to the existing value of the email field works, setting it to a new email doesn’t. Here is a log:

Mattermost log:Sent -> Method: GET, RequestUri: 'http://xr:8080/api/v4/users/me', Version: 2.0, Content: <null>, Headers:
{
  Authorization: Bearer 6j1pj1c4ci8qiq6zhig8er3moa
  Accept: application/json
  Accept: text/html
  Accept: */*
  User-Agent: XR
  User-Agent: Mattermost
  User-Agent: Tool
}:
Mattermost log:Received -> StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
  Server: nginx
  Date: Fri, 28 Aug 2020 15:39:55 GMT
  Connection: keep-alive
  ETag: 5.23.0.q6zs1g6t87dc5dxqhfphqxw5se.1598628372342..0.true.false.0
  Vary: Accept-Encoding
  X-Ratelimit-Limit: 101
  X-Ratelimit-Remaining: 99
  X-Ratelimit-Reset: 1
  X-Request-ID: ptn75rrd8jrnjg77qpygp5a4th
  X-Version-Id: 5.23.0.5.23.1.6f92c357503d0c8e07dec8e7e2ef5d5a.false
  X-Frame-Options: SAMEORIGIN
  X-Content-Type-Options: nosniff
  X-XSS-Protection: 1; mode=block
  Content-Type: application/json
  Content-Length: 528
  Expires: 0
}
Mattermost log:Received Data -> {
  "id": "q6zs1g6t87dc5dxqhfphqxw5se",
  "create_at": 1581348111471,
  "update_at": 1598628372342,
  "delete_at": 0,
  "username": "test",
  "auth_data": "",
  "auth_service": "",
  "email": "nikki@test.net",
  "email_verified": true,
  "nickname": "Nikki",
  "first_name": "",
  "last_name": "Nikki",
  "position": "",
  "roles": "system_user",
  "notify_props": {
	"email": "false",
	"mention_keys": "test,@test"
  },
  "last_password_update": 1597433515412,
  "locale": "en",
  "timezone": {
	"automaticTimezone": "",
	"manualTimezone": "",
	"useAutomaticTimezone": "true"
  },
  "MetaData": {
	"Uri": "http://xr:8080/api/v4/users/me"
  }
}
Mattermost log:Sent -> Method: PUT, RequestUri: 'http://xr:8080/api/v4/users/q6zs1g6t87dc5dxqhfphqxw5se/patch', Version: 2.0, Content: System.Net.Http.StringContent, Headers:
{
  Authorization: Bearer 6j1pj1c4ci8qiq6zhig8er3moa
  Accept: application/json
  Accept: text/html
  Accept: */*
  User-Agent: XR
  User-Agent: Mattermost
  User-Agent: Tool
  Content-Type: application/json; charset=utf-8
}:{
  "email": "nikki@test.net"
}
Mattermost log:Received -> StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
  Server: nginx
  Date: Fri, 28 Aug 2020 15:39:55 GMT
  Connection: keep-alive
  Vary: Accept-Encoding
  X-Ratelimit-Limit: 101
  X-Ratelimit-Remaining: 100
  X-Ratelimit-Reset: 1
  X-Request-ID: gby4dpwiofbn7fdkdkumfec1ga
  X-Version-Id: 5.23.0.5.23.1.6f92c357503d0c8e07dec8e7e2ef5d5a.false
  X-Frame-Options: SAMEORIGIN
  X-Content-Type-Options: nosniff
  X-XSS-Protection: 1; mode=block
  Content-Type: application/json
  Content-Length: 528
}
Mattermost log:Received Data -> {
  "id": "q6zs1g6t87dc5dxqhfphqxw5se",
  "create_at": 1581348111471,
  "update_at": 1598629195484,
  "delete_at": 0,
  "username": "test",
  "auth_data": "",
  "auth_service": "",
  "email": "nikki@test.net",
  "email_verified": true,
  "nickname": "Nikki",
  "first_name": "",
  "last_name": "Nikki",
  "position": "",
  "roles": "system_user",
  "notify_props": {
	"email": "false",
	"mention_keys": "test,@test"
  },
  "last_password_update": 1597433515412,
  "locale": "en",
  "timezone": {
	"automaticTimezone": "",
	"manualTimezone": "",
	"useAutomaticTimezone": "true"
  },
  "MetaData": {
	"Uri": "http://xr:8080/api/v4/users/q6zs1g6t87dc5dxqhfphqxw5se/patch"
  }
}
Mattermost log:Sent -> Method: PUT, RequestUri: 'http://xr:8080/api/v4/users/q6zs1g6t87dc5dxqhfphqxw5se/patch', Version: 2.0, Content: System.Net.Http.StringContent, Headers:
{
  Authorization: Bearer 6j1pj1c4ci8qiq6zhig8er3moa
  Accept: application/json
  Accept: text/html
  Accept: */*
  User-Agent: XR
  User-Agent: Mattermost
  User-Agent: Tool
  Content-Type: application/json; charset=utf-8
}:{
  "email": "test9999@example.com"
}
Mattermost log:Received -> StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
  Server: nginx
  Date: Fri, 28 Aug 2020 15:39:55 GMT
  Connection: keep-alive
  Vary: Accept-Encoding
  X-Ratelimit-Limit: 101
  X-Ratelimit-Remaining: 99
  X-Ratelimit-Reset: 1
  X-Request-ID: d8n4xd839jbeujn7d89ypt56nw
  X-Version-Id: 5.23.0.5.23.1.6f92c357503d0c8e07dec8e7e2ef5d5a.false
  Content-Type: application/json
  Content-Length: 179
}
Mattermost log:Received Data -> {
  "id": "api.context.permissions.app_error",
  "message": "You do not have the appropriate permissions.",
  "detailed_error": "",
  "request_id": "d8n4xd839jbeujn7d89ypt56nw",
  "status_code": 403,
  "MetaData": {
	"Error": {
	  "id": "api.context.permissions.app_error",
	  "message": "You do not have the appropriate permissions.",
	  "detailed_error": "",
	  "request_id": "d8n4xd839jbeujn7d89ypt56nw",
	  "status_code": 403
	},
	"Uri": "http://xr:8080/api/v4/users/q6zs1g6t87dc5dxqhfphqxw5se/patch"
  }
}	Mattermost log:Sent -> Method: PUT, RequestUri: 'http://xr:8080/api/v4/users/me/patch', Version: 2.0, Content: System.Net.Http.StringContent, Headers:
{
  Authorization: Bearer 6j1pj1c4ci8qiq6zhig8er3moa
  Accept: application/json
  Accept: text/html
  Accept: */*
  User-Agent: XR
  User-Agent: Mattermost
  User-Agent: Tool
  Content-Type: application/json; charset=utf-8
}:{
  "email": "test9999@example.com"
}
Mattermost log:Received -> StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.HttpConnection+HttpConnectionResponseContent, Headers:
{
  Server: nginx
  Date: Fri, 28 Aug 2020 15:39:55 GMT
  Connection: keep-alive
  Vary: Accept-Encoding
  X-Ratelimit-Limit: 101
  X-Ratelimit-Remaining: 98
  X-Ratelimit-Reset: 1
  X-Request-ID: sm4iqbnf77dqpfcosrcsat8a3r
  X-Version-Id: 5.23.0.5.23.1.6f92c357503d0c8e07dec8e7e2ef5d5a.false
  Content-Type: application/json
  Content-Length: 179
}
Mattermost log:Received Data -> {
  "id": "api.context.permissions.app_error",
  "message": "You do not have the appropriate permissions.",
  "detailed_error": "",
  "request_id": "sm4iqbnf77dqpfcosrcsat8a3r",
  "status_code": 403,
  "MetaData": {
	"Error": {
	  "id": "api.context.permissions.app_error",
	  "message": "You do not have the appropriate permissions.",
	  "detailed_error": "",
	  "request_id": "sm4iqbnf77dqpfcosrcsat8a3r",
	  "status_code": 403
	},
	"Uri": "http://xr:8080/api/v4/users/me/patch"
  }
}