diff --git a/docs/docs.go b/docs/docs.go
index cf30202b3fb0d89fde8a104b485c022b647a0734..370840d6e684f8ef343ad0986bffd965e7669f94 100644
--- a/docs/docs.go
+++ b/docs/docs.go
@@ -315,7 +315,7 @@ const docTemplate = `{
         },
         "/auth/register": {
             "post": {
-                "description": "Do Email Verification",
+                "description": "Generate New Account as Member",
                 "consumes": [
                     "application/json"
                 ],
@@ -325,7 +325,53 @@ const docTemplate = `{
                 "tags": [
                     "auth"
                 ],
-                "summary": "Email Verification",
+                "summary": "Register New Account",
+                "parameters": [
+                    {
+                        "description": "Register Payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/register.RegisterRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/auth/verify": {
+            "post": {
+                "description": "Do Email Verification to user",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "auth"
+                ],
+                "summary": "Do Email Verification",
                 "parameters": [
                     {
                         "description": "Register Payload",
@@ -359,6 +405,52 @@ const docTemplate = `{
                 }
             }
         },
+        "/auth/verify/resend": {
+            "post": {
+                "description": "Send Email Verification to user",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "auth"
+                ],
+                "summary": "Send Email Verification",
+                "parameters": [
+                    {
+                        "description": "Register Payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/verification.VerificationSendRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/reset/confirm": {
             "post": {
                 "description": "Do confirmation to reset password",
@@ -624,6 +716,18 @@ const docTemplate = `{
             }
         },
         "verification.VerificationRequestPayload": {
+            "type": "object",
+            "required": [
+                "id"
+            ],
+            "properties": {
+                "id": {
+                    "type": "string",
+                    "example": "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
+                }
+            }
+        },
+        "verification.VerificationSendRequestPayload": {
             "description": "Information that should be passed when request verify",
             "type": "object",
             "required": [
diff --git a/docs/swagger.json b/docs/swagger.json
index b0c36239bb54582921dae56d834e5903e59ebe55..acbb09b9750eddb9621a4c8509271d994b3c6227 100644
--- a/docs/swagger.json
+++ b/docs/swagger.json
@@ -307,7 +307,7 @@
         },
         "/auth/register": {
             "post": {
-                "description": "Do Email Verification",
+                "description": "Generate New Account as Member",
                 "consumes": [
                     "application/json"
                 ],
@@ -317,7 +317,53 @@
                 "tags": [
                     "auth"
                 ],
-                "summary": "Email Verification",
+                "summary": "Register New Account",
+                "parameters": [
+                    {
+                        "description": "Register Payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/register.RegisterRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
+        "/auth/verify": {
+            "post": {
+                "description": "Do Email Verification to user",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "auth"
+                ],
+                "summary": "Do Email Verification",
                 "parameters": [
                     {
                         "description": "Register Payload",
@@ -351,6 +397,52 @@
                 }
             }
         },
+        "/auth/verify/resend": {
+            "post": {
+                "description": "Send Email Verification to user",
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "auth"
+                ],
+                "summary": "Send Email Verification",
+                "parameters": [
+                    {
+                        "description": "Register Payload",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "$ref": "#/definitions/verification.VerificationSendRequestPayload"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "OK",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "400": {
+                        "description": "Bad Request",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    },
+                    "500": {
+                        "description": "Internal Server Error",
+                        "schema": {
+                            "$ref": "#/definitions/web.BaseResponse"
+                        }
+                    }
+                }
+            }
+        },
         "/reset/confirm": {
             "post": {
                 "description": "Do confirmation to reset password",
@@ -616,6 +708,18 @@
             }
         },
         "verification.VerificationRequestPayload": {
+            "type": "object",
+            "required": [
+                "id"
+            ],
+            "properties": {
+                "id": {
+                    "type": "string",
+                    "example": "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
+                }
+            }
+        },
+        "verification.VerificationSendRequestPayload": {
             "description": "Information that should be passed when request verify",
             "type": "object",
             "required": [
diff --git a/docs/swagger.yaml b/docs/swagger.yaml
index e01ccea263c225cf596ae8d2dd0a9750a1422851..f65ec1a9bd886e3c6fd7460ea165043dab217241 100644
--- a/docs/swagger.yaml
+++ b/docs/swagger.yaml
@@ -124,6 +124,14 @@ definitions:
     - email
     type: object
   verification.VerificationRequestPayload:
+    properties:
+      id:
+        example: 6ba7b812-9dad-11d1-80b4-00c04fd430c8
+        type: string
+    required:
+    - id
+    type: object
+  verification.VerificationSendRequestPayload:
     description: Information that should be passed when request verify
     properties:
       email:
@@ -341,7 +349,37 @@ paths:
     post:
       consumes:
       - application/json
-      description: Do Email Verification
+      description: Generate New Account as Member
+      parameters:
+      - description: Register Payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/register.RegisterRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Register New Account
+      tags:
+      - auth
+  /auth/verify:
+    post:
+      consumes:
+      - application/json
+      description: Do Email Verification to user
       parameters:
       - description: Register Payload
         in: body
@@ -364,7 +402,37 @@ paths:
           description: Internal Server Error
           schema:
             $ref: '#/definitions/web.BaseResponse'
-      summary: Email Verification
+      summary: Do Email Verification
+      tags:
+      - auth
+  /auth/verify/resend:
+    post:
+      consumes:
+      - application/json
+      description: Send Email Verification to user
+      parameters:
+      - description: Register Payload
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/verification.VerificationSendRequestPayload'
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: OK
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "400":
+          description: Bad Request
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+        "500":
+          description: Internal Server Error
+          schema:
+            $ref: '#/definitions/web.BaseResponse'
+      summary: Send Email Verification
       tags:
       - auth
   /reset/confirm:
diff --git a/go.mod b/go.mod
index b6cf3e2e6812ad2a15b62a2272bf6fc00fc72b76..ac79e565cd78a48be00bfa2ec85c7dfd4e821d71 100644
--- a/go.mod
+++ b/go.mod
@@ -22,6 +22,7 @@ require (
 require (
 	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+	github.com/google/uuid v1.3.0 // indirect
 )
 
 require (
diff --git a/go.sum b/go.sum
index 104db32d430bfc3149b43928c0b68f3784d9056d..3a961998dafe39ea3c0e30ca60f644347c85107b 100644
--- a/go.sum
+++ b/go.sum
@@ -61,6 +61,8 @@ github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws
 github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
 github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
 github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
diff --git a/handler/auth/handler.go b/handler/auth/handler.go
index adae847f2baec21f127940794b447cffdb9824b3..0799b93d0b06e23856bf1cc49949511d7f8924bf 100644
--- a/handler/auth/handler.go
+++ b/handler/auth/handler.go
@@ -3,6 +3,7 @@ package auth
 import (
 	"gitlab.informatika.org/ocw/ocw-backend/service/auth"
 	"gitlab.informatika.org/ocw/ocw-backend/service/logger"
+	"gitlab.informatika.org/ocw/ocw-backend/service/verification"
 	"gitlab.informatika.org/ocw/ocw-backend/utils/httputil"
 	"gitlab.informatika.org/ocw/ocw-backend/utils/wrapper"
 )
@@ -12,4 +13,5 @@ type AuthHandlerImpl struct {
 	httputil.HttpUtil
 	wrapper.WrapperUtil
 	logger.Logger
+	verification.VerificationService
 }
diff --git a/handler/auth/send_verify.go b/handler/auth/send_verify.go
new file mode 100644
index 0000000000000000000000000000000000000000..b2b4a2e70eaca89ac5de5f26a76fb4210d894416
--- /dev/null
+++ b/handler/auth/send_verify.go
@@ -0,0 +1,72 @@
+package auth
+
+import (
+	"fmt"
+	"net/http"
+
+	"github.com/go-playground/validator/v10"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web/auth/verification"
+)
+
+// Index godoc
+//
+//		@Tags					auth
+//		@Summary			Send Email Verification
+//		@Description	Send Email Verification to user
+//		@Produce			json
+//		@Accept				json
+//		@Param				data body verification.VerificationSendRequestPayload true "Register Payload"
+//		@Success			200	{object}	web.BaseResponse
+//	  @Failure			400 {object}  web.BaseResponse
+//	  @Failure			500 {object}  web.BaseResponse
+//		@Router				/auth/verify/resend  [post]
+func (a AuthHandlerImpl) SendEmailVerify(w http.ResponseWriter, r *http.Request) {
+	payload := verification.VerificationSendRequestPayload{}
+	validate := validator.New()
+
+	if r.Header.Get("Content-Type") != "application/json" {
+		payload := a.WrapperUtil.ErrorResponseWrap("this service only receive json input", nil)
+		a.HttpUtil.WriteJson(w, http.StatusUnsupportedMediaType, payload)
+		return
+	}
+
+	if err := a.HttpUtil.ParseJson(r, &payload); err != nil {
+		payload := a.WrapperUtil.ErrorResponseWrap("invalid json input", err.Error())
+		a.HttpUtil.WriteJson(w, http.StatusUnprocessableEntity, payload)
+		return
+	}
+
+	if err := validate.Struct(payload); err != nil {
+		if _, ok := err.(*validator.InvalidValidationError); ok {
+			payload := a.WrapperUtil.ErrorResponseWrap(err.Error(), nil)
+			a.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+			return
+		}
+
+		errPayload := web.NewResponseErrorFromValidator(err.(validator.ValidationErrors))
+		payload := a.WrapperUtil.ErrorResponseWrap(errPayload.Error(), errPayload)
+		a.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		return
+	}
+
+	err := a.AuthService.SendVerifyEmail(payload)
+
+	if err != nil {
+		respErr, ok := err.(web.ResponseError)
+		if ok {
+			payload := a.WrapperUtil.ErrorResponseWrap("you have reach limit of resend verification", respErr)
+			a.HttpUtil.WriteJson(w, http.StatusBadRequest, payload)
+		} else {
+			a.Logger.Error(
+				fmt.Sprintf("[AUTH] some error happened when do email verification: %s", err.Error()),
+			)
+			payload := a.WrapperUtil.ErrorResponseWrap("internal server error", nil)
+			a.HttpUtil.WriteJson(w, http.StatusInternalServerError, payload)
+		}
+		return
+	}
+
+	responsePayload := a.WrapperUtil.SuccessResponseWrap(nil)
+	a.HttpUtil.WriteSuccessJson(w, responsePayload)
+}
diff --git a/handler/auth/types.go b/handler/auth/types.go
index 1b70a41ef00b627a24521bb24ab8804bfe24c640..0848fea6ecd2b79b4f2470f432eeb8cbaf3c3d48 100644
--- a/handler/auth/types.go
+++ b/handler/auth/types.go
@@ -7,4 +7,5 @@ type AuthHandler interface {
 	Register(w http.ResponseWriter, r *http.Request)
 	Refresh(w http.ResponseWriter, r *http.Request)
 	EmailVerify(w http.ResponseWriter, r *http.Request)
+	SendEmailVerify(w http.ResponseWriter, r *http.Request)
 }
diff --git a/handler/auth/verify.go b/handler/auth/verify.go
index 6ab6b25233d8c7da2f4339abe7bd439736a979f1..a118518f67d6d8e4dff329541d93d406f545cbca 100644
--- a/handler/auth/verify.go
+++ b/handler/auth/verify.go
@@ -12,15 +12,15 @@ import (
 // Index godoc
 //
 //		@Tags					auth
-//		@Summary			Email Verification
-//		@Description	Do Email Verification
+//		@Summary			Do Email Verification
+//		@Description	Do Email Verification to user
 //		@Produce			json
 //		@Accept				json
 //		@Param				data body verification.VerificationRequestPayload true "Register Payload"
 //		@Success			200	{object}	web.BaseResponse
 //	  @Failure			400 {object}  web.BaseResponse
 //	  @Failure			500 {object}  web.BaseResponse
-//		@Router				/auth/register [post]
+//		@Router				/auth/verify  [post]
 func (a AuthHandlerImpl) EmailVerify(w http.ResponseWriter, r *http.Request) {
 	payload := verification.VerificationRequestPayload{}
 	validate := validator.New()
@@ -50,7 +50,7 @@ func (a AuthHandlerImpl) EmailVerify(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	err := a.AuthService.VerifyEmail(payload)
+	err := a.VerificationService.DoVerification(payload.Id)
 
 	if err != nil {
 		respErr, ok := err.(web.ResponseError)
diff --git a/model/web/auth/verification/request.go b/model/web/auth/verification/request.go
index 52b9cbc8b19133a25aca771ca96f4633e07deafa..dfddab4ba7adb0585a2147daa85ecfbfce77b25e 100644
--- a/model/web/auth/verification/request.go
+++ b/model/web/auth/verification/request.go
@@ -2,7 +2,11 @@ package verification
 
 // Email Verification Request Payload
 // @Description Information that should be passed when request verify
-type VerificationRequestPayload struct {
+type VerificationSendRequestPayload struct {
 	// User Email
 	Email string `json:"email" validate:"required,email" example:"someone@example.com"`
 }
+
+type VerificationRequestPayload struct {
+	Id string `json:"id" validate:"required" example:"6ba7b812-9dad-11d1-80b4-00c04fd430c8"`
+}
diff --git a/repository/cache/cache.go b/repository/cache/cache.go
index 7f554ed0dfe7148112096c8e58426fddc44fa900..724e4585ec8e0b3c8f60f2be22f0cf625a0d5908 100644
--- a/repository/cache/cache.go
+++ b/repository/cache/cache.go
@@ -29,6 +29,40 @@ func (c CacheRepositoryImpl) Get(key cache.Key) (string, error) {
 	return value, nil
 }
 
+func (c CacheRepositoryImpl) GetInteger(key cache.Key) (int64, error) {
+	conn := c.pool.Get()
+	defer conn.Close()
+
+	value, err := redis.Int64(conn.Do("GET", key))
+
+	if err != nil {
+		return 0, err
+	}
+
+	return value, err
+}
+
+func (c CacheRepositoryImpl) Incr(key string, expr int64) error {
+	conn := c.pool.Get()
+	defer conn.Close()
+
+	value, err := redis.Int64(conn.Do("INCR", key))
+
+	if err != nil {
+		return err
+	}
+
+	if value == 1 && expr > 0 {
+		_, err := conn.Do("EXPIRE", key, expr)
+
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+}
+
 func (c CacheRepositoryImpl) Delete(key string) error {
 	conn := c.pool.Get()
 	defer conn.Close()
diff --git a/repository/cache/type.go b/repository/cache/type.go
index dca193bc9959ce6ecde1cb35e75e021e7a20d382..d482986d93093b7dc4435cfbd8880af9a8e19b1d 100644
--- a/repository/cache/type.go
+++ b/repository/cache/type.go
@@ -6,9 +6,11 @@ import (
 
 type CacheRepository interface {
 	Get(key cache.Key) (string, error)
+	GetInteger(key cache.Key) (int64, error)
 	Set(str cache.String) error
 	Delete(key string) error
 	HGet(cache cache.Hash, field string) (string, error)
 	HGetAll(cache cache.Hash) (map[string]string, error)
 	HSet(cache cache.Hash) error
+	Incr(key string, expr int64) error
 }
diff --git a/routes/auth/route.go b/routes/auth/route.go
index 02205f37e1215d7ff63512613a7a7117f05edb7c..e81bb261069b4abc287c84ec793901ca42a9529e 100644
--- a/routes/auth/route.go
+++ b/routes/auth/route.go
@@ -14,6 +14,7 @@ func (ar AuthRoutes) Register(r chi.Router) {
 		r.Post("/login", ar.AuthHandler.Login)
 		r.Post("/refresh", ar.AuthHandler.Refresh)
 		r.Post("/register", ar.AuthHandler.Register)
+		r.Post("/verify/resend", ar.AuthHandler.SendEmailVerify)
 		r.Post("/verify", ar.AuthHandler.EmailVerify)
 	})
 }
diff --git a/service/auth/type.go b/service/auth/type.go
index 937521d8a9aacc0e95cfd1061e6cbc627b545686..f2eda67ef0abd2fa3a89f9a8249c8bd88a89af0b 100644
--- a/service/auth/type.go
+++ b/service/auth/type.go
@@ -11,5 +11,5 @@ type AuthService interface {
 	Login(payload login.LoginRequestPayload) (*login.LoginResponsePayload, error)
 	Refresh(payload refresh.RefreshRequestPayload) (*refresh.RefreshResponsePayload, error)
 	Register(payload register.RegisterRequestPayload) error
-	VerifyEmail(payload verification.VerificationRequestPayload) error
+	SendVerifyEmail(payload verification.VerificationSendRequestPayload) error
 }
diff --git a/service/auth/verify.go b/service/auth/verify.go
index a8462cec12a42a999b2910ef831768c8f6f4826d..339078a7b6838b6264a9acb5c03b820063de0e47 100644
--- a/service/auth/verify.go
+++ b/service/auth/verify.go
@@ -2,6 +2,6 @@ package auth
 
 import "gitlab.informatika.org/ocw/ocw-backend/model/web/auth/verification"
 
-func (auth AuthServiceImpl) VerifyEmail(payload verification.VerificationRequestPayload) error {
-	return nil
+func (auth AuthServiceImpl) SendVerifyEmail(payload verification.VerificationSendRequestPayload) error {
+	return auth.VerificationService.SendVerifyMail(payload.Email)
 }
diff --git a/service/verification/impl.go b/service/verification/impl.go
index 94db17485a4173f2ad820bbc100685d06f00d9b5..a74992b4fbf14b5c6e6174b5c00ee944afea812c 100644
--- a/service/verification/impl.go
+++ b/service/verification/impl.go
@@ -2,10 +2,18 @@ package verification
 
 import (
 	"gitlab.informatika.org/ocw/ocw-backend/provider/mail"
+	"gitlab.informatika.org/ocw/ocw-backend/repository/cache"
 	"gitlab.informatika.org/ocw/ocw-backend/repository/user"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/env"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/template"
+	"gitlab.informatika.org/ocw/ocw-backend/utils/token"
 )
 
 type VerificationServiceImpl struct {
 	mail.MailQueue
 	user.UserRepository
+	*env.Environment
+	template.TemplateWritterBuilder
+	token.TokenUtil
+	cache.CacheRepository
 }
diff --git a/service/verification/mail.go b/service/verification/mail.go
new file mode 100644
index 0000000000000000000000000000000000000000..6b89f3f7b7a50f41711554ade1ab6f3871bcea19
--- /dev/null
+++ b/service/verification/mail.go
@@ -0,0 +1,7 @@
+package verification
+
+type mailPayload struct {
+	BaseUrl string
+	Email   string
+	Token   string
+}
diff --git a/service/verification/send.go b/service/verification/send.go
index 9f404a803958d11c9f10a121ceacfc7aa87318d6..cfedd802ffa95cfb9aece68168ed30ae4c3ca580 100644
--- a/service/verification/send.go
+++ b/service/verification/send.go
@@ -1,6 +1,72 @@
 package verification
 
+import (
+	"errors"
+	"time"
+
+	"github.com/google/uuid"
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/cache"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+	"gitlab.informatika.org/ocw/ocw-backend/provider/mail"
+	"gorm.io/gorm"
+)
+
 func (v VerificationServiceImpl) SendVerifyMail(email string) error {
-	// TODO
+	_, err := v.UserRepository.Get(email)
+
+	if err != nil {
+		if errors.Is(err, gorm.ErrRecordNotFound) {
+			return web.NewResponseError("user not found", web.EmailNotExist)
+		}
+
+		return err
+	}
+
+	res, err := v.CacheRepository.GetInteger(cache.Key{
+		Id: v.RedisPrefixKey + "verify:cnt:" + email,
+	})
+
+	if err != nil {
+		if err.Error() != "redigo: nil returned" {
+			return err
+		}
+	}
+
+	if res > v.Environment.EmailVerificationMaxRetry {
+		return nil
+	}
+
+	id := uuid.New().String()
+	v.CacheRepository.Incr(v.RedisPrefixKey+"verify:cnt:"+email, v.EmailVerificationRetryInterval*int64(time.Minute))
+	v.CacheRepository.Set(cache.String{
+		Key: cache.Key{
+			Id: v.RedisPrefixKey + "verify:id:" + id,
+		},
+		Value:           email,
+		ExpiryInMinutes: int(v.EmailVerificationExpire) * int(time.Second),
+	})
+
+	mailBuilder, err := v.TemplateWritterBuilder.Get("email-verification.format.html")
+
+	if err != nil {
+		return err
+	}
+
+	mailData, err := mailBuilder.Write(&mailPayload{
+		BaseUrl: v.FrontendBaseURL + v.ResetPasswordPath,
+		Email:   email,
+		Token:   id,
+	})
+
+	if err != nil {
+		return err
+	}
+
+	v.MailQueue.Send(mail.Mail{
+		To:      []string{email},
+		Subject: "Email Verification",
+		Message: mailData,
+	})
+
 	return nil
 }
diff --git a/service/verification/type.go b/service/verification/type.go
index e6df1d1939e37be6abf399db52d68632e0924a4c..d321c706ff491be4398c8abaae780ca02ffe0cda 100644
--- a/service/verification/type.go
+++ b/service/verification/type.go
@@ -2,5 +2,5 @@ package verification
 
 type VerificationService interface {
 	SendVerifyMail(email string) error
-	SetVerification(email string, isVerified bool) error
+	DoVerification(id string) error
 }
diff --git a/service/verification/verify.go b/service/verification/verify.go
index b18ce1ecaa19fd332e495f81a8377b814a010246..4bfd2c115bb5f07811699599415be37bee5151da 100644
--- a/service/verification/verify.go
+++ b/service/verification/verify.go
@@ -1,6 +1,33 @@
 package verification
 
-func (v VerificationServiceImpl) SetVerification(email string, isVerified bool) error {
+import (
+	"gitlab.informatika.org/ocw/ocw-backend/model/domain/cache"
+	"gitlab.informatika.org/ocw/ocw-backend/model/web"
+)
+
+func (v VerificationServiceImpl) DoVerification(id string) error {
 	// TODO
+	email, err := v.CacheRepository.Get(cache.Key{
+		Id: v.RedisPrefixKey + "verify:id:" + id,
+	})
+
+	if err != nil {
+		return err
+	}
+
+	if email == "" {
+		return web.NewResponseErrorf("VERIFY", "id '%s' is not valid", id)
+	}
+
+	data, err := v.UserRepository.Get(email)
+
+	if err != nil {
+		return web.NewResponseErrorf("VERIFY", "username '%s' is not found", email)
+	}
+
+	data.IsActivated = true
+
+	v.UserRepository.Update(*data)
+
 	return nil
 }
diff --git a/utils/env/env.go b/utils/env/env.go
index 26bd1d30315d75f149114037acbdac94e11e9e3b..2fbe3b6f3738024d507cfbbe09497722e65e9b14 100644
--- a/utils/env/env.go
+++ b/utils/env/env.go
@@ -37,9 +37,13 @@ type Environment struct {
 	SmtpServer   string `env:"SMTP_SERVER"`
 	SmtpPort     int    `env:"SMTP_PORT" envDefault:"25"`
 
-	FrontendBaseURL       string `env:"FE_BASE_URL"`
-	ResetPasswordPath     string `env:"RESET_PASSWORD_PATH" envDefault:"/reset"`
-	EmailVerificationPath string `env:"EMAIL_VERIFICATION_PATH" envDefault:"/verification"`
+	FrontendBaseURL   string `env:"FE_BASE_URL"`
+	ResetPasswordPath string `env:"RESET_PASSWORD_PATH" envDefault:"/reset"`
+
+	EmailVerificationPath          string `env:"EMAIL_VERIFICATION_PATH" envDefault:"/verification"`
+	EmailVerificationMaxRetry      int64  `env:"EMAIL_VERIFICATION_MAX_RETRY" envDefault:"5"`
+	EmailVerificationRetryInterval int64  `env:"EMAIL_VERIFICATION_RESET_RETRY_INTERVAL_M" envDefault:"5"`
+	EmailVerificationExpire        int64  `env:"EMAIL_VERIFICATION_EXPIRE_S" envDefault:"300"`
 
 	RedisConnection string `env:"REDIS_STRING"`
 	RedisPort       string `env:"REDIS_PORT" envDefault:"6379"`