S/MIME Część 2: Podpisane, Zabezpieczone i Dostarczone przez SparkPost

Ptak

31 gru 2018

Email

1 min read

S/MIME Część 2: Podpisane, Zabezpieczone i Dostarczone przez SparkPost

Najważniejsze informacje

    • Założenie: Część 2 przechodzi od teorii S/MIME do praktyki — demonstrując jak podpisywać i szyfrować e-maile wykorzystując SparkPost jako platformę dostarczania.

    • Cel: Wyposażenie programistów w lekkie, oparte na linii poleceń workflow do podpisywania wychodzących wiadomości, weryfikacji podpisów oraz (opcjonalnie) szyfrowania treści dla określonych odbiorców.

    • Najważniejsze punkty:

      1. Installacja: Zainstaluj narzędzia demo źródłowego z GitHub (z automatycznymi testami Travis + pytest). Pipfile obsługuje wszystkie zależności Pythona.

      2. Klucze nadawcy:

        • Utwórz samosigned lub wydany przez CA certyfikat (.p12) dla swojej tożsamości e-mail.

        • Podziel go na pliki prywatne (.pem) i publiczne (.crt) do użycia przez narzędzie podpisujące.

      3. Podpisywanie:

        • Użyj załączonego skryptu sparkpostSMIME.py do podpisywania wiadomości testowych (np. tests/declaration.eml).

        • Potwierdź podpisy wizualnie w klientach takich jak Thunderbird (ikonka czerwonego kropka).

      4. Szyfrowanie:

        • Uzyskaj publiczny certyfikat każdego odbiorcy (.crt).

        • Uruchom narzędzie ponownie, aby wygenerować podpisaną + zaszyfrowaną wiadomość.

        • Odbiorcy mogą weryfikować i deszyfrować używając swoich kluczy prywatnych.

      5. Dostawa przez SparkPost:

        • Skonfiguruj ważną domenę nadawczą i klucz API.

        • Wysyłaj wiadomości przez API SparkPost z wyłączonym śledzeniem, aby zachować integralność.

      6. Użyteczność bonusowa – mimeshow:

        • Wyświetla czytelną dla człowieka strukturę komunikatów MIME RFC822 do debugowania lub inspekcji.

      7. Praktyczne wskazówki:

        • Utrzymuj nazwy plików zgodne z adresem From:.

        • Unikaj modyfikacji treści wiadomości po podpisaniu.

        • Używaj Bcc tylko do kopii archiwalnych — ci odbiorcy nie mogą deszyfrować, jeśli wiadomość jest zaszyfrowana do jednego adresu To.

Podsumowanie pytań i odpowiedzi

  • Dlaczego używać podpisywania S/MIME?

    Uwierzytelnia nadawcę i zapewnia integralność wiadomości — klienci tacy jak Thunderbird pokazują wizualny wskaźnik, gdy podpis jest ważny.

  • Jak mogę uzyskać mój certyfikat nadawcy?

    Możesz samodzielnie podpisać certyfikat za pomocą OpenSSL (do testów) lub uzyskać zaufany certyfikat od dostawców, takich jak Comodo (bezpłatny do użytku niekomercyjnego).

  • Czy mogę zaszyfrować wiadomości dla wielu odbiorców?

    Tylko jeśli masz każdy klucz publiczny odbiorcy. Skrypt demo domyślnie szyfruje do pojedynczego adresu To.

  • Jakie zabezpieczenia chronią podpisy przed zniszczeniem w transporcie?

    Narzędzie ustawia opcje API SparkPost dla wysyłania transakcyjnego i wyłącza śledzenie otwarć/kliknięć, dzięki czemu ładunek przechodzi bez zmian.

  • Jaką rolę pełni mimeshow?

    Parses surowe pliki e-mail i drukuje ich wieloczęściową strukturę — przydatne do inspekcji podpisów S/MIME, załączników i nagłówków.

  • Co dalej w serii?

    Część 3 rozszerza te możliwości S/MIME na lokalne platformy zabezpieczonego e-maila, takie jak PowerMTA i Momentum.

W części 1 mieliśmy szybki przegląd S/MIME, przyglądając się podpisywaniu i szyfrowaniu naszych strumieni wiadomości w różnych klientach pocztowych. Wiadomości S/MIME mogą być podpisane (co daje dowód tożsamości nadawcy), szyfrowane (utrzymując treść wiadomości w tajemnicy) lub obu.

Diagram illustrating email security layers showing the relationship between S/MIME signing, S/MIME encryption, and TLS connections in the email delivery process from message source through email server to recipient.

W tej części zrobimy:

  • Zainstalujemy kilka prostych narzędzi wiersza poleceń do podpisywania i szyfrowania wiadomości e-mail

  • Otrzymamy klucz/ certyfikat nadawcy do podpisywania

  • Wyślemy podpisaną wiadomość przez SparkPost i przyjrzymy się otrzymanej wiadomości

  • Opcjonalnie, otrzymamy certyfikat odbiorcy do szyfrowania

  • Wyślemy podpisaną i zaszyfrowaną wiadomość przez SparkPost i przyjrzymy się otrzymanej wiadomości

  • Przetestujemy przydatne samodzielne narzędzie „mimeshow” do przeglądania wewnętrznej zawartości plików e-mail.

OK – zaczynajmy!

Diagram illustrating email security layers showing the relationship between S/MIME signing, S/MIME encryption, and TLS connections in the email delivery process from message source through email server to recipient.

W tej części zrobimy:

  • Zainstalujemy kilka prostych narzędzi wiersza poleceń do podpisywania i szyfrowania wiadomości e-mail

  • Otrzymamy klucz/ certyfikat nadawcy do podpisywania

  • Wyślemy podpisaną wiadomość przez SparkPost i przyjrzymy się otrzymanej wiadomości

  • Opcjonalnie, otrzymamy certyfikat odbiorcy do szyfrowania

  • Wyślemy podpisaną i zaszyfrowaną wiadomość przez SparkPost i przyjrzymy się otrzymanej wiadomości

  • Przetestujemy przydatne samodzielne narzędzie „mimeshow” do przeglądania wewnętrznej zawartości plików e-mail.

OK – zaczynajmy!

