From 7a45f4d12992a9c310d2ca1750706cd5b15dd11e Mon Sep 17 00:00:00 2001
From: fit2bot <68588906+fit2bot@users.noreply.github.com>
Date: Mon, 13 Sep 2021 20:15:59 +0800
Subject: [PATCH] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E7=9F=AD=E4=BF=A1=20?=
 =?UTF-8?q?(#6826)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* perf: 优化短信

* refactor: 适配新的短信模板配置

Co-authored-by: ibuler <ibuler@qq.com>
Co-authored-by: xinwen <coderWen@126.com>
---
 apps/common/message/backends/sms/__init__.py |  43 ++++---------------
 apps/common/message/backends/sms/alibaba.py  |   2 +-
 apps/common/message/backends/sms/tencent.py  |   2 +-
 apps/jumpserver/conf.py                      |   6 ++-
 apps/jumpserver/settings/auth.py             |  14 ------
 apps/jumpserver/settings/custom.py           |  17 ++++++++
 apps/locale/zh/LC_MESSAGES/django.mo         | Bin 94647 -> 94691 bytes
 apps/locale/zh/LC_MESSAGES/django.po         |   2 +-
 apps/settings/api/alibaba_sms.py             |   9 ++--
 apps/settings/api/tencent_sms.py             |   9 ++--
 apps/settings/serializers/auth/sms.py        |  25 +++++------
 apps/settings/serializers/other.py           |  10 +++--
 12 files changed, 58 insertions(+), 81 deletions(-)

diff --git a/apps/common/message/backends/sms/__init__.py b/apps/common/message/backends/sms/__init__.py
index 760b55407..3eaf6fecf 100644
--- a/apps/common/message/backends/sms/__init__.py
+++ b/apps/common/message/backends/sms/__init__.py
@@ -11,34 +11,6 @@ from common.exceptions import JMSException
 logger = get_logger(__file__)
 
 
-class SMS_MESSAGE(TextChoices):
-    """
-    定义短信的各种消息类型,会存到类似 `ALIBABA_SMS_SIGN_AND_TEMPLATES` settings 里
-
-    {
-        'verification_code': {'sign_name': 'Jumpserver', 'template_code': 'SMS_222870834'},
-        ...
-    }
-    """
-
-    """
-    验证码签名和模板。模板例子:
-    `您的验证码:${code},您正进行身份验证,打死不告诉别人!`
-    其中必须包含 `code` 变量
-    """
-    VERIFICATION_CODE = 'verification_code'
-
-    def get_sign_and_tmpl(self, config: dict):
-        try:
-            data = config[self]
-            return data['sign_name'], data['template_code']
-        except KeyError as e:
-            raise JMSException(
-                code=f'{settings.SMS_BACKEND}_sign_and_tmpl_bad',
-                detail=_('Invalid SMS sign and template: {}').format(e)
-            )
-
-
 class BACKENDS(TextChoices):
     ALIBABA = 'alibaba', _('Alibaba cloud')
     TENCENT = 'tencent', _('Tencent cloud')
@@ -49,11 +21,7 @@ class BaseSMSClient:
     短信终端的基类
     """
 
-    SIGN_AND_TMPL_SETTING_FIELD: str
-
-    @property
-    def sign_and_tmpl(self):
-        return getattr(settings, self.SIGN_AND_TMPL_SETTING_FIELD, {})
+    SIGN_AND_TMPL_SETTING_FIELD_PREFIX: str
 
     @classmethod
     def new_from_settings(cls):
@@ -86,5 +54,12 @@ class SMS:
         )
 
     def send_verify_code(self, phone_number, code):
-        sign_name, template_code = SMS_MESSAGE.VERIFICATION_CODE.get_sign_and_tmpl(self.client.sign_and_tmpl)
+        sign_name = getattr(settings, f'{self.client.SIGN_AND_TMPL_SETTING_FIELD_PREFIX}_VERIFY_SIGN_NAME')
+        template_code = getattr(settings, f'{self.client.SIGN_AND_TMPL_SETTING_FIELD_PREFIX}_VERIFY_TEMPLATE_CODE')
+
+        if not (sign_name and template_code):
+            raise JMSException(
+                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))
diff --git a/apps/common/message/backends/sms/alibaba.py b/apps/common/message/backends/sms/alibaba.py
index b664f4401..2c5532c4f 100644
--- a/apps/common/message/backends/sms/alibaba.py
+++ b/apps/common/message/backends/sms/alibaba.py
@@ -15,7 +15,7 @@ logger = get_logger(__file__)
 
 
 class AlibabaSMS(BaseSMSClient):
-    SIGN_AND_TMPL_SETTING_FIELD = 'ALIBABA_SMS_SIGN_AND_TEMPLATES'
+    SIGN_AND_TMPL_SETTING_FIELD_PREFIX = 'ALIBABA'
 
     @classmethod
     def new_from_settings(cls):
diff --git a/apps/common/message/backends/sms/tencent.py b/apps/common/message/backends/sms/tencent.py
index 6f796bb15..427e8b7dd 100644
--- a/apps/common/message/backends/sms/tencent.py
+++ b/apps/common/message/backends/sms/tencent.py
@@ -20,7 +20,7 @@ class TencentSMS(BaseSMSClient):
     """
     https://cloud.tencent.com/document/product/382/43196#.E5.8F.91.E9.80.81.E7.9F.AD.E4.BF.A1
     """
-    SIGN_AND_TMPL_SETTING_FIELD = 'TENCENT_SMS_SIGN_AND_TEMPLATES'
+    SIGN_AND_TMPL_SETTING_FIELD_PREFIX = 'TENCENT'
 
     @classmethod
     def new_from_settings(cls):
diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py
index 74fd3b708..a2e96966f 100644
--- a/apps/jumpserver/conf.py
+++ b/apps/jumpserver/conf.py
@@ -249,12 +249,14 @@ class Config(dict):
 
         'ALIBABA_ACCESS_KEY_ID': '',
         'ALIBABA_ACCESS_KEY_SECRET': '',
-        'ALIBABA_SMS_SIGN_AND_TEMPLATES': {},
+        'ALIBABA_VERIFY_SIGN_NAME': '',
+        'ALIBABA_VERIFY_TEMPLATE_CODE': '',
 
         'TENCENT_SECRET_ID': '',
         'TENCENT_SECRET_KEY': '',
         'TENCENT_SDKAPPID': '',
-        'TENCENT_SMS_SIGN_AND_TEMPLATES': {},
+        'TENCENT_VERIFY_SIGN_NAME': '',
+        'TENCENT_VERIFY_TEMPLATE_CODE': '',
 
         'OTP_VALID_WINDOW': 2,
         'OTP_ISSUER_NAME': 'JumpServer',
diff --git a/apps/jumpserver/settings/auth.py b/apps/jumpserver/settings/auth.py
index ac9fdb631..048c76a39 100644
--- a/apps/jumpserver/settings/auth.py
+++ b/apps/jumpserver/settings/auth.py
@@ -122,21 +122,7 @@ AUTH_FEISHU = CONFIG.AUTH_FEISHU
 FEISHU_APP_ID = CONFIG.FEISHU_APP_ID
 FEISHU_APP_SECRET = CONFIG.FEISHU_APP_SECRET
 
-# SMS auth
-SMS_ENABLED = CONFIG.SMS_ENABLED
-SMS_BACKEND = CONFIG.SMS_BACKEND
-SMS_TEST_PHONE = CONFIG.SMS_TEST_PHONE
 
-# Alibaba
-ALIBABA_ACCESS_KEY_ID = CONFIG.ALIBABA_ACCESS_KEY_ID
-ALIBABA_ACCESS_KEY_SECRET = CONFIG.ALIBABA_ACCESS_KEY_SECRET
-ALIBABA_SMS_SIGN_AND_TEMPLATES = CONFIG.ALIBABA_SMS_SIGN_AND_TEMPLATES
-
-# TENCENT
-TENCENT_SECRET_ID = CONFIG.TENCENT_SECRET_ID
-TENCENT_SECRET_KEY = CONFIG.TENCENT_SECRET_KEY
-TENCENT_SDKAPPID = CONFIG.TENCENT_SDKAPPID
-TENCENT_SMS_SIGN_AND_TEMPLATES = CONFIG.TENCENT_SMS_SIGN_AND_TEMPLATES
 
 # Other setting
 TOKEN_EXPIRATION = CONFIG.TOKEN_EXPIRATION
diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py
index 0ef447621..91973d1b2 100644
--- a/apps/jumpserver/settings/custom.py
+++ b/apps/jumpserver/settings/custom.py
@@ -132,3 +132,20 @@ LOGIN_REDIRECT_MSG_ENABLED = CONFIG.LOGIN_REDIRECT_MSG_ENABLED
 CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS = CONFIG.CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS
 
 XRDP_ENABLED = CONFIG.XRDP_ENABLED
+
+
+# SMS enabled
+SMS_ENABLED = CONFIG.SMS_ENABLED
+SMS_BACKEND = CONFIG.SMS_BACKEND
+SMS_TEST_PHONE = CONFIG.SMS_TEST_PHONE
+
+# Alibaba
+ALIBABA_ACCESS_KEY_ID = CONFIG.ALIBABA_ACCESS_KEY_ID
+ALIBABA_ACCESS_KEY_SECRET = CONFIG.ALIBABA_ACCESS_KEY_SECRET
+ALIBABA_SMS_SIGN_AND_TEMPLATES = CONFIG.ALIBABA_SMS_SIGN_AND_TEMPLATES
+
+# TENCENT
+TENCENT_SECRET_ID = CONFIG.TENCENT_SECRET_ID
+TENCENT_SECRET_KEY = CONFIG.TENCENT_SECRET_KEY
+TENCENT_SDKAPPID = CONFIG.TENCENT_SDKAPPID
+TENCENT_SMS_SIGN_AND_TEMPLATES = CONFIG.TENCENT_SMS_SIGN_AND_TEMPLATES
diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo
index f5ecd7eb66a64394363cb7f5c80594275a9d3ff7..ac63b99c8c24f6c791f7e6b876df9af52f406174 100644
GIT binary patch
delta 26880
zcmZA91(+2_8t(BP+--218Qk67g1c*QcL`1!cg<kIo#5`Siv<Wy2(BSWNFWgO{@+s{
z_vX3%Y~@$=m3Fn9b7r%<<9_7(_apna5=5HeaXg9Sc`31JM$elc#q;J>SJd<3b@aR`
z5j-zGZV2+c#hpFx64vVKd5x&g(B1PU;ZPiiae8=ON$SU8HTs?G>3MI7C+XvP^(n{w
z&hu_jZr9KA+C=bt@0<Rf_nN?JdXLA2gBT3640Z#r!BvzC5AnRY416D#Q1*S#>q9vW
zjT2FxHO%u^x3>;s<5rA`hcPjp#V~wmMjh^XA<XY(CX<YcO2{U7tuZ%t!0b2&)$s&o
z#;2GC6OQn_JXjKQU@vnqUZZ>-b*8IEx^c#i^1K9;w_{v9i7}YpyG|w+J}_UIpD`-&
zn4?{NFzSp#F&ML93@n8Su?nhv3sk!fsB!z4!%+PuV-#G1zB;V3z$Vnz?ZhN_95ui#
zjE;Yx+P}eg_z5*}oH1@8Y0Vs{GcAm1uqtZY?x-CcV)ZM>u>agQ-fnA<Wvpvh2qO|N
zkD0JCX2jm8h0MjsxEvec8q_6=IL`IYk6J)kjF0s(6?Q<4I~wEQ_;KuibTU5@P{XCD
zt=oor8V+FwyoI_4B6Ejo3p1j2peX9*s*35cHEPGkq1w$vUF+4Tdu%tV-zC(}J@m<F
zrSCBX#-89N%8Y?)ikhGWs$)OYz++MU=2`s))C9*Zeg}0zf1}z*p6D)VGSoP^QSJRQ
zWMYwNiW;yZCda`RpM_e;GSp+X3w1{4Fb3X64fGV%Khh+336fw`%IQ%jklo_tPz$Jy
zjO%-?$wVX2AGOk9sK;;yCdE0ZiMOB@b`rIq2Uh>D)hC$j;+atQMsd`*Wi4J6V^eO4
zF|j+Q)AK)wOdJA>P-nCOv*T`zj!!Ta{)Jlk7YxC8Q`}>e3pH>-jDz1`I;@N8KLB+p
zMqmV-fl+Wa2A=<gWVA)AQ7b-#n(&mxucCI~1*XMFQ#~&~X2QJqEf&EaP&@Q9Y6qX7
z7VsRkfVY?nqfc`SD1yGuxHK7^K~>a5jZqzYpavRf^}aa?^?sO(ns5v1jLw>uQP=)A
z)MNJmwIdOJaQ!l(;w67z|21JV0=oNqqps}~)WFNEd;qnOOQ?liM@@JiwUDQ%=Q={T
z+rcOppK@F?%*<<kgTd4{2<Q4IAk&$E7V<sn5==);G~ZllZZh|v+8smf;8`nQxAHyn
zIcg#AurS7$?(U&-s1vB?lgUJ;DQe3`p$49W@o*-_#g(X=YX|D?J#O_EP&;)W^%#Ce
zok-Fd?gVn6#w~;zr<7R}b5izOkkJ-SMGf#1>dX(DXHfUX71RPAU_$&GHDI)v?r}?s
zI-}I6_UTbKabDD=ErnW0Q`C;NLHhIlw+bKiVKK&4c&kxcw;MI_84Si7R{zrcg4(IL
zv)s;wq9)3Wy0p1bJ5~-gUQMfSg>m%!cOs(!23W=TKn0Hz>I@g7UPPNv1D!&h*%j18
z_fZS{!^-bbI~ZZMYZnXiQci~2p=zidsf*E>-|Im}TR+g8j)^F*N1ee@)RtYvR(KE9
z{+l1&0-B@lnf9m&dY~5G54GSis7n%#x^#<C3*3&rG6%_o;wjWXf1o<PMs2w_$GxBu
zq8`Jns2#|KYG2&S<xvyWLG^EmT1Z#a4h=!gHxYG0Gv~1X$;m9Xz+P+cKhy-jpa#5!
zn&=s7%io{|{)Ad!?76NShT4JLs0j;UR;+;8us7-i7NN#lK9~L11nUW?!(J?er!g5u
zn&&P>YD`W!A8G+LPz!8ewm}Wp6Sbg$s56~x&PJW_60D5tQ0?FOWVE87`EKP=P+J$<
zOonQh9vfl~)Pl!gN}PdZaI=-)U@6K87Pwb#9aR7Rs87XVm>I{QcF^BMMrU#elj2zn
z#mA_vjJD7<jElN?LQpqlKGaiF!Qu@q-qjq6I^%HEL<>-l-+I&u9z<?(-#bGlHGzAm
zEe~4cCP;x=P!80kses!0`dAvj#XPtOi{M4nIB^!cGtO=nz%;~5q88E$bppLGg`WRW
zWHJy~j3IaebK?`#&69kIyQbw)9UG(0yen$J?@<e!Y|cluTZ>xo0gL|+wF6fy{sa>+
zzxO8@ZFR(@Zsjph9fMIFQlRRyV=Bytp;#Mr#=R~61L|6DM77_AfvrYe;xm{8ucL0#
zSLkbtBQJ9eQlkdQiW(pvY9U3fT-NF<qXw>nVb~ls!7$X0Oh!$x0L$QJtdDPS1y)_|
zd3*5h<?O#YY#^$e>i}w?OQ;F%qHdz+7zN*<7W4(R<xy9<i4vnONfuQ5qNt~&JVwR3
zsC%m^CdR&~c_*!8|Fr}22}Ho{s8{bU)B?_-p5q&+0Uu)E(+{<PXg|5fH;I`N)h-P6
zc;>WtRn$1OtlR`OehZ(B&bSMP;sA_>b1c3Tbq{PrJ->%hD?fpn=o+g3BMdAIbt2JL
zIb)(uFb-;*jHrHvE$&w!qnn}yY76^g8XRY?#Zr{dVR4MN+C3%JQT@81uJvftC7Oe|
zaWV2A?;`)uP5b>CcPZwfPGp%Y``&5`Y{r~a>_lCoCm0jIU^I-m)@^x0)ET5jZE<eY
z<5nHjuBF+@?2S>04@TXrBQZ0sz?6Fa&y$Hk;5lmGcc?9nvd-N!iBa$VTo@gzptiCe
zs$Y9l`(CI8568g!0P|6vk7{=TwZNNJ{|K|{`F~>#!q&Sj%!X-+=S5A}03%{c)brjJ
zb%{orD^U}lLT&98)TQ_hW8;0)j=n<eM6?a=3rIZlwRPFZXuy&f3tM4a?2d8JxA<h#
z0CQ0jEj3r6Cfa~H!+od)9Y@_87p(pfYA0S>`O60OUn`5f(XA*Qs$(hC#8oi^HbHe9
zj#}^})XpqIO}N_1TTm13L$&_})&4isiM>Q!x{p>LXA}FchRHU$j_FW$bs^Li*2MVO
z0JWfwsGF!is@)varP+*H$ad7i4p{jlW~O`rbz&b;3yikeomfhrj4H~aR$2qoV=Ie~
zMJ;eT#>a)`Ce+Ry!MOM<hT>Dyna14W7L*jVpfJ=4WHpPJekC%xyBnIlF@*ADbG>=i
ze1Y1TI9r{GP$!TQBVi`g8#FuW9w}>9LfyPIQ163o$cxGMCc2Eb91~KpA2q;5On|>*
z3jBx(G3hpU=Gjr@a%LmcPIN<^@%N|&jYaL$Bvkulm<M-ZG(G>%tl~`|z;<tUTNsQQ
zAQZD=dejT27V468Lp`PgP!rEbwO@zY>dh8EgxZN;P?zQ^>S=j^f#3gsk;zTq6KZR7
z?r@i+0P0L?S-A=7ChLnC(ML_Z5_Ji7U<5pZdQ6X_7J3#n;dNB|#~2UaqOS>~?Q|XD
zq6SEUT4{3BCCG?cND&NdIqGI?gtM_TYT!t_T)%{<3BoWD=E1~R5w(NOF)0q-#r|u{
zW)LWdb5IMqfI5TgsDbaI&hQm#z)u*A!MoiVW<>2w9#p@gRxXQLcvUOcN1a%6OpaZ4
zbNzKjV+d%4^RPT_K`rDxY72w-x}tWmP!olrwloXsX(@zSP(w_DUCfb~f$}`mjvO&B
zS^YzwOehtfP&ZBLy>4r>n<X&?@miP+yQ0o;3~InB<|0(PO_&aUM%{FOneR{w{){?-
zSo>VrPedj;fwZV=UBb$>Py=>B4LBBc&DNn7avZbc9ZZRF_PfuJteBs2b<Bq&QRD7H
zy*baIUT`mvOYeIL54dZR40WwDpw6%WYNaJmE3bgM2kKdUOS2=YT~E{{9Ee)bG}N_U
zZ}mH^{t%`jehuU6`Txf%q8)TwA7bW4UCXkl9cqFaurKPK7>Zi(1k?*<F6yZ`i<$5a
zhG6tV?xxL*I)RdA70ki>UIQ|^_M=e~%s^ecg{X;^qi)8HR=)!^&>;-PpHVyZ0@d#y
zRQrz>k9gQEEG8<R3bkYD&{rlq8Qt9lPz$MonxHXi0qsx=>xnwUL8$hVPy;SOwO?iB
zZK!efqHfaD7>d84?wL=hg=Rg%{_D+``-tn%8g&hOVKy9xTHtonJ#YYZ?S4j0{D=7$
zYJvZv798=YyXoSfCJIAtHZLP;LD^9KiyvkG^+G5|Kr60=8mI;8j5?vNabJs%MlEQn
zm4C#Dl$WB$S&6#&wxas|f`jp{)qi`;jo%q{Lf`oo7=gNmldNI}YNbn26K+MlVD@2P
zVAO)|TK%6E{}<IS`f+!L$;~j-rORaHBB-76OOwe;rYdUS{-`Y;i{)?y>OJrWYG<PU
z&t0PUs58ifdcF&w2CRfyXkCno9W34hwctUhr)fNL>3wfG8NJi5q89KR)$kK)f><Y9
zJUMD7vY@s)FGj^u7O#kEUkf8+bIgEkF%nKhoxn8Ii)?N{uK!jt8t`X~hQFe&{e9FM
z>?KCQbSGUrE9wjiq6Vss+Vakr83$tlT!Gq=o2UgnL5=eQb%Jj&lAixar`#4sM>R-^
zYLM2-c~Co37<I;#P!rd(awpUo_ChVZAL<o70@ZIms^2=)4sAnSvLop0Os<fLj;~M)
z_+Umj?FNjFdfpSE7M2AyP+_aDVDUPrYu^erZeP^SOtbhB)HvHQ2A)36^;hN!0iD5J
z)TMZYx)gt-7WUD~QO>xP$3?YEgX*6XwZ%nHXI2W;zYeN@Q`CannSHE&_!;(Jcl!ha
z+R|01=l3w`3~rn6QSB1_?9M1J>Qk;9ron-zh0I6o&`%f(cc3o8QOtywFbqFoMhx-K
zx>sTa%u3)pyoif&ipuBMZj5}M|CR)EnUk?2<!2az^?z~Sp!#A{%ImQV#=PKe#_E`p
z@+i!P+psA5_sHl>Q!{ISER1b&Gxouxm)rs-VJ^x$F$4aN+L3sd-S>kWs2!<;X>lB?
z{W{c%-NND+;|hNP$BM|peQzcib=Z#jxcwCi;9pn^GhgLwa1g3pmTT_M>D5tNKOEI>
zIqI(8hiZ4#;vY~a7<`>42XmmFhW?m{`MsfJ;t`mM!MGB2&Guk?JdH8&CMLt*F*Qc~
z)!kHSP}e#as$Fr^y-*1?QC-x{-4t~*w!}Et8QU<wH;_zvyp6pu@(uSF&i<I4@@~}4
z^90Ld{NMO!#)eo3x1jF+XQ&hS3zK4$n{H=9FfrwVsD)NXonRC6wc^fJ(GRu4k*F0<
zws<%uqPz&T^6jWCKZe@5o8}ADLcgHK$#lz^2VYVyhD|WrZMQ>XZ?pe{34{~S%HrK|
zD@%piy6mV+kRP?s3aCp^2lb-rYWBh8ln0?M%}flzZK$W`GKQje*DX8@b%_e!W&br$
zIRe^}DyWH?pcd2~wU9pMU<~Y#IoX_zEorv|wNsJqxgAW7>K|feL`|F%wUb4BGU`wX
zQ(|+}wHl1EF&y<cF2<}F^}btRUeo|3F>p;$JJkerX}V%69EEvtDQe=Ym<I2m=JO*z
za08~n1O#%RZlcnt3F@KFxD9Fn-K;zZb(1Ya-2?kj{m-Iay?0S3@D#P6cV@hY?mdwS
zxm3RQEt$wP7=k*J5vYz+u_P`)4R{M9<73n%dycwPuTAffyM(b&Tb>eCpAK~bxv(=9
z!F0F+qv-iRO-3uffSTYTYODT04e$@<#|V$z8?6xP5_LrN8;Ux^aEyd&P$#m{+=nG7
zpTZ~@{RuZ7#=|_!?^PxfhC^@@E<_Dn>vy-HHkg)jCv!69q`Vo`?j9z@H<%t{JarS~
zLS3RxSOiC)o|65jd+s{=>iCjO4vh4Ndq?NRQj~jQIoym<@hz(T7t|RheCEzL3{wX2
zxq!O4%071!w?plykI``yY5`MF_sr_&?0*b0dkARd$5D^rGt^D^5p@&Bd*QY`1hrEI
zP+Q#)H9<4XjIA*fPQr}19krlam<@w?3uVO|m<1cZWdAksC<1z1)}S7Xlc<i5P!mS~
z)5Wu5DCLS6f*n!)$DwYj4HmzI+WOa+0%N~&mnt)A>x-f0sqK@|8?8HPYsR5&re&yW
zyBFi(IV`~z-@%s{@;7fgjQfVmfD`_4AFGSr>Y3t8Cbq$D?--Bzi+BM4_?JhO_?i!#
zNCet;{OE4F@t^r?2MvmS;Ttgx3I+vv1MnFR$955dypi}jj>T>fDbxNfj;1^~a*)@7
za>OV>frWR88WgxhKE|YeBu2xj7$1K`cEb18xQurQwWU|B!CO>^=+S}#*D3+#p<Enw
zsd``roQ$Ek4RuYgSbb3RpuqQt5IjM=K5oH~7(szcdlBPlul^yU=Q(Q3pumeKwV4gI
z^+ixOX%*B{P~Ymm#aNWPm;+GlMq7Cr>Um#a<>lsP^MKT~IzvVcubX#JkIQ2<z*nf7
z>9duS#B%lNQ2lb4`ORXeer3&?sC%gy>SpYL8h;}CnaIo}qr36|Hpa`=AXjYHun20R
za;O2SnC(#$jj;NuSe^1L%!`k#K6xB>0vS<{bt%+MUpG#W9~ihB0Zs57YGs2lE{;Y`
zFcY-{OU=FJWvhQ-elVlObqh^|>Yv*zff~08YDb#H^<AJF0qwx|=5*8-iPh#wREH;4
z{{eLu$B*awr8NtiHBdX%*2=@oS>`&cKjK^9HtG!DpjH?szFT=})Wlh>TmrSwDpqc3
zb~6W|CLU|$W#%T-4(~_xKW1_NhGm{u#T(Qmh?&4$t3;@dnNbVOWmZD%P%A4BLrpx#
z%G=FzsQyn-<Gw^K;9ulK`R{*&T}23nQIQz~*9dj(nxJmd4pyFKE-=@iCf<pf=#s^6
zm`_j(eS=y+LSB~|KQ%_w^Phu^Cdy-$L=9LKHDCvecQ*%{<4~{cnWztyO{mX|o0tQ=
zMDG2O6E#jL)I1f;x|mwee@kmH)GEec9OBc>rB=V$+=aUN4x$FUfVxL+qb|{3s0m{x
z)*13Sf;#iWsLz&A)Q%Lwz<>YOfQ&xZJD~>ht^5OOz?G;oJ!s_{s0m)97VrTzK{P&T
zbZrx$CeDO<BW6RLP(ic2SuY9Czbe`gh>g9?Vb)*@YTyOtPv&NGuX!A`p!29}d)0hw
zzBQvJb@fTG6zwu5<@wi&I}p$S-=jW6MxiF&Xz|^sGd*OUMJ@b>m7kh#Q9BqZnKOx*
z1vOrA)I1d|Ufs7$ODsS|AJmqwF^{4qzG*&1o#9(EYI1i1Nl@|Zs0oUrCM;)GM~%}E
z)vhh7o&TLx3`Sk6aaJ)MGf<vu^@q)Kr~!UMo#``+e=%dFa1$jnGoU8QYvm$l1!RG~
zSJxVRYZYzHUKaPQJQ_7&IBJJhpw94s)t|KT6)WFCP5j)-ugxI7sa7B!2Ls>#>yy#I
z%}@jOK%L=0)Rv96@+{OBkCmu)$FLcmLp>eYQ@MCW)Wo%|+z2&ZYqK|M+z}Y~_kX66
zQHQ0dfmfrR&#hLzh#KG~>dc>`ZrUiRUB8s50n?hf%;IKcvjOTv+nD{(51gSjn1z~P
znU(jMr_8J71Jr_FneR}K?-$fUV~4l}r9!pKV&&YZS9}SxMTmX=54VQnPy<axEo=em
zd;A*I$}gIaPz(JRH9>+<*FKq<0Ts`ST2K*-S2i1%Z9@H^z;Cgh7FdJoxYImf@#E%2
z^A47w-E%AF3UdoAj=6}}wDK@3Pe+~kG1Lh@M$Plaw~CLbm8MSP&Ljuw8W%Ndp*plj
zz5BbNc4Vj-ZmvM}+hyf*s8{<v)Z_gY^%)Q$t=mCAIT;O<*DP-pjm%yapMZf&V&yfc
z1?|Twcnou5{B%KqKU$SWoltjFKOfb8B8FhNi~HUdGP>&zqJBc1!ff~wwUsH;yEkJs
z%s_c0>g)O%)ID$*b;dVPC-TaSl);sgpgzvCpynx$T2Re^eEv4GKqu4y{ZK0%Z%#vX
zoQ>+Z#Nr!J?YE;QIB7maUF)EXu3uWzc-c|cJ|AkFG8lONYbZmY73z$>vj&q<6VEl5
zqXybwZa4R#20V(|!C$QWj~OwO`yvt#3sWD4wXg~5-#_)%k=cNiGrI-6H-oddfwP%~
zQ41(<<!V-LY~_}y6X=FIp)nSpW3EK?-->#Z?#aUQuUF@F0=g?-qi&j5SzW`Fs2xa)
zI>YR!ySRvzzd^OHZMH&9(90Zv>Nga%ut})#R#^SUtUUkfu)`YeH&3JP(rc&=?@$v(
z$mUFd>X!!f8!<C#q9UmF6;SPKVFYYxwn5#j?NPt~hxlalMPd%>XYwl4z}rw;xEFKc
zIr9rvqntB)kXIXrpxT{B?cjYYe?W~BCx`p?oCudtE`eIWT~xjQ)-s>X$T?j_EG$if
zVAKTlP-ob|>c6w{U~?R50W+<<9<>vDP!k<9&zKi6jXwW>C8MugpHQEAnR2<`{S{DK
zSQGWeYk^uwFVq`t6l&l(s54rOTHp>VAGPwY=3~^;@!HDCa%()E{|sdG{1!$%xAjm1
z^+TP(NYqU_8TIRR73$mVKGd(+Ll}xTP%oyBs7o1~$1N}fHC_hP3FJlfE02MH|Gxzp
zok1sSFcfvShNC*JHFsJ3IBKBVs0IFIenjm^l)SEAY}8*+l3O_~s$VYD&X&c%=YJh*
z(83yYwFW~iKGmF$`YE>B$`?@s-a#$oZ`6dJtUgLUw~$~n6xBYvl}qL0`B$Kt1zMP0
zQIFL?bArX^nX6F!wxjNylc-Dg8g*ug^Sf7V2Gsi^A8JQSqP}G}MD6&L{5=1<_R9(A
z!{!ibfWJ`j2nF0<GE$?;wNV|rS$U+n2z77lMfE?A8t)FOef)xMAsJEQ<UzHs?vv3q
zZe?~y-Q9!DY32%Zk9ppFh`Q$Q&7eYVylALPk_fd^Ar{YrYG2agetF9@GP``OK%L1C
z<`Ro<Mm?s-P+R)I{ABfs3%ht`)QOcbYoI1>in?U2k%jr*WHS1Ww-~kJlc=q^XywP|
zEAs<pr#^BK_dMrC^=pV)SS!>S4?|5j9d#meQ43mQ@tuJ(&;J3dIAdPN3^aU%8X$I2
zH()~402xuwZ$8w-)lt{9A!?#NsONtqs{K@RzPTFpLfe6fncq994BkOa_}2VvMlR+C
ziiJ9}WT?M-XR~r1)WqN5B&>&;_`dn4`3ZH&Vib3#MPGMkF*33?Y5^TED|WZ?TyqI(
z;8o^!^N4vK)&C}HXC7Gjh4}`x(2rIhs|3%#0*OnwiVS7})R~sYD%c1$@N(3^Yf(G4
z-Qqu^7Iq1B58Sn~{+H+)CpK!HP}HT$W#y_ReYX`&38>+Bs29mt)PSqa9jF10q6WBx
z+R8ss3yWULwU1|}LfzC^Q0;45yc??hAk>Zz_pM^Kx!fu?TloZP;>+ek)B@k221ruc
zJuTT$6P8BpP)F1W^+r8zqfsxUO{f#QhZ@&^Nk&`w1+}uoWn6<)r~$H|;>A$|mouxI
z4XwTvYT%Am?u&Yb4?&GH8P$I=s@)nF_r0BDw3Vl=;sNUMcxB~?W!<YY9%`TzsP;Kf
zA2t<G1J^_i+!%Eaw72qT%tkpJ`NH8HM4kD4jIGcAzscxBBB-4EyIm~Q07X#)H%9G1
z8`S51XDfF%`=Z(nLA@8oSbQ;RqMxk1(>#D$=y8?x{9h!a0e&?fpw93Gs$tY`oC(b^
zGY9G(D2m#dTBvc_SbaAP+-z1JZcf3Xw3~;%?#^pu)bKUx<M9J(;ymTuz$H;PQEgPa
zA*lM1s0B>3_)2p<Y9ZTD?GB(8c*e@NQR6%-Z=e5vTSb%#u0t@YLnvws^O|K*6V^cu
z+|lBFQ9rFlqXwRC@wuoU8f&b45_?j<j(SB`spz{*gNn}9W_Q#*F$lGQ(Wtw5ChE*q
zq86~p%KOa|sCE}nA7b}W{okV6N3G-*m=FUuvu}YMs0s6<&af1!Lw(e}&>B17U@JdF
zE#xz5f@qapIVq}N8dN-|l}n;_rYh>Gsbg`!DH*M_BkJq%5Y&WAtic}hgn8M#XTCH)
zq9%x5#VsJ7nF{q`l?63!E>ycpPT#9ZMk{S#wnv>=KPwMI?aVaP=l(p@0H>_}7u3La
z&G)GO!ByRxG8LAjToSc2KC1u3fINTURx!saR$6&I>UrN|<pWlK1~tJ&E8j#t_YbW6
z86#1ST+N+W4Ad(-IqI4hvv>^*{P%y&t)dI+Ong<~Y}7={Q7hhH@$IM`J7Qi$wYzWi
z&n^BQHDQeE?#E^-RJn**4FiAwZ$U-_^frf}CLDuW$YgV_`IEWLJZzpbe?#^E9rY{s
zPb<f+;pRzbrmn&BuZc4eP=`FI4uw%WQQyklQ9mvxq879a^^<H9>Tx@RneZltV3e9}
zhccK2Q2olAbx`eF)a3cshr&1utVLa`%jR3$M>$!opuoSVbQSe6Teo(QR|5xQc|3!K
zF}RL<e5;|_wZ<Yi0Sn=A)EoB;YMvB+UH4&A9Cdd$MScGtj}34k4#&6H76;Y~3j9l{
zcTi`LsJ@%91nQosYvnem1q?)em@UCjJcOF~9+p8rQUmwJpaN=(`=eGk6?F;LqTUO~
zFb6)xA23-%cQdU;)gM4D;DN<on^7CNOPU-tUP07NSQA+Q|NkFkbPuesij5e!yRCfD
z%8#u459(S*Z|nw2jC%YsqvB=Fnr1Vzli3e-uZ_g$`uv|@6*I6p6-!Vb8n19P#%&Vh
zRm7R7YkV7ZsggAf@~UD5Y>3lQAFIz%6J&1Y7MKflNz0<X*fcadVc_{6Oh#KWP63=}
zu0p*!x1$E!Yw;tfEkBRCwr^0^I^nnO(iKDPXhYOJ(#pycP@j4;a3?NCe;}F0&E3c6
zWo$+HKB{5)7VeKzwNVRbiF({Rpe7iA`tCTw%5zZdmZ2`;8r0*w$GnDVD8E773rSn@
z{A+;RE!}_>Q9DrEY;JZz4LAVxSuoC=j+$^Gs^1E83znsP5Or@vYUSFcMlC$OnX?to
zzd9Bspi595HBlogcQgl^Q*b=>ORx}TZ|(ZGL-p%z<q@dyrlLMwms)uTwxoOtwUBIn
z8~6McFsq^}TA>E)f?D8UE044CkEok)g_SR%w)C!*-=q3RZR^HMf+~lh7M2^;-Y-X{
z7@20MyM7L8!ky+Z^8#v1Z=<$6Z9Dhrm<6@q9H=ubWaX-;aq6Smw>CSOJ+X_P|NdmO
zl82~)KBHC`t-Tu{1!~|-sCY5dnb$Cfp!%;dkD{K6o2ZZPkEn6=ZzpL%F;KrLlVIS#
z|7%Sq7lBTg9_ON7k%w?8-bX#RV>-IW@ki8$&qCCjayRO6yn@=|52%I4?BpK5)R={G
z1ysBj=EYH%g7=TN%PKCTzWY5vJ-45+1ZM2)-qr1}9OYH0Eq#GHqc>)RE-oGy69@5A
z4%1Sfy{mf)YN2+dGipb=W8m|D02!@pqE#$JJ*TTs6P!Vv*>$V`9ksx}Q9F>bo13^0
zYJ!rO4a;Iy?19>Wd8i%!pVdF_#`CWR$-BD-<xvfKVkpi+eV*^M_%+m4f3|qq9<E(k
zRJ%5){v%QCR$KfWYN0R9m_6N2XY9%IuPrZ5KyRu#s24^LE04GGN>sZ;s5j$PWQPO)
zLTMwNGDprx?qAcKO*xpnj>_cQTD^<#H-rc-cZdN_cCdm%$!S=G@?<*q#s*e5gZQ5`
zK1`cq<lkDn1npAWL}`g7v%JQNMf;_s%(S0LJVJP_8o`nK5NW8KznJ!$sME38bS1u1
zP*;+|W%_L*%_V;Wv)H_9w~%~4Vxvi^>ED>xR$@7=O?frqI7R)}qdxhJ)W?m)W6vL0
zy`k24Ic}uYHw;wtKZ|Ken?ck?BDJ9NkJN1>Ev0QG%1dnI)8t!zodxGo))5`2;wmc_
zp>G_<N)p7)5`)Y*Du2i4OcX|?ZgL&z!-v%j_D2)d@s^s}3{lR?+`V2y%Dlq^$3k;I
zt|$FOI>D$qLTFc({6g}7kj|2C!gxBqwPo>s@!nJ3O4>wfOM1_v2`q`m(`m?!>J=mX
zkJO3Sa$=WAM{JNT44jbklJuE2-;wwV=C!3h8nOH2b=)VfV<qJ>)a52WjaVk~`og(`
zREKic!2dLf!Y|e#t66}_3)x^}$gj6JO}!<QD`0G^?@QfL22MjcIjINvuSaRx>Nrn|
zM*cLZJ^7vV*{?Bm{wqn_C_JHaW%7H--=yJcHQ?xlp*E1p{Yj;XbtN4k|BO_e{6YHX
zXYygR)rZ9_JdO*oE%lGce?6)Y>qc9DxUKf6)qF$4s#NyG7Yx|i>hlrfL&h6`UymlV
z=}T+}ZQ_w$QrCl60b*Z|0+e;Mq<*-?XQ>bIfx7-v$&9r@_s~e6LY46&-lCztI+dpl
zKRyCS5cx+W9VKvx_0{)w9jl04BGsh5UWc*CXU1WefN{5w`10!IM*gP={2rs?$bZgC
z;UQFhPh3YE<okfvn|#$kC+==r%zpZ<CAJc8(QY3W#H+-b(<WW`^EyfVST>SI%R`z)
zxeqOeD8Lbid<j~YL>>QqU+T;F*CRXi53NmR+BdUtFIa;M%=*$+)`oV4sIL@(-)7rs
zP|zyWHZK*Wu{s^jD!|c>w1ZAViH#uXh!_5<PH_17x{-?iX1x>9;$K(k-KLd3Pjplx
ze#4fda%9RuBz=#p6&}A{5`P-4AJC$fsyQxF8--Mtbe{M>%y5NNg?0leFLuqm6*hAg
z+D#(9lzM$tT1);6`jmB?vv&H{QI&L<cq#hmn5!G@03B*sBL(#{XaJ4w5wAcRN!>-O
zFGbxf8#o4ooS?i4CzHOA*OAxS?y^bJQ~p5GkBxjvR{xB#Yuk&?8$qEj9nztWc{IvE
zJ{tLDSebGTCJwhjM-uy&^ql(FsN*x~Kp@BN5o=1yPg+i&+4P;k7}v;uPyP+<_~zvG
z)r%&Uol!O#>+3LIy#oKwq;G97(ZeQ=OxsqJlhU>lCa0{gJ2~m|g%p?g*W)4OVw5l7
zM673Hyu%=3<w^eksMto2wG?zTw?;{^Cxaih_+iS&txoMK((ja&Z_{QGZHM7%)bTCp
z8Ra#!%YxM?Pf!I%4BDh4)>8i;yx-X%_X)-)y`$nPDK%*~b%8H!xRG*c>f>Tz2Gx<3
z_!?3<$_*)R#4^<Dcu8tU`9A)p0LKf;-!aBN<ZI&auh)MMfe8%Mn$&^xh(W57a?n9X
zZj4OQSK?Qsbv8+R2Kj~jU1E30&nKUd{#mguWgWH5H0BT+Q{PGx`&Rgw4jpLl8=V8+
zW7U%*nbkk0E*o{rX}6wud-A!6Wg%&dJe0$%?P2Un`7&*<;D3(^#B|&uEu~KPpI3oF
zz8(X}WU@{-EuMo;hlsVN?iK29HP5Y0T5Hn^lh^`s;S<{YN}JrIA1Oy+jPc})k%p3=
zLadXn|5gf%Nhj&>4eHoJnn_AS`iqABEnbpIHc-}4(qe1K4<>enbSO~c{*j&fze#(E
zKce5CIE`{*@(D?g$&ZYfmPd)q4pI=oj;yX9`4!}K6d;WbFWorU*Z)WLJW90~W-+b$
zQyxct9xlTFsX504^7@Imj`Yw*c}{FAeIgSpMJ${dbPOhCpgatVD!}oYx<0f|N&DZZ
z8%2t(>y*nnO*Es>NJk>d)5(vZ!!M*LbkI?q{B4{^T}I5WAjdV@53n(^+ZcIiJBier
z^b2jGqK+=u6PthiLUx_PN+yWP0KcjQM_2M)h}EI-L{d1h5u`q<<oKIO22+2K{7mv6
z6y&%-zMRW?-`j#}*n&zTKV`ioR$ix%lWh#HBNG)TND)YLXfU31+3NHINyj|O@o)iY
z1NjBCSz&F;GFCN`j>k4ZBl5AS=eJeh$VL8JQhn<acurJv#u_MpkU@%Ac^gKc9G?yq
zsY`&JDW4-hj{HUZ!v;G=+h3XZJ?T7c$`SvaSRt#YY2Y|cosKE`q|y<c27CX%MvDJq
zXQ6x}@+qyO$`L7Nr`+7yG*ghHSa?{oVE-P|?xb{?+7_faHhN!rG@$Mt<&U_6y4s}P
z<aOM|{Wy`7l6(s4GSGG(>ex)InzhY?VYZ@{v>8FU7j33Q<d^?<bT~n9D-EiVFA#pL
zSz5oKHP4C-H7s2^(Iqo222s}W1EwQoCBK+<sd1%EUzm6*lK%F&nb;okI=<i%Tb9bH
z=r@Y;LE7BG4hrgNdr!j~)@gtZs+u#zM$#z-PN&0={|t79_%h;!Xg8VoC;D9{{YmT&
zX%ey7q^QJ-YcP)Kq}9~LAijuvC&sw-^=XSk;YWfx{-u$QrF7m;d<|(4osy!CnbhB=
z?!U)t3LlBTz>Bm?M*cqO7we<8>nVSsUl+#u>1$kfdtw4ASD?W$GAqbuB&H)Z9SRW(
zaYe5?@uD_)IpVD}nALsdA(^zqkJ=cQFfC($pkFUMgPCY^fxLgp2D?h&8YvZJpNfta
zUqD{R4N@;A{E;+<l)(lci<M}TkM<A9A0thoJ{r~!^yDiR^$$p|NhgWxq(f=L;d{}@
z+@fM4&T&ES7=zWN;WjIe3AE)mHnDTW-q3zEu_fe>({?-YO(Y#Ps9Q&@26ZQ`|G!qZ
z0DD<}N<fyPzlSa(wWIM=f{)2(Vt^mW|3%tG{3GSFconM?>qr|NVdRq&8&6#}@~xOW
zfvXDqbFcc7ViMQU7~|1iM-S3$-wNH#-vd?dAN;}JdrCY9ordEo!U>7xVY2R&Uy)B^
z1Ggbxp7{Sg$nPcXCXj%(v1s=zZQfafNR;=I_k+pwr@_yp$TX;eI=;n4)Rn>+ly6Y?
zhE$P3Q(<A7ECOx*pv`<MH!;uBrVgno^&UR4aXVA4Prf}VO$5Goq$HD`#DBbO)|sr=
zQyn?N!-usBPPTxWu{6oeP~VWRgm)=F3SZYMNwe>1n}N1}V{{z*pK-p?ARK>_8WZnh
zbq8sioY*B*a<pQ!%>U_E$A!J&;bE<V{W{bPvf46QD#ue>;VRbBkMcPyH=<o@+APFb
zftKzc7m1ajO(fduC_<`9>@pT4-V|rh=M(w<Hr6}p_k8^;(I^T(+ad;9g9;3mp4cur
zKOpHiU~QI@|BE!Ae!mjijR|P~C$ZvqfH9Jg5|cjIcp<hpns_aU{YD?|3a$eKoUnn{
zV++F3RY~dwV@V}!kloZzAr&G0q<V|f#9JFaq)ih4B$3G~a*TF(d1;-|T8<+2nVv^T
z?O4+9#4D56af~$G+C`<0jy9yp)Ni1C*J2UvR2t(P(jeMApza5~c0z2hjReM7hgdX-
zPQ!Q%o{?BtTubch@q_j0P2CLgS8yt66z#6i=q-IyQ2vK<GV+h{4{U7xG){H$&Axu@
zRH1S;DU6Ck|7kRc*l5bv80_mYo6J+vP6qvYY^Oei@=yZT$?v3Jck6S2d_BwmWqpni
z)A6mZO41!B$w_5hf}gEXFtH8P-J^49Y))N18|WN$T`2$0%7<_;Z5om06W7s?ah{RJ
z5c_(JBj1s>ujoIXe9%wf)7l05!wAJBG?x^Ud`)X#pC-x3pT~&Ab@Wi4Vb@?`(o@nV
z`kivs-a1?U&$!+4w{bA(du#K=;y39RDH4B*x=NrZ6Ewrq)~Go7Ycy!V1Um9lo<`b7
z{-*vO<nOd4srHBe<m=IEAmwG&^Ekes=VoFv$&aC)qF0oBXY%#PSH+41m(gYt<tC)q
zHfAF7rEIJ>w6nwa+R$K^1^VG7jryOX0rhd{IG1=RZl-Pv`O`L7L2J8@c6W)NCsm|w
zJ7XoW$!ilkN}5k<N78YfHlY#tjkD$dt;VZCa3~EX(6P96{*l<0@JSt#G&)Vo>(rJf
zHKjHV!=#|LCgt6D7IoYS{F5J5IF(o;8!0|*8c>eUIG@PtC`)>{<x_`AIij>{*|AI8
jHd}_xdNv~R!)2SEY~8{CvhZNe2<!Im$XF$4YKH#<xUo_@

delta 26851
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
TO%=2wPw<{i+w0c|nwsT*M!iGI

diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po
index ebfe5b919..4dd34c8d4 100644
--- a/apps/locale/zh/LC_MESSAGES/django.po
+++ b/apps/locale/zh/LC_MESSAGES/django.po
@@ -2789,7 +2789,7 @@ msgstr "短信服务商"
 
 #: settings/serializers/auth/sms.py:15 settings/serializers/email.py:69
 msgid "Signature"
-msgstr "署名"
+msgstr "签名"
 
 #: settings/serializers/auth/sms.py:16
 msgid "Template"
diff --git a/apps/settings/api/alibaba_sms.py b/apps/settings/api/alibaba_sms.py
index c7f42f110..32460778e 100644
--- a/apps/settings/api/alibaba_sms.py
+++ b/apps/settings/api/alibaba_sms.py
@@ -4,7 +4,6 @@ from rest_framework.exceptions import APIException
 from rest_framework import status
 from django.utils.translation import gettext_lazy as _
 
-from common.message.backends.sms import SMS_MESSAGE
 from common.message.backends.sms.alibaba import AlibabaSMS
 from settings.models import Setting
 from common.permissions import IsSuperUser
@@ -23,7 +22,8 @@ class AlibabaSMSTestingAPI(GenericAPIView):
 
         alibaba_access_key_id = serializer.validated_data['ALIBABA_ACCESS_KEY_ID']
         alibaba_access_key_secret = serializer.validated_data.get('ALIBABA_ACCESS_KEY_SECRET')
-        alibaba_sms_sign_and_tmpl = serializer.validated_data['ALIBABA_SMS_SIGN_AND_TEMPLATES']
+        alibaba_verify_sign_name = serializer.validated_data['ALIBABA_VERIFY_SIGN_NAME']
+        alibaba_verify_template_code = serializer.validated_data['ALIBABA_VERIFY_TEMPLATE_CODE']
         test_phone = serializer.validated_data.get('SMS_TEST_PHONE')
 
         if not test_phone:
@@ -41,12 +41,11 @@ class AlibabaSMSTestingAPI(GenericAPIView):
                 access_key_id=alibaba_access_key_id,
                 access_key_secret=alibaba_access_key_secret
             )
-            sign, tmpl = SMS_MESSAGE.VERIFICATION_CODE.get_sign_and_tmpl(alibaba_sms_sign_and_tmpl)
 
             client.send_sms(
                 phone_numbers=[test_phone],
-                sign_name=sign,
-                template_code=tmpl,
+                sign_name=alibaba_verify_sign_name,
+                template_code=alibaba_verify_template_code,
                 template_param={'code': 'test'}
             )
             return Response(status=status.HTTP_200_OK, data={'msg': _('Test success')})
diff --git a/apps/settings/api/tencent_sms.py b/apps/settings/api/tencent_sms.py
index 27ad07327..5395a1305 100644
--- a/apps/settings/api/tencent_sms.py
+++ b/apps/settings/api/tencent_sms.py
@@ -6,7 +6,6 @@ from rest_framework.exceptions import APIException
 from rest_framework import status
 from django.utils.translation import gettext_lazy as _
 
-from common.message.backends.sms import SMS_MESSAGE
 from common.message.backends.sms.tencent import TencentSMS
 from settings.models import Setting
 from common.permissions import IsSuperUser
@@ -25,7 +24,8 @@ class TencentSMSTestingAPI(GenericAPIView):
 
         tencent_secret_id = serializer.validated_data['TENCENT_SECRET_ID']
         tencent_secret_key = serializer.validated_data.get('TENCENT_SECRET_KEY')
-        tencent_sms_sign_and_tmpl = serializer.validated_data['TENCENT_SMS_SIGN_AND_TEMPLATES']
+        tencent_verify_sign_name = serializer.validated_data['TENCENT_VERIFY_SIGN_NAME']
+        tencent_verify_template_code = serializer.validated_data['TENCENT_VERIFY_TEMPLATE_CODE']
         tencent_sdkappid = serializer.validated_data.get('TENCENT_SDKAPPID')
 
         test_phone = serializer.validated_data.get('SMS_TEST_PHONE')
@@ -46,12 +46,11 @@ class TencentSMSTestingAPI(GenericAPIView):
                 secret_key=tencent_secret_key,
                 sdkappid=tencent_sdkappid
             )
-            sign, tmpl = SMS_MESSAGE.VERIFICATION_CODE.get_sign_and_tmpl(tencent_sms_sign_and_tmpl)
 
             client.send_sms(
                 phone_numbers=[test_phone],
-                sign_name=sign,
-                template_code=tmpl,
+                sign_name=tencent_verify_sign_name,
+                template_code=tencent_verify_template_code,
                 template_param=OrderedDict(code='test')
             )
             return Response(status=status.HTTP_200_OK, data={'msg': _('Test success')})
diff --git a/apps/settings/serializers/auth/sms.py b/apps/settings/serializers/auth/sms.py
index ad63a9907..8320b11eb 100644
--- a/apps/settings/serializers/auth/sms.py
+++ b/apps/settings/serializers/auth/sms.py
@@ -8,12 +8,14 @@ __all__ = ['SMSSettingSerializer', 'AlibabaSMSSettingSerializer', 'TencentSMSSet
 
 class SMSSettingSerializer(serializers.Serializer):
     SMS_ENABLED = serializers.BooleanField(default=False, label=_('Enable SMS'))
-    SMS_BACKEND = serializers.ChoiceField(choices=BACKENDS.choices, default=BACKENDS.ALIBABA, label=_('SMS provider'))
+    SMS_BACKEND = serializers.ChoiceField(
+        choices=BACKENDS.choices, default=BACKENDS.ALIBABA, label=_('SMS provider')
+    )
 
 
-class SignAndTmplPairSerializer(serializers.Serializer):
-    sign_name = serializers.CharField(max_length=256, required=True, label=_('Signature'))
-    template_code = serializers.CharField(max_length=256, required=True, label=_('Template'))
+class SignTmplPairSerializer(serializers.Serializer):
+    SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature'))
+    TEMPLATE_CODE = serializers.CharField(max_length=256, required=True, label=_('Template code'))
 
 
 class BaseSMSSettingSerializer(serializers.Serializer):
@@ -25,23 +27,18 @@ class BaseSMSSettingSerializer(serializers.Serializer):
         return data
 
 
-class SignAndTmplSerializer(serializers.Serializer):
-    verification_code = SignAndTmplPairSerializer(default={'sign_name': '', 'template_code': ''})
-
-
 class AlibabaSMSSettingSerializer(BaseSMSSettingSerializer):
     ALIBABA_ACCESS_KEY_ID = serializers.CharField(max_length=256, required=True, label='AccessKeyId')
     ALIBABA_ACCESS_KEY_SECRET = serializers.CharField(
-        max_length=256, required=False, label='AccessKeySecret', write_only=True)
-    ALIBABA_SMS_SIGN_AND_TEMPLATES = SignAndTmplSerializer(
-        label=_('Signatures and Templates'), required=True
+        max_length=256, required=False, label='AccessKeySecret', write_only=True
     )
+    ALIBABA_VERIFY_SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature'))
+    ALIBABA_VERIFY_TEMPLATE_CODE = serializers.CharField(max_length=256, required=True, label=_('Template code'))
 
 
 class TencentSMSSettingSerializer(BaseSMSSettingSerializer):
     TENCENT_SECRET_ID = serializers.CharField(max_length=256, required=True, label='Secret id')
     TENCENT_SECRET_KEY = serializers.CharField(max_length=256, required=False, label='Secret key', write_only=True)
     TENCENT_SDKAPPID = serializers.CharField(max_length=256, required=True, label='SDK app id')
-    TENCENT_SMS_SIGN_AND_TEMPLATES = SignAndTmplSerializer(
-        label=_('Signatures and Templates'), required=True
-    )
+    TENCENT_VERIFY_SIGN_NAME = serializers.CharField(max_length=256, required=True, label=_('Signature'))
+    TENCENT_VERIFY_TEMPLATE_CODE = serializers.CharField(max_length=256, required=True, label=_('Template code'))
diff --git a/apps/settings/serializers/other.py b/apps/settings/serializers/other.py
index 6ca55009c..986d614fb 100644
--- a/apps/settings/serializers/other.py
+++ b/apps/settings/serializers/other.py
@@ -1,5 +1,3 @@
-from abc import ABCMeta
-
 from django.utils.translation import ugettext_lazy as _
 from rest_framework import serializers
 
@@ -17,8 +15,12 @@ class OtherSettingSerializer(serializers.Serializer):
     OTP_VALID_WINDOW = serializers.IntegerField(label=_("OTP valid window"))
 
     PERIOD_TASK_ENABLED = serializers.BooleanField(required=False, label=_("Enable period task"))
-    WINDOWS_SSH_DEFAULT_SHELL = serializers.CharField(
-        required=False, max_length=1024, label=_('Ansible windows default shell'),
+    WINDOWS_SSH_DEFAULT_SHELL = serializers.ChoiceField(
+        choices=[
+            ('cmd', _("CMD")),
+            ('powershell', _("PowerShell"))
+        ],
+        label=_('Ansible windows default shell'),
         help_text=_('The shell type used when Windows assets perform ansible tasks')
     )