Wdrażanie sygnałów dla rozwiązań lokalnych: integracja PowerMTA

Ptak

30 sie 2019

Email

1 min read

Wdrażanie sygnałów dla rozwiązań lokalnych: integracja PowerMTA

Ptak

30 sie 2019

Email

1 min read

Wdrażanie sygnałów dla rozwiązań lokalnych: integracja PowerMTA

Zanurzmy się w szczegóły konfigurowania PowerMTA dla sygnałów SparkPost.

Zagłębmy się w szczegóły konfiguracji PowerMTA dla SparkPost Signals. Będziesz potrzebować:

  • Hosta do uruchomienia najnowszej wersji PowerMTA – nowego lub istniejącej maszyny

  • Konta SparkPost z uprawnieniem klucza API do „Wydarzenia przychodzące: Zapis” jak opisano tutaj

Skonfigurujemy PowerMTA do przesyłania wydarzeń do Twojego konta SparkPost, a następnie będziesz mógł używać następujących:

Najpierw zainstaluj (lub zaktualizuj do) PowerMTA 5.0 r4 lub nowszej wersji, postępując zgodnie z zwykłymi instrukcjami instalacji v5.0, które są dość proste. Następnie przejdziemy przez następujące kroki:

  • Skonfiguruj łącznik PowerMTA do SparkPost Signals

  • Ustaw śledzenie zaangażowania z niestandardową domeną śledzącą

  • Wybierz, które strumienie ruchu PowerMTA zgłosić do Signals

  • Testowanie, czy wydarzenia docierają do Signals

  • Przeglądanie, jak używać znaczących nazw, które dobrze się prezentują w raportach.

Omówimy również inne szczegółowe aspekty konfiguracji PowerPMTA używane w naszym demo Signals:

  • Zdarzenia FBL (Skargi na spam) i zdalne (out-of-band) zwroty

  • Konfiguracja iniekcji, w tym DKIM

  • Konfiguracja FBL i OOB

  • Konfiguracja i nazewnictwo VirtualMTA (i jak to się pojawia w raportach SparkPost Signals)

Na koniec jest „dodatkowa funkcja” z kodem zapewniającym zgodność nazw kampanii z konwencjami nazewnictwa PowerMTA X-Job.

Skonfiguruj PowerMTA connector

Konfiguracja Signals jest opisana w sekcji 10.1 Przewodnika Użytkownika 5.0. Tutaj zaczniemy od „Use Case #2”, który umożliwia Signals dla całego ruchu z tego hosta PowerMTA i włącza śledzenie zaangażowania SparkPost.

# # SparkPost Signals # <signals> api-key ##my ingest API key here## upload-url https://api.sparkpost.com/api/v1/ingest/events log-verbose true min-free-space 1G engagement-tracking sparkpost # to włącza śledzenie otwarć i kliknięć w PowerMTA customer-id 123 # Twój numer konta SparkPost tutaj </signals> enable-signals true

Oto, co robi każdy atrybut:

api-key

To jest unikalne dla Twojego konta SparkPost, to wartość, którą otrzymałeś wcześniej od SparkPost.

upload-url

Musi pasować do adresu Twojej usługi API SparkPost, niezależnie od tego, czy jest to US czy EU. Po więcej informacji zobacz tutaj. Najczęściej spotykane wartości to:

SparkPost (US): https://api.sparkpost.com/api/v1/ingest/events

SparkPost EU:    https://api.eu.sparkpost.com/api/v1/ingest/events

log-verbose

Ta dyrektywa jest opcjonalna i po włączeniu daje trochę więcej informacji w pliku pmta.log, co może być przydatne podczas konfiguracji, aby potwierdzić, że wszystko działa poprawnie. Każdą minutę, nawet gdy nie ma ruchu, zobaczysz:

2019-07-26 11:47:57 Signals: Discovered 0 files

Z ruchem, zobaczysz coś takiego:

2019-07-26 11:50:57 Signals: Discovered sp1-0000000000003FBD.json 2019-07-26 11:50:57 Signals: Transferred sp1-0000000000003FBD.json successfully. 2019-07-26 11:50:57 Signals: Discovered 1 file, transferred 1 file successfully

min-free-space

To mówi PowerMTA, przy jakim progu przestrzeni dyskowej należy zacząć usuwać najstarsze pliki wydarzeń JSON SparkPost, aby zrobić miejsce na nowe pliki, gdy przestrzeń dyskowa jest na wyczerpaniu.