Diagram illustrating email security layers showing the relationship between S/MIME signing, S/MIME encryption, and TLS connections in the email delivery process from message source through email server to recipient.

W tej części zrobimy:

  • Zainstalujemy kilka prostych narzędzi wiersza poleceń do podpisywania i szyfrowania wiadomości e-mail

  • Otrzymamy klucz/ certyfikat nadawcy do podpisywania

  • Wyślemy podpisaną wiadomość przez SparkPost i przyjrzymy się otrzymanej wiadomości

  • Opcjonalnie, otrzymamy certyfikat odbiorcy do szyfrowania

  • Wyślemy podpisaną i zaszyfrowaną wiadomość przez SparkPost i przyjrzymy się otrzymanej wiadomości

  • Przetestujemy przydatne samodzielne narzędzie „mimeshow” do przeglądania wewnętrznej zawartości plików e-mail.

OK – zaczynajmy!

Funkcja bonusowa: wyświetlanie części MIME za pomocą „mimeshow”

Wewnętrzne szczegóły plików MIME w formacie RFC822 są dosyć skomplikowane do odczytania przez ludzi. Projekt zawiera samodzielne narzędzie, które to ułatwia, nazywane mimeshow.

To narzędzie przyjmuje dowolne pliki e-mail, które posiadasz (nie tylko te w formacie S/MIME) i pokazuje wewnętrzną strukturę. Oto przykład:

./mimeshow.py testcases/img_and_attachment.eml

Zobaczysz:

To Bob <bob.lumreeker@gmail.com>
From Steve <steve@thetucks.com> 
Subject Testing attachments etc 
MIME-Version 1.0
Content-Type multipart/mixed; boundary="------------7D48652042860D0098C65210"
Content-Language en-GB
Content-Type multipart/alternative; boundary="------------58C0BF87598336550D70EB95" 
Content-Type text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding 7bit
Content-Transfer-Encoding quoted-printable 
Content-Type text/html; charset="utf-8"
Content-Type application/pdf; name="sparkpost-datasheet-tam-technical-account-management.pdf" 
Content-Transfer-Encoding base64
Content-Disposition attachment; filename="sparkpost-datasheet-tam-technical-account-management.pdf"

Możesz również użyć go jako filtru, aby uzyskać zrozumiałe podsumowanie wyników sparkpostSMIME :

./sparkpostSMIME.py tests/declaration.eml --sign --encrypt | ./mimeshow.py


Zobaczysz:

To Bob <bob.lumreeker@gmail.com>  
From Steve <steve@thetucks.com>
Subject Here is our declaration 
Content-Language en-GB
MIME-Version 1.0
Content-Type application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m
Content-Transfer-Encoding base64
Content-Disposition attachment; filename=smime.p7m

Wewnętrzne szczegóły plików MIME w formacie RFC822 są dosyć skomplikowane do odczytania przez ludzi. Projekt zawiera samodzielne narzędzie, które to ułatwia, nazywane mimeshow.

To narzędzie przyjmuje dowolne pliki e-mail, które posiadasz (nie tylko te w formacie S/MIME) i pokazuje wewnętrzną strukturę. Oto przykład:

./mimeshow.py testcases/img_and_attachment.eml

Zobaczysz:

To Bob <bob.lumreeker@gmail.com>
From Steve <steve@thetucks.com> 
Subject Testing attachments etc 
MIME-Version 1.0
Content-Type multipart/mixed; boundary="------------7D48652042860D0098C65210"
Content-Language en-GB
Content-Type multipart/alternative; boundary="------------58C0BF87598336550D70EB95" 
Content-Type text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding 7bit
Content-Transfer-Encoding quoted-printable 
Content-Type text/html; charset="utf-8"
Content-Type application/pdf; name="sparkpost-datasheet-tam-technical-account-management.pdf" 
Content-Transfer-Encoding base64
Content-Disposition attachment; filename="sparkpost-datasheet-tam-technical-account-management.pdf"

Możesz również użyć go jako filtru, aby uzyskać zrozumiałe podsumowanie wyników sparkpostSMIME :

./sparkpostSMIME.py tests/declaration.eml --sign --encrypt | ./mimeshow.py


Zobaczysz:

To Bob <bob.lumreeker@gmail.com>  
From Steve <steve@thetucks.com>
Subject Here is our declaration 
Content-Language en-GB
MIME-Version 1.0
Content-Type application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m
Content-Transfer-Encoding base64
Content-Disposition attachment; filename=smime.p7m

Wewnętrzne szczegóły plików MIME w formacie RFC822 są dosyć skomplikowane do odczytania przez ludzi. Projekt zawiera samodzielne narzędzie, które to ułatwia, nazywane mimeshow.

To narzędzie przyjmuje dowolne pliki e-mail, które posiadasz (nie tylko te w formacie S/MIME) i pokazuje wewnętrzną strukturę. Oto przykład:

./mimeshow.py testcases/img_and_attachment.eml

Zobaczysz:

To Bob <bob.lumreeker@gmail.com>
From Steve <steve@thetucks.com> 
Subject Testing attachments etc 
MIME-Version 1.0
Content-Type multipart/mixed; boundary="------------7D48652042860D0098C65210"
Content-Language en-GB
Content-Type multipart/alternative; boundary="------------58C0BF87598336550D70EB95" 
Content-Type text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding 7bit
Content-Transfer-Encoding quoted-printable 
Content-Type text/html; charset="utf-8"
Content-Type application/pdf; name="sparkpost-datasheet-tam-technical-account-management.pdf" 
Content-Transfer-Encoding base64
Content-Disposition attachment; filename="sparkpost-datasheet-tam-technical-account-management.pdf"

Możesz również użyć go jako filtru, aby uzyskać zrozumiałe podsumowanie wyników sparkpostSMIME :

./sparkpostSMIME.py tests/declaration.eml --sign --encrypt | ./mimeshow.py


Zobaczysz:

To Bob <bob.lumreeker@gmail.com>  
From Steve <steve@thetucks.com>
Subject Here is our declaration 
Content-Language en-GB
MIME-Version 1.0
Content-Type application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m
Content-Transfer-Encoding base64
Content-Disposition attachment; filename=smime.p7m

