Source code for univention.management.console.modules.passwordreset.sending.send_sms

#!/usr/bin/python3
#
# Send a token to a user using a text message service.
#
# SPDX-FileCopyrightText: 2015-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only

#
#
# This is meant as an example. Please feel free to copy this file and adapt #
# it to your needs.                                                         #
#
#

#
#
# If the return code is other that True or an exception is raised and not   #
# caught, it is assumed that it was not possible to send the token to the   #
# user. The token is then deleted from the database.                        #
#
#

import os
import subprocess

from univention.config_registry import ConfigRegistry
from univention.lib.i18n import Translation
from univention.management.console.modules.passwordreset.send_plugin import UniventionSelfServiceTokenEmitter


_ = Translation('univention-self-service-passwordreset-umc').translate


[docs] class SendSMS(UniventionSelfServiceTokenEmitter): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cmd = self.ucr.get("umc/self-service/passwordreset/sms/command", "").split() if not self.cmd: raise ValueError("SendSMS: UCR umc/self-service/passwordreset/sms/command must contain the path to the program to execute.") self.country_code = self.ucr.get("umc/self-service/passwordreset/sms/country_code") if not self.country_code.isdigit(): raise ValueError("SendSMS: UCR umc/self-service/passwordreset/sms/country_code must contain a number.") self.read_sms_secret()
[docs] def read_sms_secret(self): self.password_file = self.ucr.get("umc/self-service/passwordreset/sms/password_file") if self.password_file is None: self.log("SendSMS: No sms secret file set") self.sms_username = "" self.sms_password = "" return try: with open(self.password_file) as pw_file: self.sms_username, self.sms_password = pw_file.readline().strip().split(":") except ValueError as ve: self.log("SendSMS: Format of sms secrets file ({}) is 'username:password'. Error: {}").format(self.password_file, ve) self.log("SendSMS: Format error in sms secrets file (%s): %s", self.password_file, ve) raise except OSError as e: self.log("SendSMS: Error reading sms secrets file (%s): %s", self.password_file, e) raise
[docs] @staticmethod def send_method(): return "mobile"
[docs] @staticmethod def send_method_label(): return _("Mobile number")
[docs] @staticmethod def is_enabled(): ucr = ConfigRegistry() ucr.load() return ucr.is_true("umc/self-service/passwordreset/sms/enabled")
@property def udm_property(self): return "PasswordRecoveryMobile" @property def token_length(self): length = self.ucr.get("umc/self-service/passwordreset/sms/token_length", 12) try: length = int(length) except ValueError: length = 12 return length
[docs] def send(self): env = os.environ.copy() env["selfservice_username"] = self.data["username"] env["selfservice_address"] = self.data["address"] env["selfservice_token"] = self.data["token"] env["sms_country_code"] = self.country_code env["sms_username"] = self.sms_username env["sms_password"] = self.sms_password # # # ATTENTION # # The environment is inherited by all programs that are started by your # # program. Your program should remove the token from its environment, # # before starting any other program. # # # print(f"Starting external program {self.cmd}...") cmd_proc = subprocess.Popen(self.cmd, env=env, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE) cmd_out, cmd_err = cmd_proc.communicate() cmd_out, cmd_err = cmd_out.decode('UTF-8', 'replace'), cmd_err.decode('UTF-8', 'replace') cmd_exit = cmd_proc.wait() if cmd_out: self.log("STDOUT of %s: %s", self.cmd, cmd_out) if cmd_err: self.log("STDERR of %s: %s", self.cmd, cmd_err) if cmd_exit == 0: return True else: raise Exception("Error sending token.")