enable-signals

To mówi PowerMTA, aby przesyłać do Signals, w tym przypadku globalnie dla całego ruchu (więcej informacji tutaj, dla wersji 5.0). Możesz być bardziej selektywny w kwestii tego, które strumienie ruchu przesyłać, jeśli chcesz.

Możesz również oznaczyć konkretny ruch PowerMTA do zgłaszania jako należący do subkonta SparkPost – to kolejny sposób na odróżnienie jednego strumienia ruchu od drugiego.

engagement-tracking, customer-id
Rozwiązanie PowerMTA w zakresie śledzenia zaangażowania domyślnie używa domeny do śledzenia dla usługi SparkPost hostowanej w USA. Należy określić swój numeryczny identyfikator klienta SparkPost; oto instrukcje, jak go znaleźć.

tracking-domain

Dla kont w SparkPost EU dodaj następującą linię:

tracking-domain pmta.eu.spgo.io # to jest punkt końcowy dla SparkPost EU

Custom Tracking domain

Jeśli wolisz używać własnej domeny do śledzenia (to jest lepsze z punktu widzenia dostarczalności), wykonaj następujące czynności:

  • Utwórz domenę śledzącą u swojego dostawcy DNS, tworząc rekord CNAME. To zazwyczaj będzie subdomena Twojej głównej domeny, np. track.mycompany.com .

track.mycompany.com CNAME pmta.spgo.io # jeśli masz konto SparkPost US track.mycompany.com CNAME pmta.eu.spgo.io # jeśli masz konto SparkPost EU

Możesz także używać domen śledzących HTTPS, chociaż jest to bardziej skomplikowane (zobacz kroki konfiguracyjne SparkPost dla domen śledzących HTTPS).

  • Zarejestruj domenę śledzącą na swoim koncie SparkPost i zweryfikuj ją. Poczekaj kilka minut przed próbą, aby umożliwić propagację zmian DNS przez Internet, w zależności od Twojego dostawcy DNS.

  • Skonfiguruj PowerMTA do użycia tej domeny zamiast domyślnej, używając

tracking-domain yourdomain.com # Umieść tutaj swoją własną domenę

Możesz sprawdzić, czy dostarczone e-maile mają dodane „piksele otwarcia” i linki opakowane, patrząc na wewnętrzne elementy poczty (w Gmailu użyj menu w prawym górnym rogu i wybierz „Pokaż oryginał”).

Show original option highlighted


Zauważysz piksele otwarcia na początku i końcu HTML w e-mailu. Każdy link HTML jest również zmieniony, aby mieć REF  wskazujący na domenę śledzącą.

HTML code highlighted


To wszystko, czego potrzebujesz, aby uruchomić SparkPost Signals z wbudowanym Śledzeniem Zaangażowania PowerMTA.

Zapobieganie śledzeniu określonych linków w twoim e-mailu html

Możesz zapobiec śledzeniu określonych linków przez PowerMTA, ustawiając niestandardowy atrybut data-msys-clicktrack  na „0”  :

<a href="#" data-msys-clicktrack="0">Przykład</a>

PowerMTA nie będzie opakowywać linku. Usunie także ten atrybut przed przesłaniem wiadomości do odbiorcy.

Wybierz, które strumienie ruchu PowerMTA raportować do Signals

Możesz wybrać, które Sygnały mają być aktywne:

  • Globalnie (tego użyliśmy w powyższym przykładzie)

  • For some Virtual MTAs and not others

  • For some Virtual MTA pools and not others

  • Dla konkretnych adresów "Sender" lub "From" przekazywanych przez PowerMTA, w połączeniu z wyborem Virtual MTA / Virtual MTA pool

Ta konfiguracja jest bardzo potężna i jest zilustrowana za pomocą serii przykładów użycia (v5.0) w Przewodniku użytkownika.

Możesz wybrać, które Sygnały mają być aktywne:

  • Globalnie (tego użyliśmy w powyższym przykładzie)

  • For some Virtual MTAs and not others

  • For some Virtual MTA pools and not others

  • Dla konkretnych adresów "Sender" lub "From" przekazywanych przez PowerMTA, w połączeniu z wyborem Virtual MTA / Virtual MTA pool

Ta konfiguracja jest bardzo potężna i jest zilustrowana za pomocą serii przykładów użycia (v5.0) w Przewodniku użytkownika.