1. Zainstaluj narzędzia

Narzędzia demonstracyjne są dostępne na GitHubie, z pełnymi instrukcjami instalacji. Możesz zauważyć logo „build passing” – Travis i pytest automatycznie sprawdzają status budowy. Zauważ, że te narzędzia nie są oficjalnie wspierane przez SparkPost, ale starałem się, aby były niezawodne i łatwe w użyciu.

Jeśli masz pewne doświadczenie z Pythonem i pip, instalacja powinna być Ci znajoma. Plik Pipfile automatycznie zajmuje się zewnętrznymi zależnościami. Gdy już to skończysz, możesz sprawdzić, czy wszystko jest zainstalowane, uruchamiając

./sparkpostSMIME.py -h

Powinieneś zobaczyć przyjazny tekst pomocy. Następnie musimy…

Narzędzia demonstracyjne są dostępne na GitHubie, z pełnymi instrukcjami instalacji. Możesz zauważyć logo „build passing” – Travis i pytest automatycznie sprawdzają status budowy. Zauważ, że te narzędzia nie są oficjalnie wspierane przez SparkPost, ale starałem się, aby były niezawodne i łatwe w użyciu.

Jeśli masz pewne doświadczenie z Pythonem i pip, instalacja powinna być Ci znajoma. Plik Pipfile automatycznie zajmuje się zewnętrznymi zależnościami. Gdy już to skończysz, możesz sprawdzić, czy wszystko jest zainstalowane, uruchamiając

./sparkpostSMIME.py -h

Powinieneś zobaczyć przyjazny tekst pomocy. Następnie musimy…

Narzędzia demonstracyjne są dostępne na GitHubie, z pełnymi instrukcjami instalacji. Możesz zauważyć logo „build passing” – Travis i pytest automatycznie sprawdzają status budowy. Zauważ, że te narzędzia nie są oficjalnie wspierane przez SparkPost, ale starałem się, aby były niezawodne i łatwe w użyciu.

Jeśli masz pewne doświadczenie z Pythonem i pip, instalacja powinna być Ci znajoma. Plik Pipfile automatycznie zajmuje się zewnętrznymi zależnościami. Gdy już to skończysz, możesz sprawdzić, czy wszystko jest zainstalowane, uruchamiając

./sparkpostSMIME.py -h

Powinieneś zobaczyć przyjazny tekst pomocy. Następnie musimy…

2. Uzyskaj swój klucz / certyfikat nadawcy do podpisywania

Jeśli masz już plik klucza dla swojej tożsamości nadawcy, możesz przejść dalej. W przeciwnym razie oto dwie opcje do wyboru:

a) Samopodpisany klucz / certyfikat testowy (nie ważny zewnętrznie)

Jeśli tylko testujesz, możesz stworzyć certyfikaty i klucze „samopodpisane” dla adresu e-mail, korzystając z narzędzia wiersza poleceń openssl w systemie Linux,  postępując zgodnie z taką procedurą jak ta. Na końcu tego procesu będziesz miał plik smime.p12 . Zmień nazwę tego pliku, aby odpowiadała twojej tożsamości nadawcy, w tym znak @, na przykład, alice@example.com.p12 .

lub

b) Ważne zewnętrznie klucze / certyfikaty

Jeśli chcesz uzyskać ważne zewnętrznie klucze / certyfikaty, które umożliwiają ci podpisywanie, jest lista dostawców tutaj. Znalazłem, że Comodo działa dobrze (darmowe do użytku niekomercyjnego), i to jest łatwiejsze niż procedura samopodpisania powyżej. Postępuj zgodnie z procesem rejestracji, otrzymaj swój e-mail walidacyjny i otwórz link w Firefoxie. Przejdź do Preferencji Firefox / Prywatność i bezpieczeństwo. Przewiń do Certyfikaty / Wyświetl certyfikaty:

Firefox browser settings page showing certificate management options under the Privacy & Security section, with controls for how the browser handles personal certificate requests.


Wybierz swój certyfikat i użyj opcji „Zapisz kopię zapasową”, aby zapisać jako plik w formacie PKCS12 (dodaj rozszerzenie pliku .p12 do swojej nazwy pliku), który zawiera klucz prywatny i łańcuch publicznych certyfikatów.

Certificate Manager window showing a list of software security device certificates from COMODO CA Limited, with details including certificate names and serial numbers


Podaj hasło, aby zabezpieczyć plik .p12:

Certificate backup password entry dialog with password fields and strength meter


Generuj osobne pliki kluczy publicznych (.crt) i prywatnych (.pem)

Niezależnie od tego, czy użyłeś a) czy b), będziesz teraz miał plik .p12 dla swojej tożsamości nadawcy. To ogromny krok do przodu – napij się teraz kawy!

Teraz musimy wygenerować osobne pliki kluczy publicznych i prywatnych w ten sposób – zastępując swoim własnym adresem e-mail przykład. (Mac OSX i Linux):

openssl pkcs12 -in alice\@example.com.p12 -clcerts -nokeys -out alice\@example.com.crt openssl pkcs12 -in alice\@example.com.p12 -nocerts -nodes -out alice\@example.com.pem

Będziesz musiał wprowadzić hasło, które podałeś wcześniej. Zauważ, że te odwrotne ukośniki \ są używane do eskapowania znaku @ – nie oddzielając nazw ścieżki katalogu (to ukośnik prosty / w Mac OSX i Linux).

Jeśli używasz systemu Windows, dostępne są implementacje openssl, takie jak MINGW64, wbudowany w narzędzia wiersza poleceń Git, ale odkryłem, że często się zawiesza. Znajdziesz to prawdopodobnie łatwiejsze i szybsze do wykonania w Linuxie, a następnie skopiować swoje pliki. Te same narzędzia Git dla Windows mają ładnego klienta ssh, którego możesz używać do logowania się do systemu Linux, takiego jak instancja Amazon EC2.


2.1 Podpisywanie wiadomości

W katalogu testów dla alice@example.com znajduje się już przykładowy klucz/certyfikat i plik źródłowy e-mail, więc możesz uzyskać jakieś wyjście, nawet zanim będziesz miał swoje własne klucze. Po prostu wpisz następujące:

