Podczas instalacji:
- generujesz unikalny identyfikator instalacji i zapisujesz lokalnie.
- wywołujesz API zabezpieczone (np. użytkownik + hasło) przesyłając ten identyfikator.
- serwer dopisuje (jeżeli może) instalację do konta użytkownika, oraz jeżeli wszystko OK, zwraca token JWT, z długą datą ważności (typu rok), zapisujesz sobie i używasz w dalszej części sekwencji jako refresh token
- wywołujesz endpoint sprawdzający ważność licencji na danym urządzeniu, przedstawiając się tokenem JWT (pozyskanym wyżej)
- serwer zwraca krótkotrwały token JWT, dalej nazwany JWT-licencja. Token zawiera warunki licencji (np. z jakiego adresu można wysyłać maile, czy coś tam) + datę ważności licencji na lokalnym komputerze (np. 7 dni)
- zapisujesz sobie lokalnie i sprawdzasz przy każdym uruchomieniu jakie są warunki licencji i czy data nie została przekroczona, jeśli tak, to kasujesz.
Potencjalne zagrożenia:
- Przeniesienie pliku z pobranym tokenem na inny komputer pozwala na obejście limitu, więc warto zadbać, żeby były tam dane istotne dla użytkownika (żeby nie chciał się nimi dzielić)
- Alternatywnie/dodatkowo można w identyfikatorze urządzenia umieścić np. mac adres. Opcją ultimate jest wygenerowanie i zapisanie kluczy asymetrycznych za pomocą TPM (dla użytkownika teoretycznie nie do wyciągnięcia) i użycie tego jako sekretu urządzenia.
Oczywiście pozostaje kwestia zabezpieczenia samej aplikacji przed dekompilacją / deassemblacją (nie wiem jakiego języka używasz). Z tym nie poradził sobie skutecznie chyba nikt, więc popularną metodą jest przeniesienie kluczowych funkcji aplikacji na serwer. Czyli w twoim przypadku miałbyś tego grubego klienta u użytkownika, aplikacja przesyła treść i adresatów maili na serwer, a serwer (twój) zajmuje się wysłaniem tego dalej.
Czyli tak jak napisał @UglyMan tylko trochę bardziej rozpisane.