Скрипт для создания почтового ящика в iRedMail (MySQL)

Обновлено и опубликовано Опубликовано:

В iRedMail Pro есть API для управления почтовыми ящиками. Мы же рассмотрим процесс создания почтового ящика с помощью своего скрипта в бесплатной версии почтового сервера. В статье будет описан случай, когда учетные записи для почты хранятся в СУБД (MariaDB).

Мы рассмотрим отдельно SQL-запрос для создания почтового ящика в базе данных, а после — скрипт на php, из которого можно будет сделать свой мини API.

Запрос SQL

По умолчанию, почтовые ящики iRedMail хранятся в базе данных vmail, таблице mailbox. Чтобы создать новый, нужно просто выполнить SQL-запрос на вставку новой записи. В самой таблице более 50 полей, но нам нужно заполнить всего 6:

  1. username — имя учетной записи в виде адреса электронной почты.
  2. password — пароль с указанием хэша. По умолчанию используется SSHA512. Процесс генерации из командной строки будет показан ниже.
  3. language — язык по умолчанию. На самом деле, можно оставить и пустым — на запрос это не повлияет, но для удобства лучше сразу указать язык.
  4. maildir — путь к каталогу для хранения почты. Данный путь собирается из домена, первых 3-х букв в имени пользователя, а также даты и времени создания почтового ящика.
  5. domain — домен, для которого создается почта.
  6. created — дата и время создания почтового ящика.

Остальные поля можно не указывать — значения для них по умолчанию нас, вполне, устроят.

И так, чтобы получить хэш для пароля нового почтового ящика в командной строке на сервере iRedmail выполняем команду:

doveadm pw -s 'ssha512' -p 'password123'

* где doveadm — административная утилита dovecot, которая устанавливается вместе с iredmail; ssha512 — указание алгоритма шифрования; password123 — наш пароль.

В результате выполнения команды мы получим что-то на подобие:

{SSHA512}iNX3KgDLYVvA+nQKlJf4GUVOTLwiyxYpBoAD1NBs1CK0rIG4XVbPXWWeN5lRrMXljQD16s9q9ny+EO8iX7SpnbH/+K0=

Это и будет хэш пароля, который мы будем использовать для запроса.

И так, синтаксис самого запроса SQL выглядит так:

INSERT INTO mailbox (`username`, `password`, `language`, `maildir`, `domain`, `created`) VALUES ('<username>', '<password>', '<language>', '<maildir>', '<domain>', '<created>');

Пример запроса:

INSERT INTO mailbox (`username`, `password`, `language`, `maildir`, `domain`, `created`) VALUES ('testmaster@dmosk.ru', '{SSHA512}iNX3KgDLYVvA+nQKlJf4GUVOTLwiyxYpBoAD1NBs1CK0rIG4XVbPXWWeN5lRrMXljQD16s9q9ny+EO8iX7SpnbH/+K0=', 'ru_RU', 'dmosk.ru/t/e/s/testmaster-2020.02.25.22.52.53/', 'dmosk.ru', '2020-02-25 22:53:50');

* в данном запросе мы добавим почтовый ящик testmaster@dmosk.ru с паролем password123 (хэш мы генерировали выше), по умолчанию для пользователя будет использоваться русский язык. Обратите внимание на каталог для почты dmosk.ru/t/e/s/testmaster-2020.02.25.22.52.53 — как и говорилось выше, его путь собран из домена, первых 3-х букв в имени пользователя, а также даты и времени создания почтового ящика.

Данный запрос можно выполнить в phpmyadmin или командной консоли mysql — для подключения к ней на почтовом сервере вводим:

mysql -uroot -p

... и вводим пароль пользователя root от СУБД. После подключаемся к базе vmail:

> use vmail

Можно выполнять запросы.

После можно проверить работоспособность почтовых ящиков с помощью roundcube или другого почтового клиента.

Скрипт на PHP

Разобравшись с процессом создания записи в базе данных, создадим скрипт, который будет проверять нет ли уже такой учетной записи и сложность ее пароля. Разобьем процесс на подготовку базы данных и написание самого скрипта.