cd tests ../sparkpostSMIME.py example_email1.eml --sign

A otrzymasz:

To: Bob <bob@example.com> 
From: Alice <alice@example.com> 
Subject: A message MIME-Version: 1.0 
Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m" 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment; filename="smime.p7m" MIIKXAYJKoZIhvcNAQcCoIIKTTCCCkkCAQExDzANBglghkgBZQMEAgEFADCCAQoGCSqGSIb3DQEH AaCB/ASB+VRvOiBCb2IgPGJvYkBleGFtcGxlLmNvbT4NCkZyb206IEFsaWNlIDxhbGljZUBleGFt : :

Nie możesz faktycznie wysyłać e-maili z example.com za pomocą SparkPost, chyba że posiadasz tę domenę, więc następnym krokiem jest użycie własnego klucza i wysłanie podpisanej wiadomości z własnej domeny.

Jeśli masz już plik klucza dla swojej tożsamości nadawcy, możesz przejść dalej. W przeciwnym razie oto dwie opcje do wyboru:

a) Samopodpisany klucz / certyfikat testowy (nie ważny zewnętrznie)

Jeśli tylko testujesz, możesz stworzyć certyfikaty i klucze „samopodpisane” dla adresu e-mail, korzystając z narzędzia wiersza poleceń openssl w systemie Linux,  postępując zgodnie z taką procedurą jak ta. Na końcu tego procesu będziesz miał plik smime.p12 . Zmień nazwę tego pliku, aby odpowiadała twojej tożsamości nadawcy, w tym znak @, na przykład, alice@example.com.p12 .

lub

b) Ważne zewnętrznie klucze / certyfikaty

Jeśli chcesz uzyskać ważne zewnętrznie klucze / certyfikaty, które umożliwiają ci podpisywanie, jest lista dostawców tutaj. Znalazłem, że Comodo działa dobrze (darmowe do użytku niekomercyjnego), i to jest łatwiejsze niż procedura samopodpisania powyżej. Postępuj zgodnie z procesem rejestracji, otrzymaj swój e-mail walidacyjny i otwórz link w Firefoxie. Przejdź do Preferencji Firefox / Prywatność i bezpieczeństwo. Przewiń do Certyfikaty / Wyświetl certyfikaty:

Firefox browser settings page showing certificate management options under the Privacy & Security section, with controls for how the browser handles personal certificate requests.


Wybierz swój certyfikat i użyj opcji „Zapisz kopię zapasową”, aby zapisać jako plik w formacie PKCS12 (dodaj rozszerzenie pliku .p12 do swojej nazwy pliku), który zawiera klucz prywatny i łańcuch publicznych certyfikatów.

Certificate Manager window showing a list of software security device certificates from COMODO CA Limited, with details including certificate names and serial numbers


Podaj hasło, aby zabezpieczyć plik .p12:

Certificate backup password entry dialog with password fields and strength meter


Generuj osobne pliki kluczy publicznych (.crt) i prywatnych (.pem)

Niezależnie od tego, czy użyłeś a) czy b), będziesz teraz miał plik .p12 dla swojej tożsamości nadawcy. To ogromny krok do przodu – napij się teraz kawy!

Teraz musimy wygenerować osobne pliki kluczy publicznych i prywatnych w ten sposób – zastępując swoim własnym adresem e-mail przykład. (Mac OSX i Linux):

openssl pkcs12 -in alice\@example.com.p12 -clcerts -nokeys -out alice\@example.com.crt openssl pkcs12 -in alice\@example.com.p12 -nocerts -nodes -out alice\@example.com.pem

Będziesz musiał wprowadzić hasło, które podałeś wcześniej. Zauważ, że te odwrotne ukośniki \ są używane do eskapowania znaku @ – nie oddzielając nazw ścieżki katalogu (to ukośnik prosty / w Mac OSX i Linux).

Jeśli używasz systemu Windows, dostępne są implementacje openssl, takie jak MINGW64, wbudowany w narzędzia wiersza poleceń Git, ale odkryłem, że często się zawiesza. Znajdziesz to prawdopodobnie łatwiejsze i szybsze do wykonania w Linuxie, a następnie skopiować swoje pliki. Te same narzędzia Git dla Windows mają ładnego klienta ssh, którego możesz używać do logowania się do systemu Linux, takiego jak instancja Amazon EC2.


2.1 Podpisywanie wiadomości

W katalogu testów dla alice@example.com znajduje się już przykładowy klucz/certyfikat i plik źródłowy e-mail, więc możesz uzyskać jakieś wyjście, nawet zanim będziesz miał swoje własne klucze. Po prostu wpisz następujące:

cd tests ../sparkpostSMIME.py example_email1.eml --sign

A otrzymasz:

To: Bob <bob@example.com> 
From: Alice <alice@example.com> 
Subject: A message MIME-Version: 1.0 
Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m" 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment; filename="smime.p7m" MIIKXAYJKoZIhvcNAQcCoIIKTTCCCkkCAQExDzANBglghkgBZQMEAgEFADCCAQoGCSqGSIb3DQEH AaCB/ASB+VRvOiBCb2IgPGJvYkBleGFtcGxlLmNvbT4NCkZyb206IEFsaWNlIDxhbGljZUBleGFt : :

Nie możesz faktycznie wysyłać e-maili z example.com za pomocą SparkPost, chyba że posiadasz tę domenę, więc następnym krokiem jest użycie własnego klucza i wysłanie podpisanej wiadomości z własnej domeny.

Jeśli masz już plik klucza dla swojej tożsamości nadawcy, możesz przejść dalej. W przeciwnym razie oto dwie opcje do wyboru:

a) Samopodpisany klucz / certyfikat testowy (nie ważny zewnętrznie)

Jeśli tylko testujesz, możesz stworzyć certyfikaty i klucze „samopodpisane” dla adresu e-mail, korzystając z narzędzia wiersza poleceń openssl w systemie Linux,  postępując zgodnie z taką procedurą jak ta. Na końcu tego procesu będziesz miał plik smime.p12 . Zmień nazwę tego pliku, aby odpowiadała twojej tożsamości nadawcy, w tym znak @, na przykład, alice@example.com.p12 .

lub

b) Ważne zewnętrznie klucze / certyfikaty

