Meshtastic позволяет обмениваться сообщениями через LoRa mesh-сеть даже без доступа к интернету. Но можно ли связать такую сеть с обычной электронной почтой?

Несколько месяцев назад мой отец купил пару устройств на базе Meshtastic - небольших LoRa-модулей, которые позволяют отправлять текстовые сообщения через mesh-сеть без интернета.

Для базовой связи это работает отлично: устройства автоматически ретранслируют сообщения друг другу и позволяют обмениваться текстом даже там, где нет мобильной связи.

Однако быстро возникла практическая проблема: писать сообщения только внутри Meshtastic-сети неудобно. Большая часть коммуникации всё равно происходит через обычные мессенджеры и email.

Возникла идея: сделать шлюз между электронной почтой и mesh-сетью.

Задачи были следующие:

  • читать новые письма из почтового ящика и отправлять их в mesh-сеть

  • принимать сообщения из mesh-сети и отправлять их обратно по email

После нескольких экспериментов и бессонных ночей появился Python-скрипт, который выполняет эти функции.

Как выглядит система

Финальная конфигурация простая:

[Email Server] <-> [Python Gateway] <-> [Meshtastic Node 1]
                                         |
                                         | LoRa Mesh
                                         |
                     [Phone App] <-> [Meshtastic Node 2]
  • дома работает компьютер, к которому подключены интернет и нода Meshtastic (USB или Bluetooth).

  • Вторая нода находится у пользователя и подключена к телефону через официальное приложение.

  • Python-скрипт превращает компьютер в мост между интернетом и LoRa mesh-сетью.

Архитектура скрипта

Скрипт выполняет три основные задачи:

  1. Проверка почтового ящика через IMAP и чтение новых писем.

  2. Отправка писем в mesh-сеть с фрагментацией сообщений.

  3. Прием сообщений из mesh-сети и отправка их как email.

Конфигурация

Все параметры хранятся в .env файле:

  • EMAIL / PASSWORD — учетные данные почты

  • IMAP_SERVER / SMTP_SERVER - адреса сервера с вашим почтовым ящиком

  • DEST_NODE — ID ноды получателя

  • BLE_NAME — имя Bluetooth устройства

  • ALLOWED_NODE — ID ноды, которой разрешено отправлять email

Скрипт автоматически создаёт .env при первом запуске и предлагает ввести параметры.

def ensure_env():
    if os.path.exists(".env"):
        return
    ...

Подключение к ноде через Bluetooth

Meshtastic ноды можно подключать к компьютеру двумя способами:

  • через USB

  • через Bluetooth

Подключение через USB обычно не вызывает проблем, однако Bluetooth оказался немного сложнее.

Изначально я пробовал подключаться напрямую по BLE-адресу устройства. Однако быстро выяснилось, что после длительного отключения или перезапуска ноды её Bluetooth-адрес может измениться. В результате скрипт переставал находить устройство и соединение терялось.

Чтобы избежать этой проблемы, я решил использовать более устойчивый способ: пользователь указывает только имя ноды, а скрипт сам находит её текущий адрес.

Сначала выполняется сканирование устройств с помощью CLI-утилиты Meshtastic:

def find_ble_address():

    print("Scanning for BLE nodes...")

    result = subprocess.run(
        ["meshtastic", "--ble-scan"],
        capture_output=True,
        text=True,
        timeout=15
    )

Команда meshtastic --ble-scan выводит список доступных BLE-устройств и их адресов. Вот пример вывода команды:

Found: name='ABCD_ab10' address='161929F1-8E3A-5472-8422-DE14A2C51C8A'
Found: name='ABCD_ab11' address='8EC80A96-76BD-FFD8-DC37-3C6AF8CFB511'
BLE scan finished

Скрипт анализирует этот вывод и ищет ноду с нужным именем:

for line in result.stdout.splitlines():

    match = re.search(r"name='([^']+)'.*address='([^']+)'", line)

    if not match:
        continue

    name,address = match.groups()

    if name == settings["BLE_NAME"]:
        return address

После этого используется найденный адрес для подключения:

return BLEInterface(address=addr)