Подготовка базы данных

Для того, чтобы максимально обезопасить работу с данными, мы создадим отдельного пользователя в MariaDB / MySQL, который будет иметь доступ на чтение и запись только в таблицу mailbox.

На сервере заходим в командную оболочку SQL:

mysql -uroot -p

Создаем пользователя, от которого будет вестись работа с таблицей mailbox:

> GRANT SELECT, UPDATE, INSERT ON vmail.mailbox TO 'apiuser'@'localhost' IDENTIFIED BY '123password!';

* в данном примере мы создаем пользователя apiuser, который сможет подключиться к базе только с локального сервера (предполагается, что скрипт будет работать на сервере iRedMail). Пароль пользователя будет 123password!, а доступ ограничен только на запросы SELECT, UPDATE, INSERT и только на таблицу mailbox базы vmail.

Подробнее процесс создания пользователя в СУБД на базе MySQL описан в инструкции Создание пользователей MySQL/MariaDB и предоставление прав доступа.

После настройки привилегий, можно приступить к написанию самого скрипта.

Пример скрипта на PHP

И так, сам скрипт будет выглядеть так:

  1. <?php
  2.  
  3. function mysql_conn() {
  4.     $mi_conn = mysqli_connect('localhost', 'apiuser', '123password!', 'vmail') or die("MySQL connect error");
  5.     mysqli_query($mi_conn, "SET NAMES 'utf8'");
  6.     return $mi_conn;
  7. }
  8.  
  9. function check_mailbox($username) {
  10.     // Проверяем на наличие в базе
  11.     global $mi_conn;
  12.     $result = mysqli_query($mi_conn, "SELECT * FROM mailbox WHERE `username`='{$username}'");
  13.     $mass = mysqli_fetch_array($result);
  14.     if ($mass['username']) {
  15.         return "Почтовый ящик уже существует.";
  16.     }
  17.  
  18.     // Проверяем на правильность формата (учетная запись должна быть в виде email)
  19.     if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
  20.         return "Адрес {$username} указан не верно.";
  21.     }
  22. }
  23.  
  24. function check_password($password) {
  25.     // Проверка сложности на количество символов
  26.     global $password_min_length;
  27.     $length = mb_strlen($password, 'UTF-8');
  28.     if ($length < $password_min_length) {
  29.         return "Пароль должен быть более {$password_min_length} символов.";
  30.     }
  31.     // Проверка сложности на наличие цифр и букв
  32.     preg_match('/\d/', $password, $d_matches);
  33.     preg_match('/\w/', $password, $w_matches);
  34.     if (!$d_matches[0] || !$w_matches[0]) {
  35.         return "Пароль должен содержать буквы и цифры.";
  36.     }
  37. }
  38.  
  39. function create_mailbox($username, $password) {
  40.     // Проверка учетной записи на наличие в базе и правильность формата
  41.     $result_check_mailbox = check_mailbox($username);
  42.     if ($result_check_mailbox) {
  43.         return "Ошибка при создании учетной записи. {$result_check_mailbox}";
  44.     }
  45.  
  46.     // Проверка пароля на сложность
  47.     $result_check_password = check_password($password);
  48.     if ($result_check_password) {
  49.         return "Ошибка при создании учетной записи. {$result_check_password}";
  50.     }
  51.  
  52.     // Создаем почтовую учетную запись
  53.     global $mi_conn;
  54.     $username_arr = explode("@", $username);
  55.     $user = $username_arr[0];
  56.     $domain = $username_arr[1];
  57.     $username_3char = str_replace('.', '_', implode('/', str_split(mb_substr($user, 0, 3))));
  58.     $username_createdate = date("Y.m.d.H.i.s");
  59.     $createdate = date("Y-m-d H:i:s");
  60.     $password_hash = exec("doveadm pw -s 'ssha512' -p '{$password}'");
  61.     $username_path = "{$domain}/{$username_3char}/{$user}-{$username_createdate}/";
  62.     if (mysqli_query($mi_conn, "INSERT INTO mailbox (`username`, `password`, `language`, `maildir`, `domain`, `created`) VALUES ('{$username}', '{$password_hash}', 'ru_RU', '{$username_path}', '{$domain}', '{$createdate}')")) {
  63.         return "Учетная запись создана";
  64.     } else {
  65.         return "Ошибка sql-запроса";
  66.     }
  67. }
  68.  
  69. $username = $_POST[username];
  70. $password = $_POST[password];
  71. $password_min_length = 8;
  72.  
  73. $mi_conn = mysql_conn();
  74. $result = create_mailbox($username, $password);
  75.  
  76. echo $result;
  77.  
  78. ?>