Jeśli chcesz uzyskać ważne zewnętrznie klucze / certyfikaty, które umożliwiają ci podpisywanie, jest lista dostawców tutaj. Znalazłem, że Comodo działa dobrze (darmowe do użytku niekomercyjnego), i to jest łatwiejsze niż procedura samopodpisania powyżej. Postępuj zgodnie z procesem rejestracji, otrzymaj swój e-mail walidacyjny i otwórz link w Firefoxie. Przejdź do Preferencji Firefox / Prywatność i bezpieczeństwo. Przewiń do Certyfikaty / Wyświetl certyfikaty:

Firefox browser settings page showing certificate management options under the Privacy & Security section, with controls for how the browser handles personal certificate requests.


Wybierz swój certyfikat i użyj opcji „Zapisz kopię zapasową”, aby zapisać jako plik w formacie PKCS12 (dodaj rozszerzenie pliku .p12 do swojej nazwy pliku), który zawiera klucz prywatny i łańcuch publicznych certyfikatów.

Certificate Manager window showing a list of software security device certificates from COMODO CA Limited, with details including certificate names and serial numbers


Podaj hasło, aby zabezpieczyć plik .p12:

Certificate backup password entry dialog with password fields and strength meter


Generuj osobne pliki kluczy publicznych (.crt) i prywatnych (.pem)

Niezależnie od tego, czy użyłeś a) czy b), będziesz teraz miał plik .p12 dla swojej tożsamości nadawcy. To ogromny krok do przodu – napij się teraz kawy!

Teraz musimy wygenerować osobne pliki kluczy publicznych i prywatnych w ten sposób – zastępując swoim własnym adresem e-mail przykład. (Mac OSX i Linux):

openssl pkcs12 -in alice\@example.com.p12 -clcerts -nokeys -out alice\@example.com.crt openssl pkcs12 -in alice\@example.com.p12 -nocerts -nodes -out alice\@example.com.pem

Będziesz musiał wprowadzić hasło, które podałeś wcześniej. Zauważ, że te odwrotne ukośniki \ są używane do eskapowania znaku @ – nie oddzielając nazw ścieżki katalogu (to ukośnik prosty / w Mac OSX i Linux).

Jeśli używasz systemu Windows, dostępne są implementacje openssl, takie jak MINGW64, wbudowany w narzędzia wiersza poleceń Git, ale odkryłem, że często się zawiesza. Znajdziesz to prawdopodobnie łatwiejsze i szybsze do wykonania w Linuxie, a następnie skopiować swoje pliki. Te same narzędzia Git dla Windows mają ładnego klienta ssh, którego możesz używać do logowania się do systemu Linux, takiego jak instancja Amazon EC2.


2.1 Podpisywanie wiadomości

W katalogu testów dla alice@example.com znajduje się już przykładowy klucz/certyfikat i plik źródłowy e-mail, więc możesz uzyskać jakieś wyjście, nawet zanim będziesz miał swoje własne klucze. Po prostu wpisz następujące:

cd tests ../sparkpostSMIME.py example_email1.eml --sign

A otrzymasz:

To: Bob <bob@example.com> 
From: Alice <alice@example.com> 
Subject: A message MIME-Version: 1.0 
Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m" 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment; filename="smime.p7m" MIIKXAYJKoZIhvcNAQcCoIIKTTCCCkkCAQExDzANBglghkgBZQMEAgEFADCCAQoGCSqGSIb3DQEH AaCB/ASB+VRvOiBCb2IgPGJvYkBleGFtcGxlLmNvbT4NCkZyb206IEFsaWNlIDxhbGljZUBleGFt : :

Nie możesz faktycznie wysyłać e-maili z example.com za pomocą SparkPost, chyba że posiadasz tę domenę, więc następnym krokiem jest użycie własnego klucza i wysłanie podpisanej wiadomości z własnej domeny.

3. Wyślij podpisaną wiadomość za pomocą SparkPost

Teraz użyjemy prawdziwej domeny nadawcy, skonfigurowanej zgodnie z Przewodnikiem dla nowych użytkowników SparkPost. Mamy certyfikat nadawcy i pliki kluczy w bieżącym katalogu:

steve@thetucks.com.crt steve@thetucks.com.pem

Plik tests/declaration.eml jest dołączony do projektu. To tylko plik tekstowy, więc możesz dostosować adres From: do swojej własnej domeny nadawcy oraz adres To: do swojego testowego odbiorcy. Początek pliku wygląda tak:

Do: Bob <bob.lumreeker@gmail.com> Od: Steve <steve@thetucks.com> Temat: Oto nasza deklaracja MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-Language: en-GB Kiedy w trakcie wydarzeń ludzkich staje się konieczne …

Ustaw swój klucz API:

export SPARKPOST_API_KEY=<<Put your API key here>

Wyślij e-mail:

./sparkpostSMIME.py tests/declaration.eml --sign --send_api

Zobaczysz:

Otwarte połączenie do https://api.sparkpost.com/api/v1 Wysyłanie tests/declaration.eml Od: Steve <steve@thetucks.com> Do: Bob  <bob.lumreeker@gmail.com> OK - w 1.15 sekund

Po około sekundzie, e-mail dociera do skrzynki odbiorczej Boba. Thunderbird wyświetla go z czerwonym punktem na kopercie, co wskazuje na ważny podpis nadawcy.

Thunderbird email inbox showing an email with a subject 'Here is our declaration'

Sukces! Dokończ tę kawę, zasłużyłeś na nią. Jeśli masz problemy, sprawdź, czy twój adres From: w pliku e-mail odpowiada nazwie twoich plików .crt i .pem.

Teraz użyjemy prawdziwej domeny nadawcy, skonfigurowanej zgodnie z Przewodnikiem dla nowych użytkowników SparkPost. Mamy certyfikat nadawcy i pliki kluczy w bieżącym katalogu:

steve@thetucks.com.crt steve@thetucks.com.pem

Plik tests/declaration.eml jest dołączony do projektu. To tylko plik tekstowy, więc możesz dostosować adres From: do swojej własnej domeny nadawcy oraz adres To: do swojego testowego odbiorcy. Początek pliku wygląda tak:

Do: Bob <bob.lumreeker@gmail.com> Od: Steve <steve@thetucks.com> Temat: Oto nasza deklaracja MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-Language: en-GB Kiedy w trakcie wydarzeń ludzkich staje się konieczne …

Ustaw swój klucz API:

export SPARKPOST_API_KEY=<<Put your API key here>

Wyślij e-mail:

./sparkpostSMIME.py tests/declaration.eml --sign --send_api

Zobaczysz:

Otwarte połączenie do https://api.sparkpost.com/api/v1 Wysyłanie tests/declaration.eml Od: Steve <steve@thetucks.com> Do: Bob  <bob.lumreeker@gmail.com> OK - w 1.15 sekund

Po około sekundzie, e-mail dociera do skrzynki odbiorczej Boba. Thunderbird wyświetla go z czerwonym punktem na kopercie, co wskazuje na ważny podpis nadawcy.

Thunderbird email inbox showing an email with a subject 'Here is our declaration'

Sukces! Dokończ tę kawę, zasłużyłeś na nią. Jeśli masz problemy, sprawdź, czy twój adres From: w pliku e-mail odpowiada nazwie twoich plików .crt i .pem.

Teraz użyjemy prawdziwej domeny nadawcy, skonfigurowanej zgodnie z Przewodnikiem dla nowych użytkowników SparkPost. Mamy certyfikat nadawcy i pliki kluczy w bieżącym katalogu:

steve@thetucks.com.crt steve@thetucks.com.pem

Plik tests/declaration.eml jest dołączony do projektu. To tylko plik tekstowy, więc możesz dostosować adres From: do swojej własnej domeny nadawcy oraz adres To: do swojego testowego odbiorcy. Początek pliku wygląda tak:

Do: Bob <bob.lumreeker@gmail.com> Od: Steve <steve@thetucks.com> Temat: Oto nasza deklaracja MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-Language: en-GB Kiedy w trakcie wydarzeń ludzkich staje się konieczne …

Ustaw swój klucz API:

export SPARKPOST_API_KEY=<<Put your API key here>

Wyślij e-mail:

./sparkpostSMIME.py tests/declaration.eml --sign --send_api

Zobaczysz:

Otwarte połączenie do https://api.sparkpost.com/api/v1 Wysyłanie tests/declaration.eml Od: Steve <steve@thetucks.com> Do: Bob  <bob.lumreeker@gmail.com> OK - w 1.15 sekund

Po około sekundzie, e-mail dociera do skrzynki odbiorczej Boba. Thunderbird wyświetla go z czerwonym punktem na kopercie, co wskazuje na ważny podpis nadawcy.

Thunderbird email inbox showing an email with a subject 'Here is our declaration'

Sukces! Dokończ tę kawę, zasłużyłeś na nią. Jeśli masz problemy, sprawdź, czy twój adres From: w pliku e-mail odpowiada nazwie twoich plików .crt i .pem.

4. Szyfrowanie wiadomości

Aby zaszyfrować wiadomość, potrzebujesz publicznego klucza odbiorcy w formie certyfikatu. Jest to plik tekstowy, który wygląda mniej więcej tak:

Atrybuty torby   friendlyName: s COMODO CA Limited ID #2   localKeyID: 32 84 AB 9C 56 5C 80 C6 89 4D 40 46 DD D4 7C 71 E8 CD ED C1 subject=/emailAddress=bob.lumreeker@gmail.com issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Client Authentication and Secure Email CA -----BEGIN CERTIFICATE----- wygląda jak losowe znaki tutaj -----END CERTIFICATE-----

Istnieje przykładowy certyfikat odbiorcy dla bob@example.com w katalogu testów, więc możesz ćwiczyć z nim przed posiadaniem prawdziwego certyfikatu:

cd tests ../sparkpostSMIME.py example_email1.eml --sign --encrypt

Zobaczysz:

To: Bob <bob@example.com>
From: Alice <alice@example.com> 
Subject: A message MIME-Version: 1.0 
Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment; filename=smime.p7m MIIRwQYJKoZIhvcNAQcDoIIRsjCCEa4CAQAxggKlMIICoQIBADCBijCBhDELMAkG :

Zauważysz, że długość wyniku jest znacznie dłuższa niż w przypadku zaszyfrowanej wiadomości, ponieważ zawiera wiele dodatkowych informacji oraz samej zaszyfrowanej wiadomości.


4.1 Wysyłanie zaszyfrowanej, podpisanej wiadomości przez SparkPost

Wyślijmy zaszyfrowaną wiadomość na prawdziwy adres e-mail. Możesz postępować w ten sam sposób jak wcześniej (samopodpisany lub dostawca taki jak Comodo), aby uzyskać publiczny klucz / certyfikat dla własnych adresów odbiorców. Potrzebujesz tylko pliku .crt – odbiorca nigdy nie musi przekazywać ci swojego klucza prywatnego (pliki .p12 i .pem).

Posiadam plik bob.lumreeker@gmail.com.crt dla mojego zamierzonego odbiorcy – odpowiadający adresowi From: w moim pliku.

Oto polecenie, aby wysłać:

./sparkpostSMIME.py tests/declaration.eml --sign --encrypt --send_api

Widzę:

Otwarta połączenie na https://api.sparkpost.com/api/v1 Wysyłanie tests/declaration.eml From: Steve <steve@thetucks.com> Do: Bob <bob.lumreeker@gmail.com> OK - w 1.168 sekund

Poczta wyświetla się w Thunderbirdzie z ikoną „czerwonego kropka” podpisu i ikoną „kłódki” szyfrowanej.

Thunderbird email view with signature and encryption icons

Możesz wysyłać złożone e-maile oparte na HTML z linkami i obrazkami równie łatwo, jak w przypadku tego, który pokazano w Części 1. Niektóre programy klienckie, takie jak Thunderbird, proszą o pozwolenie na wyświetlanie zewnętrznych linków i obrazów w szyfrowanych wiadomościach S/MIME, ale wiadomości tylko podpisane dobrze wyświetlają się w klientach w tym Thunderbird i Gmail:

Avocado marketing email with guacamole in a blue bowl and product order sectionsGmail interface showing an HTML email with guacamole image and Avocado marketing content