Możesz wybrać, które Sygnały mają być aktywne:

  • Globalnie (tego użyliśmy w powyższym przykładzie)

  • For some Virtual MTAs and not others

  • For some Virtual MTA pools and not others

  • Dla konkretnych adresów "Sender" lub "From" przekazywanych przez PowerMTA, w połączeniu z wyborem Virtual MTA / Virtual MTA pool

Ta konfiguracja jest bardzo potężna i jest zilustrowana za pomocą serii przykładów użycia (v5.0) w Przewodniku użytkownika.

Testowanie, czy Twoje wydarzenia docierają do Signals

Oto widok SparkPost Signals, połączony z PowerMTA. Możesz zauważyć, że wynik zdrowia się zmienia.

Health score dashboard


Nazwy Kampanii są dostępne jako elementy raportowania, wraz z Subkonto, Pula IP, Dostawca Skrzynki Pocztowej i Domeną Wysyłającą.

Oprócz przeglądania logów PowerMTA, możesz sprawdzić, czy dane o zdarzeniach docierają do SparkPost, patrząc na ekran Integracji Sygnalizacji.

Signals integration screen

Na ekranie Wyszukiwania Zdarzeń SparkPost, powinieneś zobaczyć zdarzenia pojawiające się w ciągu kilku minut. Obejmą one Zdarzenia Wstrzyknięcia i Dostawy, jak również Odbicia i potencjalnie Zdarzenia Odbicia Poza Pasmem i Skargi Na Spam, jeśli już skonfigurowałeś PowerMTA, aby je obsługiwać.
Jeśli masz włączone Śledzenie Zaangażowania, zobaczysz również otwarcie, initial_open i kliknięcie zdarzenia.

Używanie znaczących nazw, które dobrze wyglądają w raportowaniu

Tworzenie nazw puli PowerMTA VirtualMTA i nazw zadań tak, aby były znaczące i czytelne dla człowieka, jest warte zachodu. Pojawiają się bezpośrednio w twoich aspektach SparkPost Signals i raporcie podsumowującym.

Jak wspomniano wcześniej, nie musisz tworzyć tych pul w swoim koncie SparkPost. SparkPost pobiera je z twojej konfiguracji PowerMTA.

Oto jak terminy konfiguracji PowerMTA tłumaczą się na terminy SparkPost.

Termin PowerMTA Termin raportów/ sygnałów SparkPostDomena odbiorcy
(część domeny w polu „rcpt” w pliku księgowym).Domena odbiorcyCzęść domeny w nagłówku „Nadawca” lub „From” w wiadomości przekazanej przez PowerMTA.
(część domeny „orig” w pliku księgowym).Domena nadawcyVirtualMTA (nazwa) —VillageMTA Pool (nazwa)
(„vmtaPool” w pliku księgowym)Pula IP (nazwa)smtp-source-host a.b.c.d
(„dlvSourceIp” w pliku księgowym)Adres IP nadawcya.b.c.dJob (nazwa)
(„jobId” w pliku księgowym)ID kampanii (nazwa) — Szablon (nazwa)„Subkonto” nie jest natywną koncepcją PowerMTA.

Jednakże PowerMTA może oznaczać virtualMTAs, pool’e Virtual MTA lub domeny nadawcy-lub-From za pomocą ID subkonta do raportowania SparkPost.

ID subkonta (numer wydarzenia FBL)Skarga na spam (wydarzenie)Zdalne odbicie (wydarzenie)Poza pasmem odbicie (wydarzenie)

Utworzenie co najmniej jednego adresu smtp-source-host umożliwia również prawidłowe zidentyfikowanie adresu IP nadawcy przez SparkPost, aby wyświetlił się on w wydarzeniach Injection i Delivery, a także w widoku raportu podsumowującego.

Nazwy zadań są ustalane w PowerMTA poprzez nagłówek w wstrzykniętej wiadomości. Oprócz umożliwienia indywidualnej kontroli zadań (wstrzymaj/wznów itp.), co samo w sobie jest przydatne, PowerMTA przekazuje nazwy do raportowania SparkPost Signals jako „ID kampanii”. Zobacz Przewodnik użytkownika w wersji 5.0 sekcja 12.8 „Śledzenie kampanii w PowerMTA za pomocą JobID”.

