2021-08-24 06:20:54 +00:00
|
|
|
|
from collections import OrderedDict
|
|
|
|
|
import importlib
|
|
|
|
|
|
|
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
from django.db.models import TextChoices
|
|
|
|
|
from django.conf import settings
|
|
|
|
|
|
|
|
|
|
from common.utils import get_logger
|
|
|
|
|
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',
|
2021-09-09 13:11:26 +00:00
|
|
|
|
detail=_('Invalid SMS sign and template: {}').format(e)
|
2021-08-24 06:20:54 +00:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BACKENDS(TextChoices):
|
|
|
|
|
ALIBABA = 'alibaba', _('Alibaba')
|
|
|
|
|
TENCENT = 'tencent', _('Tencent')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class BaseSMSClient:
|
|
|
|
|
"""
|
|
|
|
|
短信终端的基类
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
SIGN_AND_TMPL_SETTING_FIELD: str
|
|
|
|
|
|
|
|
|
|
@property
|
|
|
|
|
def sign_and_tmpl(self):
|
|
|
|
|
return getattr(settings, self.SIGN_AND_TMPL_SETTING_FIELD, {})
|
|
|
|
|
|
|
|
|
|
@classmethod
|
|
|
|
|
def new_from_settings(cls):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
|
|
def send_sms(self, phone_numbers: list, sign_name: str, template_code: str, template_param: dict, **kwargs):
|
|
|
|
|
raise NotImplementedError
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class SMS:
|
|
|
|
|
client: BaseSMSClient
|
|
|
|
|
|
|
|
|
|
def __init__(self, backend=None):
|
|
|
|
|
m = importlib.import_module(f'.{backend or settings.SMS_BACKEND}', __package__)
|
|
|
|
|
self.client = m.client.new_from_settings()
|
|
|
|
|
|
|
|
|
|
def send_sms(self, phone_numbers: list, sign_name: str, template_code: str, template_param: dict, **kwargs):
|
|
|
|
|
return self.client.send_sms(
|
|
|
|
|
phone_numbers=phone_numbers,
|
|
|
|
|
sign_name=sign_name,
|
|
|
|
|
template_code=template_code,
|
|
|
|
|
template_param=template_param,
|
|
|
|
|
**kwargs
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
return self.send_sms([phone_number], sign_name, template_code, OrderedDict(code=code))
|