diff --git a/src/users/change-email.dto.ts b/src/users/change-email.dto.ts
new file mode 100644
index 0000000000000000000000000000000000000000..eb783e4490f15c9c32b2f78d4f6dae4f679553fd
--- /dev/null
+++ b/src/users/change-email.dto.ts
@@ -0,0 +1,10 @@
+import { IsEmail, IsNotEmpty } from 'class-validator';
+
+export class EmailChangeDto {
+  @IsNotEmpty()
+  @IsEmail()
+  readonly newEmail: string;
+  @IsNotEmpty()
+  @IsEmail()
+  readonly oldEmail: string;
+}
diff --git a/src/users/user.interface.ts b/src/users/user.interface.ts
index 0fe05c6f856caafb64c23ff4dfbaaa778d6b5773..704569733e0657f065a6598cdc4dcfc7bcdf1954 100644
--- a/src/users/user.interface.ts
+++ b/src/users/user.interface.ts
@@ -7,4 +7,6 @@ export interface IUser extends Document {
   emailVerified: boolean;
   validationToken: string;
   role: number;
+  changeEmailToken: string;
+  newEmail: string;
 }
diff --git a/src/users/user.schema.ts b/src/users/user.schema.ts
index abb11e91aaac1bac06d07ab6c513567b89a6791c..c41262a381bd19c00b266be3a8345cb91a9c2c51 100644
--- a/src/users/user.schema.ts
+++ b/src/users/user.schema.ts
@@ -16,6 +16,12 @@ export class User {
 
   @Prop({ enum: [UserRole.admin, UserRole.user], default: UserRole.user })
   role: number;
+
+  @Prop({ default: null })
+  changeEmailToken: string;
+
+  @Prop({ default: null })
+  newEmail: string;
 }
 
 export const UserSchema = SchemaFactory.createForClass(User);
diff --git a/src/users/users.controller.ts b/src/users/users.controller.ts
index c7120670e093cfe37ea2cdd5c81586ec2afc6590..b797570a30dd3fd0aa5798698dddf55a4773743a 100644
--- a/src/users/users.controller.ts
+++ b/src/users/users.controller.ts
@@ -2,6 +2,7 @@ import { Body, Controller, Get, Param, Post, Query, Request, UseGuards } from '@
 import { ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger';
 import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
 import { PasswordChangeDto } from './change-password.dto';
+import { EmailChangeDto } from './change-email.dto';
 import { CreateUserDto } from './create-user.dto';
 import { UsersService } from './users.service';
 
@@ -44,4 +45,20 @@ export class UsersController {
       passwordChangeDto.newPassword
     );
   }
+
+  @UseGuards(JwtAuthGuard)
+  @Post('change-email')
+  @ApiResponse({ status: 201, description: 'Email confirmation send' })
+  @ApiResponse({ status: 401, description: 'Invalid Email' })
+  public async changeEmail(@Request() req, @Body() emailChangeDto: EmailChangeDto) {
+    return this.usersService.changeUserEmail(emailChangeDto.newEmail, emailChangeDto.oldEmail);
+  }
+
+  @UseGuards(JwtAuthGuard)
+  @Post('verify-change-email')
+  @ApiResponse({ status: 201, description: 'Email changed' })
+  @ApiResponse({ status: 401, description: 'Invalid Token' })
+  public async verifyAndUpdateEmail(@Request() req, @Query('token') token: string) {
+    return this.usersService.verifyAndUpdateUserEmail(token);
+  }
 }
diff --git a/src/users/users.service.ts b/src/users/users.service.ts
index dbaed19c46e7bf14a8a71eeaf7e5562cf16aaed5..b0770d5554cd047b1a0b7fff291c94466f374101 100644
--- a/src/users/users.service.ts
+++ b/src/users/users.service.ts
@@ -134,6 +134,38 @@ export class UsersService {
     }
   }
 
+  public async changeUserEmail(newEmail: string, oldEmail: string) {
+    const user = await this.findOne(oldEmail);
+    if (user) {
+      const config = this.mailerService.config;
+      const ejsPath = this.mailerService.getTemplateLocation(config.templates.changeEmail.ejs);
+      const jsonConfig = this.mailerService.loadJsonConfig(config.templates.changeEmail.json);
+      const token = crypto.randomBytes(64).toString('hex');
+      const html = await ejs.renderFile(ejsPath, {
+        config,
+        token: token,
+      });
+      this.mailerService.send(user.email, jsonConfig.subject, html);
+      user.changeEmailToken = token;
+      user.newEmail = newEmail;
+      user.save();
+    }
+    throw new HttpException('Email sent if account exist', HttpStatus.OK);
+  }
+
+  public async verifyAndUpdateUserEmail(token: string): Promise<any> {
+    const user = await this.userModel.findOne({ changeEmailToken: token }).exec();
+    if (user) {
+      user.email = user.newEmail;
+      user.newEmail = null;
+      user.changeEmailToken = null;
+      user.save();
+      return user;
+    } else {
+      throw new HttpException('Invalid token', HttpStatus.UNAUTHORIZED);
+    }
+  }
+
   public async changeUserPassword(userId: string, oldPassword: string, newPassword: string): Promise<any> {
     const user = await this.findById(userId, true);
     const arePasswordEqual = await this.comparePassword(oldPassword, user.password);