diff --git a/backend/src/main/java/pl/polskalokalnie/auth/AccountEmailService.java b/backend/src/main/java/pl/polskalokalnie/auth/AccountEmailService.java new file mode 100644 index 0000000..708d43d --- /dev/null +++ b/backend/src/main/java/pl/polskalokalnie/auth/AccountEmailService.java @@ -0,0 +1,113 @@ +package pl.polskalokalnie.auth; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import pl.polskalokalnie.mailconfig.MailConfigService; +import pl.polskalokalnie.mailconfig.SmtpConfig; +import pl.polskalokalnie.send.EmailSender; +import pl.polskalokalnie.send.SendResult; + +/** + * Wysylka transakcyjnych wiadomosci e-mail (aktywacja konta, reset hasla) w firmowym szablonie HTML + * (logo + nazwa u gory, tresc, przycisk CTA). Korzysta z konfiguracji SMTP z panelu admina. + * + * Gdy SMTP nie jest skonfigurowany/wlaczony - link jest logowany (tryb deweloperski), aby proces + * dalo sie przetestowac bez realnej skrzynki. Po skonfigurowaniu SMTP wiadomosci ida realnie. + */ +@Service +public class AccountEmailService { + + private static final Logger log = LoggerFactory.getLogger(AccountEmailService.class); + + private final EmailSender emailSender; + private final MailConfigService mailConfigService; + private final String baseUrl; + + public AccountEmailService(EmailSender emailSender, + MailConfigService mailConfigService, + @Value("${app.public-base-url:http://localhost}") String baseUrl) { + this.emailSender = emailSender; + this.mailConfigService = mailConfigService; + this.baseUrl = baseUrl == null ? "http://localhost" : baseUrl.replaceAll("/+$", ""); + } + + public void sendActivation(String email, String name, String token) { + String link = baseUrl + "/aktywacja/" + token; + String html = template( + "Aktywuj swoje konto", + greeting(name), + "
Dziękujemy za rejestrację w serwisie Polska Lokalnie. Aby dokończyć zakładanie konta i móc" + + " korzystać ze wszystkich funkcji, potwierdź swój adres e-mail klikając poniższy przycisk.
" + + "Link jest ważny przez 48 godzin. Jeśli to nie Ty" + + " zakładałeś konto, zignoruj tę wiadomość.
", + "Aktywuj konto", + link); + send(email, "Aktywuj konto w serwisie Polska Lokalnie", html, "AKTYWACJA", link); + } + + public void sendPasswordReset(String email, String name, String token) { + String link = baseUrl + "/reset-hasla/" + token; + String html = template( + "Ustaw nowe hasło", + greeting(name), + "Otrzymaliśmy prośbę o zresetowanie hasła do Twojego konta. Kliknij poniższy przycisk, aby ustawić" + + " nowe hasło.
" + + "Link jest ważny przez 1 godzinę. Dotychczasowe hasło" + + " pozostaje aktywne do momentu ustawienia nowego. Jeśli nie prosiłeś o zmianę hasła, zignoruj tę wiadomość.
", + "Ustaw nowe hasło", + link); + send(email, "Reset hasła w serwisie Polska Lokalnie", html, "RESET HASŁA", link); + } + + private void send(String email, String subject, String html, String label, String link) { + SmtpConfig smtp = mailConfigService.getSmtp(); + boolean configured = smtp.isEnabled() + && smtp.getHost() != null && !smtp.getHost().isBlank(); + if (!configured) { + // Tryb deweloperski - brak skonfigurowanej skrzynki. Logujemy link, by dalo sie przetestowac. + log.info("[E-MAIL:{}] SMTP nieskonfigurowany. Link dla {}: {}", label, email, link); + return; + } + SendResult result = emailSender.send(smtp, email, subject, html); + if (!result.ok()) { + log.warn("[E-MAIL:{}] Nie udalo sie wyslac do {} ({}). Link: {}", label, email, result.error(), link); + } + } + + private static String greeting(String name) { + String who = name == null || name.isBlank() ? "" : " " + name.trim().split("\\s+")[0]; + return "Cześć" + who + ",
"; + } + + /** Firmowy szablon HTML: naglowek z logo i nazwa, tresc, przycisk CTA, stopka. */ + private String template(String heading, String greetingHtml, String bodyHtml, String ctaLabel, String ctaUrl) { + return "" + + "Jeśli przycisk nie działa, skopiuj"
+ + " link do przeglądarki:
" + ctaUrl + "
Polska Lokalnie | SoftSPM
" + + "Ogłoszenia nieruchomości bez prowizji. Ta wiadomość została wysłana automatycznie - prosimy na nią nie odpowiadać.
" + + "{card.description}
- + {card.id === 'rules' ? ( + {card.action}+ Wyróżnione oferty wyświetlają się wyżej na listach i przyciągają więcej zainteresowanych{listingTitle ? ` - „${listingTitle}"` : ''}. +
+ + {done ? ( + <> +Ładowanie planów...
} +{error}
} + +{error}
} + {notActivated && ( + + )} + {info &&{info}
}Wpisz 10 cyfr numeru NIP, aby pobrać nazwę i adres firmy z rejestru REGON.
+ +Aktywujemy Twoje konto...
} + {state === 'ok' && ( + <> +Możesz się teraz zalogować i korzystać ze wszystkich funkcji serwisu.
+ Przejdź do logowania + > + )} + {state === 'error' && ( + <> +{message || 'Link aktywacyjny jest nieprawidłowy lub wygasł.'}
+Zaloguj się i poproś o ponowne wysłanie linku aktywacyjnego.
+ Przejdź do logowania + > + )} +Za chwilę przekierujemy Cię do logowania.
+ Przejdź do logowania + > + ) : ( + <> +Wpisz nowe hasło do swojego konta. Dotychczasowe hasło działa do momentu jego zmiany.
+ + > + )} +Wysłaliśmy kod SMS na numer {phone}. Wpisz go poniżej, aby potwierdzić poprawność numeru.
+ +{error}
} + {note &&{note}
} +Ładowanie...
+ ) : banners.length === 0 ? ( +Brak banerów. Dodaj pierwszy w formularzu powyżej.
+ ) : ( +{error}
} +{error}
} +{error}
:{note}
)} + + {/* Plany promowania */} +Brak planów.
} +Brak pakietów.
} +Brak płatności.
+ ) : ( +| Data | Użytkownik | Pozycja | Kwota | Metoda | Status | +
|---|---|---|---|---|---|
| {dt(o.createdAt)} | +{o.userEmail} | +{o.itemName} | +{zl(o.amount)} | +{o.method} | +{o.status === 'PAID' ? 'Opłacone' : o.status === 'PENDING' ? 'Oczekuje' : 'Błąd'} | +
{error}
:{note}
)} + +
+
Polska Lokalnie | SoftSPM
+{subtitle}
+Data ostatniej aktualizacji: {LAST_UPDATED}
+Zasady przetwarzania danych osobowych określa Polityka prywatności. Administratorem danych jest Usługodawca.
+ +Platforma wykorzystuje pliki cookie zgodnie z Polityką prywatności. Podczas pierwszej wizyty Użytkownik wyraża zgodę na wykorzystanie plików cookie lub ogranicza ją do plików niezbędnych.
+ +Platforma, jej układ, logotyp oraz oprogramowanie podlegają ochronie prawnej i stanowią własność Usługodawcy lub podmiotów, z którymi Usługodawca współpracuje. Kopiowanie lub wykorzystywanie bez zgody jest zabronione.
+ +Konsument może skorzystać z pozasądowych sposobów rozpatrywania reklamacji i dochodzenia roszczeń, w tym z platformy ODR Komisji Europejskiej dostępnej pod adresem ec.europa.eu/consumers/odr oraz z pomocy powiatowego (miejskiego) rzecznika konsumentów.
+ +Administratorem danych osobowych jest {PROVIDER.legal}, {PROVIDER.address}, NIP: {PROVIDER.nip}. Kontakt w sprawach danych osobowych: {PROVIDER.email}.
+ +Dane mogą być przekazywane podmiotom przetwarzającym je na zlecenie Administratora, w szczególności: dostawcy hostingu {PROVIDER.hosting}, Operatorowi płatności AutoPay (Autopay S.A.) w zakresie realizacji płatności, dostawcom usług e-mail i SMS oraz podmiotom świadczącym wsparcie techniczne - wyłącznie w zakresie niezbędnym i na podstawie odpowiednich umów powierzenia.
+ +Dane przechowujemy przez czas trwania umowy (posiadania Konta), a po jej zakończeniu przez okres wymagany przepisami (m.in. rozliczeniowymi) lub do przedawnienia roszczeń. Dane przetwarzane na podstawie zgody - do jej wycofania.
+ +Przysługuje Państwu prawo dostępu do danych, ich sprostowania, usunięcia, ograniczenia przetwarzania, przenoszenia, wniesienia sprzeciwu oraz cofnięcia zgody w dowolnym momencie (bez wpływu na zgodność z prawem wcześniejszego przetwarzania). Mają Państwo także prawo wniesienia skargi do Prezesa Urzędu Ochrony Danych Osobowych (ul. Stawki 2, 00-193 Warszawa).
+ +Dane są przetwarzane na terenie Europejskiego Obszaru Gospodarczego, a serwery Platformy znajdują się fizycznie na terytorium Rzeczypospolitej Polskiej. W razie przekazania danych poza EOG stosujemy odpowiednie zabezpieczenia (m.in. standardowe klauzule umowne).
+ +Zgodę na pliki inne niż niezbędne wyrażają Państwo w banerze cookie podczas pierwszej wizyty; można ją w każdej chwili zmienić w ustawieniach przeglądarki. Ograniczenie plików cookie może wpłynąć na dostępność części funkcji.
+ +Stosujemy środki techniczne i organizacyjne odpowiadające ryzyku, w tym szyfrowanie transmisji (SSL/TLS) oraz kontrolę dostępu do danych.
+ +Polityka może być aktualizowana. Aktualna wersja jest zawsze dostępna w Platformie wraz z datą ostatniej aktualizacji.
++ Używamy plików cookie, aby platforma działała poprawnie, oraz - za Twoją zgodą - do celów analitycznych + i marketingowych. Szczegóły znajdziesz w Polityce prywatności i{' '} + Regulaminie. +
+