Zauważ, że rozwijana lista pokazuje „Zweryfikowany adres e-mail”.

Aby zaszyfrować wiadomość, potrzebujesz publicznego klucza odbiorcy w formie certyfikatu. Jest to plik tekstowy, który wygląda mniej więcej tak:

Atrybuty torby   friendlyName: s COMODO CA Limited ID #2   localKeyID: 32 84 AB 9C 56 5C 80 C6 89 4D 40 46 DD D4 7C 71 E8 CD ED C1 subject=/emailAddress=bob.lumreeker@gmail.com issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Client Authentication and Secure Email CA -----BEGIN CERTIFICATE----- wygląda jak losowe znaki tutaj -----END CERTIFICATE-----

Istnieje przykładowy certyfikat odbiorcy dla bob@example.com w katalogu testów, więc możesz ćwiczyć z nim przed posiadaniem prawdziwego certyfikatu:

cd tests ../sparkpostSMIME.py example_email1.eml --sign --encrypt

Zobaczysz:

To: Bob <bob@example.com>
From: Alice <alice@example.com> 
Subject: A message MIME-Version: 1.0 
Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment; filename=smime.p7m MIIRwQYJKoZIhvcNAQcDoIIRsjCCEa4CAQAxggKlMIICoQIBADCBijCBhDELMAkG :

Zauważysz, że długość wyniku jest znacznie dłuższa niż w przypadku zaszyfrowanej wiadomości, ponieważ zawiera wiele dodatkowych informacji oraz samej zaszyfrowanej wiadomości.


4.1 Wysyłanie zaszyfrowanej, podpisanej wiadomości przez SparkPost

Wyślijmy zaszyfrowaną wiadomość na prawdziwy adres e-mail. Możesz postępować w ten sam sposób jak wcześniej (samopodpisany lub dostawca taki jak Comodo), aby uzyskać publiczny klucz / certyfikat dla własnych adresów odbiorców. Potrzebujesz tylko pliku .crt – odbiorca nigdy nie musi przekazywać ci swojego klucza prywatnego (pliki .p12 i .pem).

Posiadam plik bob.lumreeker@gmail.com.crt dla mojego zamierzonego odbiorcy – odpowiadający adresowi From: w moim pliku.

Oto polecenie, aby wysłać:

./sparkpostSMIME.py tests/declaration.eml --sign --encrypt --send_api

Widzę:

Otwarta połączenie na https://api.sparkpost.com/api/v1 Wysyłanie tests/declaration.eml From: Steve <steve@thetucks.com> Do: Bob <bob.lumreeker@gmail.com> OK - w 1.168 sekund

Poczta wyświetla się w Thunderbirdzie z ikoną „czerwonego kropka” podpisu i ikoną „kłódki” szyfrowanej.

Thunderbird email view with signature and encryption icons

Możesz wysyłać złożone e-maile oparte na HTML z linkami i obrazkami równie łatwo, jak w przypadku tego, który pokazano w Części 1. Niektóre programy klienckie, takie jak Thunderbird, proszą o pozwolenie na wyświetlanie zewnętrznych linków i obrazów w szyfrowanych wiadomościach S/MIME, ale wiadomości tylko podpisane dobrze wyświetlają się w klientach w tym Thunderbird i Gmail:

Avocado marketing email with guacamole in a blue bowl and product order sectionsGmail interface showing an HTML email with guacamole image and Avocado marketing content

Zauważ, że rozwijana lista pokazuje „Zweryfikowany adres e-mail”.

Aby zaszyfrować wiadomość, potrzebujesz publicznego klucza odbiorcy w formie certyfikatu. Jest to plik tekstowy, który wygląda mniej więcej tak:

Atrybuty torby   friendlyName: s COMODO CA Limited ID #2   localKeyID: 32 84 AB 9C 56 5C 80 C6 89 4D 40 46 DD D4 7C 71 E8 CD ED C1 subject=/emailAddress=bob.lumreeker@gmail.com issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO RSA Client Authentication and Secure Email CA -----BEGIN CERTIFICATE----- wygląda jak losowe znaki tutaj -----END CERTIFICATE-----

Istnieje przykładowy certyfikat odbiorcy dla bob@example.com w katalogu testów, więc możesz ćwiczyć z nim przed posiadaniem prawdziwego certyfikatu:

cd tests ../sparkpostSMIME.py example_email1.eml --sign --encrypt

Zobaczysz:

To: Bob <bob@example.com>
From: Alice <alice@example.com> 
Subject: A message MIME-Version: 1.0 
Content-Type: application/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m 
Content-Transfer-Encoding: base64 
Content-Disposition: attachment; filename=smime.p7m MIIRwQYJKoZIhvcNAQcDoIIRsjCCEa4CAQAxggKlMIICoQIBADCBijCBhDELMAkG :

Zauważysz, że długość wyniku jest znacznie dłuższa niż w przypadku zaszyfrowanej wiadomości, ponieważ zawiera wiele dodatkowych informacji oraz samej zaszyfrowanej wiadomości.


4.1 Wysyłanie zaszyfrowanej, podpisanej wiadomości przez SparkPost

Wyślijmy zaszyfrowaną wiadomość na prawdziwy adres e-mail. Możesz postępować w ten sam sposób jak wcześniej (samopodpisany lub dostawca taki jak Comodo), aby uzyskać publiczny klucz / certyfikat dla własnych adresów odbiorców. Potrzebujesz tylko pliku .crt – odbiorca nigdy nie musi przekazywać ci swojego klucza prywatnego (pliki .p12 i .pem).

Posiadam plik bob.lumreeker@gmail.com.crt dla mojego zamierzonego odbiorcy – odpowiadający adresowi From: w moim pliku.

Oto polecenie, aby wysłać:

./sparkpostSMIME.py tests/declaration.eml --sign --encrypt --send_api

Widzę:

Otwarta połączenie na https://api.sparkpost.com/api/v1 Wysyłanie tests/declaration.eml From: Steve <steve@thetucks.com> Do: Bob <bob.lumreeker@gmail.com> OK - w 1.168 sekund

Poczta wyświetla się w Thunderbirdzie z ikoną „czerwonego kropka” podpisu i ikoną „kłódki” szyfrowanej.