В результате пользователю нужно указать только имя ноды в .env:

BLE_NAME=Meshtastic_1234

А скрипт автоматически найдёт её текущий BLE-адрес при запуске.
Это делает подключение намного стабильнее, особенно если нода часто перезапускается или долго находится вне зоны соединения.

Чтение и отправка почты

IMAP-подключение:

mail = imaplib.IMAP4_SSL(settings["IMAP_SERVER"],settings["IMAP_PORT"])
mail.login(settings["EMAIL"],settings["PASSWORD"])
mail.select("INBOX")
status,data = mail.search(None,"UNSEEN")

Скрипт извлекает отправителя, тему и тело письма. Для обработки MIME используется библиотека pyzmail, которая упрощает работу с различными форматами писем.

SMTP-подключение:

server = smtplib.SMTP(settings["SMTP_SERVER"],settings["SMTP_PORT"],timeout=10)
server.ehlo()
server.starttls()

server.login(settings["EMAIL"],settings["PASSWORD"])
server.send_message(msg)

Для создания письма также используется MIME.

msg = MIMEText(body)

msg["From"] = settings["EMAIL"]
msg["To"] = to_addr
msg["Subject"] = subject

Ограничения LoRa и фрагментация сообщений

LoRa поддерживает только небольшие пакеты данных. Полное письмо может быть длиннее допустимого размера.

Решение — разбивка письма на фрагменты.

def split_message(text, size):
    msg_id = generate_msg_id()
    total = (len(text)+size-1)//size
    return [
        f"MAIL {msg_id} {i//size+1}/{total}\n{text[i:i+size]}"
        for i in range(0, len(text), size)
    ]

Каждому фрагменту присваивается случайный ID и номер пакета. Это позволяет корректно собирать сообщения на принимающей стороне.

Отправка в mesh-сеть

Фрагменты отправляются через API Meshtastic.

iface.sendText(
    packet_text,
    destinationId=settings["DEST_NODE"]
)
time.sleep(3)

Между отправками добавлена небольшая задержка для минимизации потерь в сети. Скрипт поддерживает как USB, так и Bluetooth подключение к ноде.

Вот примеры того как выглядят отправленная почта через меш
Вот примеры того как выглядят отправленная почта через меш
И вот как она выглядит в приложении Meshtastic
И вот как она выглядит в приложении Meshtastic

Отправка email из mesh-сети

Для обратной отправки email используется простой текстовый формат: EML|адрес_получателя|тема|текст_сообщения. Скрипт проверяет входящие сообщения: если сообщение начинается с EML|, оно интерпретируется как команду на отправку email. После успешной отправки письма шлюз возвращает подтверждение обратно в mesh-сеть.

def parse_mesh_email(text):
    if not text.startswith("EML|"):
        return None
    parts = text.split("|",3)
    if len(parts) < 4:
        return None
    return parts[1].strip(), parts[2].strip(), parts[3].strip()

После успешной отправки email скрипт возвращает подтверждение в mesh-сеть:

send_email(to_addr,subject,body)

confirm = f"EMAIL SENT: {to_addr}"
iface.sendText(confirm, destinationId=settings["DEST_NODE"])

Проблема с ID

Meshtastic отображает ID ноды в шестнадцатеричном формате, а API возвращает десятичный. Из-за этого проверка отправителя не работала.

sender = str(packet.get("from"))

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

allowed = str(int(settings["ALLOWED_NODE"][1:],16))

sender = str(packet.get("from"))

После этого фильтрация сообщений заработала нормально.

Обработка входящих сообщений из mesh-сети

Для приема сообщений используется механизм подписки на события библиотеки Meshtastic.

При запуске скрипт подписывается на событие получения пакета:

pub.subscribe(on_receive, "meshtastic.receive")

После этого каждый входящий пакет передается в функцию on_receive

def on_receive(packet):

Первым делом проверяется, удалось ли корректно декодировать сообщение:

if "decoded" not in packet:
    return

Далее выполняется проверка отправителя. Скрипт обрабатывает сообщения только от заранее разрешённой ноды.