Описание скрипта:

Строки Описание
3-7 Функция подключения к базе данных. в данном примере идет соединение от учетной записи, которую мы создали при настройке MySQL выше. В итоге, функция возвращает переменную со ссылкой подключения к базе.
9-22 Данная функция проверяет корректность добавляемого пользователя. Сначала мы проверяем, есть ли уже такой пользователь в базе, и если есть — возвращаем ошибку. После мы проверяем формат введенного email адреса.
24-37 Проверяем пароль на сложность. В первую очередь мы проверяем, что пароль более 7 символов. Во вторую — что в пароле есть и символы и цифры.
39-67 Данная функция, собственно, создает учетную запись. Сначала мы вызываем функцию проверки на наличие в базе и правильности формата введенного имени создаваемой записи, затем проверяем пароль. Если проверки не вернули ошибку, мы выполняем запрос SQL на вставку записи.
69 Задаем переменную с именем учетной записи. В качестве значения мы принимаем переменную, отправленную в виде запроса POST.
70 Задаем переменную с паролем. В качестве значения мы принимаем переменную, отправленную в виде запроса POST.
71 Указываем минимальную длину пароля, который должен задаваться учетной записи.
73 Вызываем функцию подключения к базе, результат заносим в переменную.
74 Вызываем функцию создания учетной записи. Результат ее работы заносим в переменную $result.
76 Выводим содержимое переменной $result.

API

Полученный нами скрипт нужно скопировать на веб-сервер — мы получим возможность отправлять на него запросы POST, что позволит говорить о создании примитивного API по созданию почтовых учетных записей на сервере iRedMail.

Для запуска написанного нами скрипта нужно отправить POST запрос на http-сервер. Пример скрипта на PHP, который это делает:

  1. <?php
  2.  
  3. function my_curl_uni($url, $postfields) {
  4.     $curl = curl_init();
  5.     curl_setopt($curl, CURLOPT_URL, $url);
  6.     curl_setopt($curl, CURLOPT_HEADER, false);
  7.     curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  8.     curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 20);
  9.     curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  10.     curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  11.     curl_setopt($curl, CURLOPT_POSTFIELDS, $postfields);
  12.     $return = curl_exec($curl);
  13.     curl_close($curl);
  14.     return $return;
  15. }
  16.  
  17. $url = "http://api.dmosk.ru";
  18. $postfields = array('username'=>'test@dmosk.ru', 'password'=>'test123test');
  19. $result = my_curl_uni($url, $postfields);
  20. print_r($result);
  21.  
  22. ?>

Описание скрипта:

Строки Описание
3-15 Функция отправки POST запроса с помощью CURL. В качестве аргументов она принимает http-адрес, на который нужно отправить запрос и массив данных. Возвращает функция ответ нашего скрипта.
17 Задаем переменную с адресом, на который будет отправлен запрос. В моем примере это api.dmosk.ru — от будет запускать написанный нами скрипт для создания почтового ящика.
18 Создаем массив данных — в качестве первого элемента передаем username, второго — password.
19 Вызываем нашу функцию по отправке запроса POST. Результат передаем в переменную $result.
20 Выводим на экран содержимое ответа (переменная $result).
# Почта
Дмитрий Моск — частный мастер
Был ли вам полезен этот скрипт?

Да            Нет