Thunderbird email view with signature and encryption icons

Możesz wysyłać złożone e-maile oparte na HTML z linkami i obrazkami równie łatwo, jak w przypadku tego, który pokazano w Części 1. Niektóre programy klienckie, takie jak Thunderbird, proszą o pozwolenie na wyświetlanie zewnętrznych linków i obrazów w szyfrowanych wiadomościach S/MIME, ale wiadomości tylko podpisane dobrze wyświetlają się w klientach w tym Thunderbird i Gmail:

Avocado marketing email with guacamole in a blue bowl and product order sectionsGmail interface showing an HTML email with guacamole image and Avocado marketing content

Zauważ, że rozwijana lista pokazuje „Zweryfikowany adres e-mail”.

Dalsze myśli i rzeczy, o których warto pamiętać

To narzędzie stosuje bardzo prostą metodę pobierania niezbędnych kluczy – po prostu szuka nazwanych plików w bieżącym katalogu. Bardziej złożone układy, takie jak przechowywanie wszystkich kluczy w bazie danych, mogłyby być łatwo dodane, ale chciałem, aby kod był jak najprostszy.

Możesz dodać innych odbiorców za pomocą Cc: i Bcc: i będą oni dostarczani; może to być przydatne do celów archiwalnych. Podpisane wiadomości są odbierane i mogą być wyświetlane przez innych odbiorców w komplecie z podpisem. Narzędzie usuwa nagłówek Bcc: z dostarczonej wiadomości (tak jak zrobiłby to klient pocztowy na komputerze).

Aby zapewnić, że wiadomości przechodzą przez SparkPost niezmienione (co mogłoby zepsuć podpisywanie), narzędzie ustawia opcje API dla „transakcyjnego” wysyłania, z wyłączonym śledzeniem otwarć i kliknięć.

Jeśli używasz szyfrowania, pamiętaj, że narzędzie pobiera pojedynczy adres To: na to. Inni odbiorcy mogą dekodować treść wiadomości tylko wtedy, gdy mają prywatny klucz odbiorcy To:. Jeśli używasz dodatkowych odbiorców jako zapisu dokonanych dostaw, na przykład, może to być w porządku.

To narzędzie stosuje bardzo prostą metodę pobierania niezbędnych kluczy – po prostu szuka nazwanych plików w bieżącym katalogu. Bardziej złożone układy, takie jak przechowywanie wszystkich kluczy w bazie danych, mogłyby być łatwo dodane, ale chciałem, aby kod był jak najprostszy.

Możesz dodać innych odbiorców za pomocą Cc: i Bcc: i będą oni dostarczani; może to być przydatne do celów archiwalnych. Podpisane wiadomości są odbierane i mogą być wyświetlane przez innych odbiorców w komplecie z podpisem. Narzędzie usuwa nagłówek Bcc: z dostarczonej wiadomości (tak jak zrobiłby to klient pocztowy na komputerze).

Aby zapewnić, że wiadomości przechodzą przez SparkPost niezmienione (co mogłoby zepsuć podpisywanie), narzędzie ustawia opcje API dla „transakcyjnego” wysyłania, z wyłączonym śledzeniem otwarć i kliknięć.

Jeśli używasz szyfrowania, pamiętaj, że narzędzie pobiera pojedynczy adres To: na to. Inni odbiorcy mogą dekodować treść wiadomości tylko wtedy, gdy mają prywatny klucz odbiorcy To:. Jeśli używasz dodatkowych odbiorców jako zapisu dokonanych dostaw, na przykład, może to być w porządku.

To narzędzie stosuje bardzo prostą metodę pobierania niezbędnych kluczy – po prostu szuka nazwanych plików w bieżącym katalogu. Bardziej złożone układy, takie jak przechowywanie wszystkich kluczy w bazie danych, mogłyby być łatwo dodane, ale chciałem, aby kod był jak najprostszy.

Możesz dodać innych odbiorców za pomocą Cc: i Bcc: i będą oni dostarczani; może to być przydatne do celów archiwalnych. Podpisane wiadomości są odbierane i mogą być wyświetlane przez innych odbiorców w komplecie z podpisem. Narzędzie usuwa nagłówek Bcc: z dostarczonej wiadomości (tak jak zrobiłby to klient pocztowy na komputerze).

Aby zapewnić, że wiadomości przechodzą przez SparkPost niezmienione (co mogłoby zepsuć podpisywanie), narzędzie ustawia opcje API dla „transakcyjnego” wysyłania, z wyłączonym śledzeniem otwarć i kliknięć.

Jeśli używasz szyfrowania, pamiętaj, że narzędzie pobiera pojedynczy adres To: na to. Inni odbiorcy mogą dekodować treść wiadomości tylko wtedy, gdy mają prywatny klucz odbiorcy To:. Jeśli używasz dodatkowych odbiorców jako zapisu dokonanych dostaw, na przykład, może to być w porządku.

Podpisane, zapieczętowane, dostarczone…jestem Twój

Oto nasze szybkie podsumowanie, jak podpisywać, pieczętować i dostarczać wiadomości S/MIME za pomocą SparkPost. Szybkie przypomnienie: projekt demo jest dostępny na GitHub, a starałem się, aby jego instalacja i użycie były łatwe.

Oto nasze szybkie podsumowanie, jak podpisywać, pieczętować i dostarczać wiadomości S/MIME za pomocą SparkPost. Szybkie przypomnienie: projekt demo jest dostępny na GitHub, a starałem się, aby jego instalacja i użycie były łatwe.

Oto nasze szybkie podsumowanie, jak podpisywać, pieczętować i dostarczać wiadomości S/MIME za pomocą SparkPost. Szybkie przypomnienie: projekt demo jest dostępny na GitHub, a starałem się, aby jego instalacja i użycie były łatwe.

Inne wiadomości

Przeczytaj więcej z tej kategorii

A person is standing at a desk while typing on a laptop.

Kompletna platforma oparta na sztucznej inteligencji, która rośnie wraz z Twoim biznesem.

A person is standing at a desk while typing on a laptop.

Kompletna platforma oparta na sztucznej inteligencji, która rośnie wraz z Twoim biznesem.