Istnieje kilka rzeczy, na które należy zwrócić uwagę odnośnie nazewnictwa zadań. Podczas gdy SparkPost (z formatem JSON i unikaniem JSON) pozwala na znaki takie jak <SPACE> w nazwach kampanii, nagłówki poczty są bardziej restrykcyjne. Dozwolone znaki w nagłówku X-Job to:

A-Za-z0-9!#$%&'()*+,-./:;<=>?@[\]^_{|}~ 

Innymi słowy, niedozwolone znaki to między innymi <SPACE>, cudzysłowy „ i odwrotny apostrof `. Jeśli jesteś przyzwyczajony do pracy z nazwami X-Job, to nie będzie to zaskakujące i nazwy twoich ID kampanii będą „po prostu działać” w raportowaniu SparkPost. Jeśli jak ja, najpierw nauczyłeś się SparkPost, możesz chcieć narzędzia, które zapewni bezpieczeństwo twoim wartościom X-Job; zobacz dodatkową funkcję na końcu tego artykułu.

FBL zdarzenia (Spam Complaints) i zdalne (out-of-band) bounces

PowerMTA może odbierać i przetwarzać wydarzenia FBL (znane w SparkPost jako wydarzenia zgłoszenia spamu) oraz zdalne odbicia (znane w SparkPost jako odbicia poza pasmem, ponieważ odpowiedź wraca jakiś czas później, a nie podczas rozmowy SMTP).

W Port25 Support Forum znajdują się artykuły na temat konfigurowania Bounce Processor i FBL Processor. Jeśli jesteś istniejącym użytkownikiem PowerMTA, prawdopodobnie już je masz.

Oto konfiguracja, którą zrobiłem na potrzeby demonstracji, na podstawie tych artykułów i zorientowana na hosting PowerMTA w Amazon EC2.

Jeśli znasz konfigurację PowerMTA w tym obszarze, możesz pominąć tę część, aż do następnej poziomej linii.

Konfiguracja Injection

Będziemy używać portu 587 do wiadomości wstrzykniętych, które będą przychodzić przez publiczny Internet z innego hosta. Musimy powstrzymać złych aktorów przed odkryciem i nadużywaniem tej usługi, więc stosujemy uwierzytelnianie za pomocą nazwy użytkownika/hasła oraz opcjonalnie TLS, podobnie jak w punktach wstrzyknięcia SMTP SparkPost.

Chcemy być w stanie wysyłać wiadomości z właściwie uwierzytelnionych źródeł do dowolnego miejsca przeznaczenia. Chcemy również osobnego serwera nasłuchującego na porcie 25 dla FBL i zdalnych odpowiedzi zwrotnych, które nie wymagają uwierzytelnienia.

# # Adres(y) IP i port(y), na których nasłuchujemy przychodzących połączeń SMTP # smtp-listener 0.0.0.0:587 smtp-listener 0.0.0.0:25

W poniższych deklaracjach <source> używamy uwierzytelniania za pomocą nazwy użytkownika/hasła oraz opcjonalnie TLS w celu obrony przed nieautoryzowanym wstrzykiwaniem wiadomości. Ustawiamy również limity szybkości połączeń dla nieudanych prób hasła.

Twoje ustawienie może być inne; na przykład, jeśli masz prywatną sieć między wtryskiwaczem a PowerMTA, nie będziesz potrzebować uwierzytelniania hasłem.

# Jeden reguła źródłowa dla całego wstrzykiwania, wewnętrznego lub zewnętrznego. Wymuszaj uwierzytelnianie, z wyjątkiem odbić i FBL # <source 0/0> log-connections false log-commands false # WARNING: verbose! tylko dla dev log-data false # WARNING: jeszcze bardziej szczegółowe! smtp-service true # pozwalaj na usługę SMTP smtp-max-auth-failure-rate 1/min allow-unencrypted-plain-auth false allow-starttls true rewrite-list mfrom </source> <source {auth}> always-allow-relaying yes # tylko jeśli uwierzytelnianie się powiodło default-virtual-mta default process-x-job true </source>

Deklaracja <source {auth}> (zobacz tutaj. v5.0) ma zastosowanie po pomyślnym uwierzytelnieniu. Tutaj pozwala na dalsze przekazywanie, ustawia domyślną grupę wirtualnych MTA do użycia oraz dodaje nagłówek X-Job (który będzie zgłaszany przez SparkPost Signals jako campaign_id).

Lista rewrite-map przekształca wstrzyknięte wiadomości, aby używały określonej domeny MAIL FROM (aka domena zwrotna lub Return-Path:).

# # Zmienie adres MAIL FROM, aby odpowiadał domenie zwrotnej # <rewrite-list mfrom> mail-from *@pmta.signalsdemo.trymsys.net *@bounces.pmta.signalsdemo.trymsys.net </rewrite-list>

Następnie ustawiamy naszą konfigurację TLS oraz nazwę użytkownika / hasło SMTP, zgodnie z aktualnymi zaleceniami.

# # Zabezpiecz usługę przychodzącą nazwą użytkownika, hasłem i TLS. SMT 2020-06-15 # smtp-server-tls-certificate /etc/pmta/pmtasignalsdemo.pem smtp-server-tls-allow-tlsv1 false smtp-server-tls-allow-tlsv1.1 false smtp-server-tls-allow-tlsv1.2 true smtp-server-tls-allow-tlsv1.3 true # # Użytkownicy SMTP (uwierzytelnieni za pomocą SMTP AUTH) # <smtp-user SMTP_Injection> password ##PUT YOUR PASSWORD HERE## authentication-method password </smtp-user>

Możemy sprawdzić, że (niepewne, przestarzałe) TLS v1.0 nie jest akceptowane za pomocą mojego ulubionego narzędzia testowego SMTP, swaks.

swaks --server pmta.signalsdemo.trymsys.net --port 587 --to test@trymsys.net --from any@sparkpost.com --tls --tls-protocol tlsv1

Widzimy:

*** Rozruch TLS nie powiódł się (connect(): error:00000000:lib(0):func(0):reason(0)) *** STARTTLS próbował, ale nie powiódł się

Podobnie dla  –tls-protocol tlsv1_1.

Zastosujmy również podpis DKIM na naszych wychodzących wiadomościach, ponieważ to dobre praktyki (postępowałem zgodnie z tymi instrukcjami aby ustawić klucz).

# # DKIM # domena-klucz mypmta, pmta.signalsdemo.trymsys.net, /etc/pmta/mypmta.pmta.signalsdemo.trymsys.net.pem

Konfiguracja FBL i OOB

Teraz .. w końcu .. deklarujemy, które konkretne domeny są otwarte na zdalne odpowiedzi bounce i FBL. Nie chcemy ich przekazywać nigdzie (aby zapobiec atakom typu backscatter), po prostu wewnętrznie przetwarzamy te odpowiedzi.

# # Włącz przetwarzanie Bounce i FBL dla konkretnych domen # relay-domain pmta.signalsdemo.trymsys.net relay-domain bounces.pmta.signalsdemo.trymsys.net relay-domain fbl.pmta.signalsdemo.trymsys.net <bounce-processor> deliver-unmatched-email no deliver-matched-email no <address-list> domain pmta.signalsdemo.trymsys.net domain bounces.pmta.signalsdemo.trymsys.net </address-list> </bounce-processor> <feedback-loop-processor> deliver-unmatched-email no deliver-matched-email no <address-list> domain fbl.pmta.signalsdemo.trymsys.net </address-list> </feedback-loop-processor>

Możesz zobaczyć, że skonfigurowałem dwie domeny bounce, ponieważ bawiłem się używaniem/nieużywaniem reguły przepisywania mfrom.

Domena FBL jest zazwyczaj rejestrowana w zewnętrznych usługach, takich jak Microsoft SNDS; zobacz ten artykuł po więcej informacji. W tym demo, FBL będą pochodzić z Bouncy Sink, więc nie ma potrzeby rejestracji.

Testowanie nasłuchiwacza SMTP

Ważne jest, aby przetestować, czy Twój nasłuchiwacz SMTP wymaga autoryzacji dla jakichkolwiek ogólnych miejsc docelowych, odrzucając wszelkie wiadomości, które nie są specjalnie zaadresowane do domen FBL i remote-bounce.

swaks --server pmta.signalsdemo.trymsys.net --port 25 --to test@strange.pmta.signalsdemo.trymsys.net --from any@sparkpost.com

Odpowiedź, zgodnie z oczekiwaniami, pokazuje, że przesyłanie dalej jest zabronione:

550 5.7.1 przesyłanie dalej zabronione dla odbiorcy w "RCPT TO:<test@strange.pmta.signalsdemo.trymsys.net>

(Koniec opisu konfiguracji demo).

Konfiguracja i nazewnictwo VirtualMTA

PowerMTA VirtualMTAs (i pule VirtualMTA) to potężne funkcje zarządzania strumieniami wiadomości, a raporty PowerMTA / SparkPost Signals najlepiej działają, gdy te funkcje są aktywne.

# # Przekieruj cały wychodzący ruch przez tę wirtualną mta / pulę. # Zadeklaruj tutaj adres IP dostawy, aby sygnały SparkPost przechwytywały wydarzenia "inject" (aka "reception") z odpowiednim atrybutem sending_IP # <virtual-mta mta1>     smtp-source-host 172.31.25.101 pmta.signalsdemo.trymsys.net </virtual-mta> <virtual-mta-pool default>     virtual-mta mta1     <domain *>         max-smtp-out    20       # max. połączenia *na domenę*         bounce-after    4d12h    # 4 dni, 12 godzin         retry-after     10m      # 10 minut         dkim-sign       tak     </domain> </virtual-mta-pool>

Ustawienie virtual-mta-pool jest raportowane w SparkPost jako „IP Pool” i jest dostępne jako aspekt raportowania w SparkPost Signals (menu rozwijane pod wykresami).

Health score dashboard


Raport Podsumowujący również pokazuje IP Pool jako aspekt raportowania „Group By”.

Summary report dashboard


Jak wspomniano wcześniej w tym artykule, skonfigurowanie co najmniej jednego adresu smtp-source-host również umożliwia SparkPostowi poprawną identyfikację adresu IP nadawcy, aby wyświetlił się w wydarzeniach Injection i Delivery oraz w Raporcie Podsumowującym:

Summary report with the group by filter set to "Sending IP"

To wszystko, czego potrzebujesz, aby rozpocząć podstawową integrację między PowerMTA a SparkPost Signals. Znajdziesz kompletny przykład pliku konfiguracyjnego tutaj.

Zanim wyjdziesz, oto obiecana dodatkowa funkcja.

Funkcja bonusowa: X-Job name checking/filtering

Aby zapewnić, że dowolny ciąg znaków jest bezpieczny do użycia jako nazwa X-Job w PowerMTA, oto prosta funkcja Python do zamiany niebezpiecznych znaków na podkreślenie „_”

import re def pmtaSafeJobID(s):    """    :param s: str    :return: str    Przekształć dowolny identyfikator kampanii na dozwolone znaki dla nagłówka PMTA X-Job.    Zobacz https://download.port25.com/files/UsersGuide-5.0.html#tracking-a-campaign-in-powermta-with-a-jobid    Konkretne zabronienia <sp> " ` ale pozwól na większość innych znaków.    """    # Zauważ, że trzeba uciekać ' - [ ] i podwójnie uciekać \ - zobacz https://docs.python.org/3/library/re.html    disallowedChars = '[^A-Za-z0-9!#$%&\'()*+,\-./:;<=>?@\[\\\\\]^_{|}~]'    return re.sub(disallowedChars, '_', s)

To wykorzystuje regularne wyrażenia Pythona w specyficzny sposób. Deklaruje zbiór zabronionych znaków używając operatora „dopełnienie zbioru” ^, zamiast wymieniać wszystkie dozwolone znaki. To oznacza, że przechwytujemy (i zabezpieczamy) znaki poza zwykłym zestawem 7-bitowym. Możemy to pokazać za pomocą tego fragmentu testowego:

s='' for i in range(32, 256): s += chr(i) print(pmtaSafeJobID(s))

Daje

_!_#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^__abcdefghijkl mnopqrstuvwxyz{|}~___________________________________________________________ ______________________________________________________________________

Możesz zobaczyć, że <SPACE>, podwójne cudzysłowy „, i backtick `, jak również wszystkie znaki poza ~ są zamieniane na podkreślenie.

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

Kompletna, AI-native platforma, która skaluje się wraz z Twoim business.

Produkt

Rozwiązania

Zasoby

Company

Ustawienia prywatności

Już wkrótce

Social

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.

Zarejestruj się

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

Kompletna, AI-native platforma, która skaluje się wraz z Twoim business.

Produkt

Rozwiązania

Zasoby

Company

Ustawienia prywatności

Social

Biuletyn

Bądź na bieżąco z Bird dzięki cotygodniowym aktualizacjom do Twojej skrzynki odbiorczej.

Zarejestruj się