sender = str(packet.get("from"))

if sender != str(int(settings["ALLOWED_NODE"][1:],16)):
    return

Это простая защита от случайных или чужих сообщений в сети.

Также добавлена защита от повторной обработки одного и того же пакета. Иногда в mesh-сети сообщение может прийти несколько раз из-за ретрансляции.

packet_id = packet.get("id")

if packet_id in recent_packets:
    return

recent_packets.add(packet_id)

Если сообщение уже обрабатывалось, оно игнорируется.

После этого из пакета извлекается текст сообщения, который затем анализируется и при необходимости интерпретируется как команда на отправку email.

Почему именно email

Возникает логичный вопрос: зачем вообще использовать email поверх LoRa-сети?

На первый взгляд это выглядит странно, ведь Meshtastic уже поддерживает обмен текстовыми сообщениями. Однако у email есть несколько практических преимуществ.

Во-первых, это универсальный и очень простой интерфейс. Практически любое устройство уже умеет отправлять письма, поэтому для взаимодействия с mesh-сетью не требуется устанавливать дополнительное программное обеспечение и покупать Meshtastic.

Во-вторых, email хорошо подходит в качестве асинхронного транспорта. Сообщения могут накапливаться в почтовом ящике и отправляться в сеть по мере появления соединения с шлюзом.

Кроме того, такой подход позволяет легко интегрировать LoRa-сеть с существующей инфраструктурой: автоматическими уведомлениями, системами мониторинга или простыми скриптами.

В результате email выступает не столько как основной способ общения, сколько как удобный мост между обычным интернетом и автономной mesh-сетью.

Итог

В результате получился простой шлюз между электронной почтой и LoRa mesh-сетью на базе Meshtastic. Весь шлюз реализован примерно в ~400 строках Python-кода, а скомпелированный файл занимает ~14MB

Скрипт позволяет:

  • получать email через Meshtastic mesh-сеть

  • отправлять email из mesh-сети

  • использовать обычную почту как транспорт поверх LoRa

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

Код проекта доступен на GitHub, также есть скомпилированный бинарник для macOS который можно запускать напрямую: https://github.com/Nnnnest/mesh-email-gateway

