diff --git a/apps/authentication/api/password.py b/apps/authentication/api/password.py
index f721ed2a8..3453a6d8b 100644
--- a/apps/authentication/api/password.py
+++ b/apps/authentication/api/password.py
@@ -1,5 +1,6 @@
 import time
 
+from django.conf import settings
 from django.core.cache import cache
 from django.http import HttpResponseRedirect
 from django.shortcuts import reverse
@@ -40,12 +41,15 @@ class UserResetPasswordSendCodeApi(CreateAPIView):
         return user, None
 
     @staticmethod
-    def safe_send_code(token, code, target, form_type, content):
+    def safe_send_code(token, code, target, form_type, content, user_info):
         token_sent_key = '{}_send_at'.format(token)
         token_send_at = cache.get(token_sent_key, 0)
         if token_send_at:
             raise IntervalTooShort(60)
-        SendAndVerifyCodeUtil(target, code, backend=form_type, **content).gen_and_send_async()
+        tooler = SendAndVerifyCodeUtil(
+            target, code, backend=form_type, user_info=user_info, **content
+        )
+        tooler.gen_and_send_async()
         cache.set(token_sent_key, int(time.time()), 60)
 
     def prepare_code_data(self, user_info, serializer):
@@ -61,7 +65,7 @@ class UserResetPasswordSendCodeApi(CreateAPIView):
         if not user:
             raise ValueError(err)
 
-        code = random_string(6, lower=False, upper=False)
+        code = random_string(settings.SMS_CODE_LENGTH, lower=False, upper=False)
         subject = '%s: %s' % (get_login_title(), _('Forgot password'))
         context = {
             'user': user, 'title': subject, 'code': code,
@@ -82,7 +86,7 @@ class UserResetPasswordSendCodeApi(CreateAPIView):
             code, target, form_type, content = self.prepare_code_data(user_info, serializer)
         except ValueError as e:
             return Response({'error': str(e)}, status=400)
-        self.safe_send_code(token, code, target, form_type, content)
+        self.safe_send_code(token, code, target, form_type, content, user_info)
         return Response({'data': 'ok'}, status=200)
 
 
diff --git a/apps/authentication/mfa/sms.py b/apps/authentication/mfa/sms.py
index 7cf71985e..f88e56d35 100644
--- a/apps/authentication/mfa/sms.py
+++ b/apps/authentication/mfa/sms.py
@@ -2,6 +2,7 @@ from django.conf import settings
 from django.utils.translation import gettext_lazy as _
 
 from common.utils.verify_code import SendAndVerifyCodeUtil
+from users.serializers import SmsUserSerializer
 from .base import BaseMFA
 
 sms_failed_msg = _("SMS verify code invalid")
@@ -14,8 +15,13 @@ class MFASms(BaseMFA):
 
     def __init__(self, user):
         super().__init__(user)
-        phone = user.phone if self.is_authenticated() else ''
-        self.sms = SendAndVerifyCodeUtil(phone, backend=self.name)
+        phone, user_info = '', None
+        if self.is_authenticated():
+            phone = user.phone
+            user_info = SmsUserSerializer(user).data
+        self.sms = SendAndVerifyCodeUtil(
+            phone, backend=self.name, user_info=user_info
+        )
 
     def check_code(self, code):
         assert self.is_authenticated()
diff --git a/apps/common/sdk/sms/endpoint.py b/apps/common/sdk/sms/endpoint.py
index 7618d6da9..d0bdb1bcf 100644
--- a/apps/common/sdk/sms/endpoint.py
+++ b/apps/common/sdk/sms/endpoint.py
@@ -43,7 +43,7 @@ class SMS:
             **kwargs
         )
 
-    def send_verify_code(self, phone_number, code):
+    def send_verify_code(self, phone_number, code, **kwargs):
         prefix = getattr(self.client, 'SIGN_AND_TMPL_SETTING_FIELD_PREFIX', '')
         sign_name = getattr(settings, f'{prefix}_VERIFY_SIGN_NAME', None)
         template_code = getattr(settings, f'{prefix}_VERIFY_TEMPLATE_CODE', None)
@@ -53,4 +53,7 @@ class SMS:
                 code='verify_code_sign_tmpl_invalid',
                 detail=_('SMS verification code signature or template invalid')
             )