Комментарии (24)


  1. warhammerman2
    19.03.2026 00:14

    Здорово!

    А подскажите пожалуйста, какое приложение используется на телефоне для взаимодействия с нодой?


    1. danielstealth
      19.03.2026 00:14

      Meshtastic приложение и используется) есть в магазинах приложений и на сайте проекта, исходный код открытый.


      1. warhammerman2
        19.03.2026 00:14

        Спасибо


  1. sav13
    19.03.2026 00:14

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

    А как можно гарантировать доставку большого письма, дефрагментированного на много сообщений? Как запросить потерянные пакеты?


    1. KlugKopf Автор
      19.03.2026 00:14

      Сейчас посмотрел их документацию, по идее у них есть аргумент --ack который можно использовать в связке с --sendtext, чтобы дождаться подтверждения. Как будет время протестирую как оно будет работать


    1. FisHlaBsoMAN
      19.03.2026 00:14

      Никак, утилизировать в шреддере ноды в режиме Client с плохой антенной, которые воруют хопы


  1. Last26
    19.03.2026 00:14

    Ребята мештастик в городе очень плохо работает.. Точнее он для этого мало предназначен ввиду постоянного спама в эфир всякой телеметрией и крайне сомнительной логикой трансляции сообщений согласно которой нода с более слабым сигналом им воспринимается как наиболее удаленная и используется для ретрансляции в то время как она может быть нодой с паршивой антенной в соседней комнате .. Ну и кроме того допустимо всего 7 ретрансляций..короче в больших городских сетях это работает плохо...используйте meshcore...он гораздо лучше..


  1. Zhabrozavr
    19.03.2026 00:14

    Помню азбуку Морзе, могу передавать ключом. Сдаётся мне, буду востребованным специалистом, если так и дальше дело пойдёт. На днях зондировал почву по поводу наличия в продаже телеграфных ключей. Не умеем бороться с причинами проблем - будем иметь дело с последствиями.


    1. Strijar
      19.03.2026 00:14

      Одного ключа будет маловато. К нему надо трансивер, антенну и сеть операторов которые это все будут принимать (; А так то уже есть куча цифровых видов связи для КВ которые работают быстрей и надежней чем телеграф.


      1. Zhabrozavr
        19.03.2026 00:14

        Для того чтобы вспомнить навыки передачи кроме ключа ничего и не требуется. А преимущество передачи азбукой Морзе в помехозащищённости (при той же мощности передача на большее расстояние) и простоте.


        1. Strijar
          19.03.2026 00:14

          С передачей в телеграфе то проблем нет, вопрос в приеме. С простотой согласен, с помехозащищеностью нет. Современые цифровые виды работают при SNR -20-30дб (это сигнал в 100-1000 раз слабей шума)


  1. maximlubyanov
    19.03.2026 00:14

    Не хотите написать socks proxy, чтоб мештастик можно было использовать как транспорт для любого ip трафика?


    1. kildm_live
      19.03.2026 00:14

      Мне кажется он для этого мало подходит.


    1. KlugKopf Автор
      19.03.2026 00:14

      У мештастика лимит 200 байт на пакет, к тому же просто скорость передачи не очень высокая и если попробовать гнать весь трафик, то будут огромные задержки


    1. NutsUnderline
      19.03.2026 00:14

      ну примерно такое называется lorawan но это такие скорости которые сейчас приравнивается к 0. Поэтому излишняя прослойка. 2G GSM и то мало что тянет сейчас


  1. UA6ATG
    19.03.2026 00:14

    Так не проще это сделать через приложение дельта чат , он работает также через почту . Тем более там уже готовые библиотеки есть


  1. ibnteo
    19.03.2026 00:14

    Может стоит добавить шифрование информации? В письмах могут быть данные, которье не должны быть доступны другим участникам сети.


    1. KlugKopf Автор
      19.03.2026 00:14

      Сообщения отправляются указанному получателю и мештастик сам шифрует их публичным ключом, так что по идее их не должно быть видно другим людям. Можно встроить своё шифрование и сжатие но тогда получатель будет получать их в зашифрованном виде и перед тем как прочитать сообщение его нужно будет ещё расшифровать


  1. RealZel
    19.03.2026 00:14

    На днях как раз смотрел видео про похожее решение https://youtu.be/XTnYVh7K6xQ. Сам как владелец мешстастиков не сильно представляю как оно может работать чтобы хоть какой-то трафик пропускать через себя. Не всегда сообщения доходят напрямую, не говоря уже про прыжки.


  1. UA6ATG
    19.03.2026 00:14

    я запустил приложение на raspberry Да , но при запуске он меня спрашивает выбор порта или блютуз и вопрос , не желаем ли мы обновить конфигурацию! Но ведь мне надо запустить приложение в SYSTEMCTL!! Какая командная строка в этом случаи поддерживается ?


    1. KlugKopf Автор
      19.03.2026 00:14

      У меня это просто CLI скрипт и для работы он требует ввод пользователя, так что просто запустить его как сервис не получится, для этого нужно немного поменять структуру скрипта и как он получает начальные настройки


      1. UA6ATG
        19.03.2026 00:14

        Странно это все очень. Могу Выслать переделанный рабочий скрипт который ничего не спрашивает, а берет настройки с конфига. В этом его и смысл . Так как надо запустить процессом на raspberry pi.


  1. ndrewpj
    19.03.2026 00:14

    "Сообщения могут накапливаться в почтовом ящике и отправляться в сеть по мере появления соединения с шлюзом." часть проблем - сама архитектура Meshtastic. А у Meshcore нет этой проблемы, там накапливается и всё высылается


  1. Limping
    19.03.2026 00:14

    М-да, если ещё и разбивать одно письмо на несколько пакетов мештастика - никакой Long Fast не выдержит.

    Если речь про сеть для одного человека, которому нужно где-то с горы отправлять почту до первой ноды с интернетом, это ничего. А в городе это просто забьёт канал и будет график загрузки с конскими значениями утилизации.