-        return self.send_sms([phone_number], sign_name, template_code, OrderedDict(code=code))
+        return self.send_sms(
+            [phone_number], sign_name, template_code,
+            OrderedDict(code=code), **kwargs
+        )
diff --git a/apps/common/utils/verify_code.py b/apps/common/utils/verify_code.py
index a5f6c668c..00a6b75bd 100644
--- a/apps/common/utils/verify_code.py
+++ b/apps/common/utils/verify_code.py
@@ -20,16 +20,20 @@ logger = get_logger(__file__)
         be executed to send SMS messages"""
     )
 )
-def send_sms_async(target, code):
-    SMS().send_verify_code(target, code)
+def send_sms_async(target, code, user_info):
+    SMS().send_verify_code(target, code, user_info=user_info)
 
 
 class SendAndVerifyCodeUtil(object):
     KEY_TMPL = 'auth-verify-code-{}'
 
-    def __init__(self, target, code=None, key=None, backend='email', timeout=None, **kwargs):
+    def __init__(
+            self, target, code=None, key=None, backend='email',
+            user_info=None, timeout=None, **kwargs
+    ):
         self.code = code
         self.target = target
+        self.user_info = user_info
         self.backend = backend
         self.key = key or self.KEY_TMPL.format(target)
         self.timeout = settings.VERIFY_CODE_TTL if timeout is None else timeout
@@ -78,7 +82,7 @@ class SendAndVerifyCodeUtil(object):
         return code
 
     def __send_with_sms(self):
-        send_sms_async.apply_async(args=(self.target, self.code), priority=100)
+        send_sms_async.apply_async(args=(self.target, self.code, self.user_info), priority=100)
 
     def __send_with_email(self):
         subject = self.other_args.get('subject', '')
diff --git a/apps/users/forms/profile.py b/apps/users/forms/profile.py
index 9a99c74fd..2b2e9a703 100644
--- a/apps/users/forms/profile.py
+++ b/apps/users/forms/profile.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 #
 from django import forms
+from django.conf import settings
 from django.utils.translation import gettext_lazy as _
 
 from common.utils import validate_ssh_public_key
@@ -103,7 +104,9 @@ class UserForgotPasswordForm(forms.Form):
         label=_('SMS'), required=False,
         help_text=_('The phone number must contain an area code, for example, +86')
     )
-    code = forms.CharField(label=_('Verify code'), max_length=6, required=False)
+    code = forms.CharField(
+        label=_('Verify code'), max_length=settings.SMS_CODE_LENGTH, required=False
+    )
     form_type = forms.ChoiceField(
         choices=[('sms', _('SMS')), ('email', _('Email'))],
         widget=forms.HiddenInput({'value': 'email'})
diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py
index 9343af38f..7d4632485 100644
--- a/apps/users/serializers/user.py
+++ b/apps/users/serializers/user.py
@@ -1,6 +1,5 @@
 # -*- coding: utf-8 -*-
 #
-
 from functools import partial
 
 from django.conf import settings
@@ -27,6 +26,7 @@ from ..models import User
 
 __all__ = [
     "UserSerializer",
+    "SmsUserSerializer",
     "MiniUserSerializer",
     "InviteSerializer",
     "ServiceAccountSerializer",
@@ -411,6 +411,14 @@ class UserRetrieveSerializer(UserSerializer):
         fields = UserSerializer.Meta.fields + ["login_confirm_settings"]
 
 
+class SmsUserSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = User
+        fields = [
+            'id', 'username', 'name', 'email', 'phone', 'source', 'is_active', 'comment'
+        ]
+
+
 class MiniUserSerializer(serializers.ModelSerializer):
     class Meta:
         model = User
diff --git a/apps/users/views/profile/reset.py b/apps/users/views/profile/reset.py
index e62d043b1..561816f03 100644
--- a/apps/users/views/profile/reset.py
+++ b/apps/users/views/profile/reset.py
@@ -16,6 +16,7 @@ from authentication.utils import check_user_property_is_correct
 from common.const.choices import COUNTRY_CALLING_CODES
 from common.utils import FlashMessageUtil, get_object_or_none, random_string
 from common.utils.verify_code import SendAndVerifyCodeUtil
+from users.serializers import SmsUserSerializer
 from users.notifications import ResetPasswordSuccessMsg
 from ... import forms
 from ...models import User
@@ -51,8 +52,7 @@ class UserForgotPasswordPreviewingView(FormView):
         if token_sent_at:
             raise IntervalTooShort(sent_ttl)
         token = random_string(36)
-        user_info = {'username': user.username, 'phone': user.phone, 'email': user.email}
-        cache.set(token, user_info, 5 * 60)
+        cache.set(token, SmsUserSerializer(user).data, 5 * 60)
         cache.set(token_sent_at_key, time.time(), sent_ttl)
         return token