Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [MySQL][PHP]Php mail() - limit wiadomości na serwerze
Forum PHP.pl > Forum > Przedszkole
darney
Witam. Posiadam swoją grupę mailingową. Z chwilą jej wielkości kiedy dobiłem do ponad 150 pojawił się problem z wysyłaniem hurtem jednej wiadomości. Na serwerze jest limit 100 maili na godzinę. Jak przebudować skrypt aby przygotował paczki odbiorców. 100 maili do jednej części osób i kolejne 100 do drugiej. Chciał bym także po wykonaniu skryptu nie martwić się już nim i zamknąć okno po ukazaniu się komunikatu o powodzeniu operacji. Czy jest to możliwe ?.

Mój skrypt to stary przebudowany książkowy.
  1. while ($row = mysqli_fetch_array($result)){
  2. $to = $row['mailer_email'];
  3. $mailer_imie = $row['mailer_imie'];
  4. $mailer_nazwisko = $row['mailer_nazwisko'];
  5. $msg = "Drogi $mailer_imie $mailer_nazwisko,\n$text";
  6. $from = 'From: "xxx@xxx.pl" <xxx@xxx.pl>' . PHP_EOL .
  7. //'Cc: "CC Display Name" <xxx@xxx.pl>' . PHP_EOL .
  8. 'X-Mailer: PHP-' . phpversion() . PHP_EOL;
  9. $from .= "Content-type: text/html; charset=utf-8\n";
  10. //$from .= "Content-Transfer-Encoding: 8bit\n";
  11.  
  12. mail($to, $subject, $txt_mail, $from);
  13. echo 'Wysłano wiadomość pod adres: ' . $to . '<br />';
  14.  
Wilu88
Sam właśnie piszę taki moduł do swojego cms'a i jedyne wg mnie sensowne wyjście to:

1. Przy tworzeniu nowej wiadomości stworzyć tabele w której zapiszesz oczekujące na wysyłkę maile w tabeli znajdzie się id maila z listy mailingowej oraz id wiadomości która będzie zapisana w innej tabeli.

Następnie w cronie napisać skrypt wykonujący się co godzinę a w nim:

pętla powiedzmy 50 przebiegową (w razie czego) która z tabeli oczekującej na wysyłkę pobierze maila i wiadomość wyśle ją a następnie usunie ten rekord jeśli pójdzie wszystko w porządku.

To mój pomysł może ktoś ma inny
peter13135
można ewentualnie zamiast crona użyć wejścia userów na stronę i sprawdzać po dacie.
thek
Też kiedyś się zmagałem z tym problemem i rozwiązalem podobnie do Wilu88. Pisze mailing i ustalam mu datę wysyłki (dziś lub przyszłość). Jeśli przyszłość to działa skrypt, ktory raz na dobę, przed północa sprawdza daty wysyłek maili i jeśli napotka taki, który ma wysyłke na dzień kolejny, dodaje maile dla jego adresatów do kolejki. Jesli wysyłka na dziś, to od razu wrzucam do kolejki. Skrytp wysyłający odpalany z crona co kilka minut. W konfigu ustalam wielkość paczki jako:
( limit_serwera - margines_bezpieczeństwa ) / ilość uruchomień_na_godzinę
czyli dla przypuśćmy 100/h dałbym 90-95/h (trzeba zostawić margines na rejestracje, odzyskiwanie haseł, zapytania mailowe itp). Jeśli odpalanie co 6 minut to 90/10 = 9 i tyle wynosiła by wielkość paczki u mnie by było OK. Poza tym przemyśl jeszcze możliwość zatrzymania i/lub wznowienia mailingu lub co zrobić jeśli mailing ruszył, a Ty aktualizowałeś treść mailingu po zauważeniu błędów. Do tego kontrola działania mailingu (ilość wysłanych, ilość prób błędnych) czy jego statystyki. Wiele osób o takich rzeczach nawet nie myśli lub nie wie jak zaimplementować, choć przynajmniej część powinna być.

I uwierz, że się da to czego chcesz, ale trzeba nieraz pokombinować z cronem lub uruchamianiem skryptu w CLI jesli serwis to umożliwia i nieskończone wywoływanie skryptu przez samego siebie, z dobrze napisanym warunkiem stop. To drugie to nie tak pewna metoda i nie zawsze możliwa do zastosowania. Nie polecam jednak jej nikomu, kto nie ma większej wiedzy bo można serwer załatwić.
Wilu88
Jeśli chodzi o zmianę treści maili w czasie wysyłki no to przecież i tak nic już nie zrobisz z mailami które zostaną wysłane. A skoro w tabeli z oczekującymi mailami masz podane tylko id wiadomości zapisanej w innej tabeli to gdy tam zmienisz jej treść, to przy wysyłaniu maila pobierze już nową treść.

Jedyne co można było by jeszcze przemyśleć to jakieś zabezpieczenie związane z porównywaniem daty edycji wiadomości a datą wysyłki maila, czyli nie usuwać rekordu po wysłaniu a dodawać tylko datę wysyłki i jeżeli zostanie zmieniona wiadomość to wysłać jeszcze raz maile, które mają datę mniejszą od daty edycji wiadomości.
thek
Zebyś Ty widział jak niektórzy piszą systemy mailingu to byś się zdzwił. Poza tym chyba nie bierzesz pod uwage jednego: mailing to nie zawsze "Bierz WYSIWYG i pisz całą treść mailingu" smile.gif Powiedziałbym, że ze względu na głupotę piszących takie coś to najgorszy sposób przechowywania mailingu do wysyłki. Musi obowiązywać pewien stały szablon. User powinien mieć możliwość eduycji jedynie wąskiego wycinka maila. Reszta powinna być niezmienna. W takim wypadku w bazie trzymany jest jedynie fragment i chyba nie powiesz mi, że przy każdym przejściu pętli lub co uruchomienie kolejnego cyklu crona byś go na nowo generował? Jeśli w moim skrypcie daje userowi 2 pola do uzupełnienia i opcjonalnie checkboxy do włączenia ewentualnych elementów dodatkowych + resztę layoutu maila generuję z automatu to niestety, ale srednio mi się to nada, zwłaszcza w chwili gdy pewne elementy maila zawierają jeszcze szablon do zmiany z użyciem preg_replace w stylu {username}, a dodatkowo może się nałożyć jednoczesna wysyłka kilku mailingów w jednym przebiegu cron-a, z czym też nie każdy skrypt sobie dobrze radzi.

Dobrze przemyslany skrypt wysyłający jest niewrażliwy na edycję mailingu, ponieważ go generuje w zasadzie tylko raz, gdy zaczyna wysyłkę, a jeśli zmiana następuje w trakcie wysyłki to ów wygenerowany usuwa i skrypt powinien sam sobie poradzić z jego ponownym utworzeniem. Odpada masa IFow, kombinowania z datami i zapychaniem bazy nadmiarowymi informacjami smile.gif

Przykładowo gdy u mnie w skrypcie rusza mailing to sprawdzam czy istnieje już wygenerowany w bazie o tym id. Jesli tak - korzystam, jeśli nie - tworzę i wrzucam do bazy jako cache oraz w skrypcie do tablicy z indeksem równym id. Jeśli w trakcie wysyłki nadpisze mailing to usuwam ów wygenerowany z bazy a dodatkowo sprawdzam czy nie zmieniła mi się grupa docelowa adresatów (mam skrypt gdzie mogę to określać) i modyfikuję kolejkę tak, by uwzględniło zmiany dla userów, którym jeszcze nie wysłało maila. Ogólnie jest więcej zabawy niż myślisz bo skrypt jest bardziej rozbudowany niż "napisz mailing i wysyłaj wszystkim". Jeśli dochodzą do tego grupy uzytkowników, szablony, wysyłki cykliczne, statystyki, obsługa newslettera dynamiczna (wstrzymywanie, wznawianie i edycja w locie) i trochę innych bajerów to mailing przestaje być banalnym skryptem.
Wilu88
Zgodzę się z Tobą że to nie jest prosta sprawa. Z drugiej strony ja piszę mailing na jakieś 100-200 maili nie podejrzewam aby kiedykolwiek było więcej, poza tym będzie wykorzystywany w naszej firmie, wiec odchodzi kwestia martwienia się o użytkownika.

Poza tym planuje ustawić crona aby wysyłał maile tylko w nocy aby nie obciążać serwera, tym samym zmian w treści w trakcie wysyłania raczej nie będzie biggrin.gif

Co do statystyk to też takie ubogie trochę zrobiłem za pomocą str_replace zamieniam linki występujące w treści na takie aby przechodziły przez skrypt przekierowujący na własnym serwerze, tym samym wiem ile było odwiedzin bezpośrednio z maili.

Wiadomo lepiej zrobić raz a porządnie aby służył i w serwisach z małą listą mailingową jak i w dużych serwisach, ale aktualnie moje umiejętności mi na to nie pozwalają biggrin.gif
thek
Ja także nie pisze kolosów smile.gif najwieksze mailingi, które na tym chodzą, mają góra kilkuset userów po stronie newslettera samego i może kilka tysięcy od strony wstrzykniętego serwisu. Mimo że brak na VPS z reguły limitów na wysyłke i w teorii można puścić od razu całoś, to nie robie tego. Czemu? Spamlisty smile.gif Jeśli serwer docelowy dostanie z jednego serwera dla różnych userów mail w bardzo krótkim czasie, to od pewnej ilości łapie Cię na spamlistę. A potem się tłumacz userom, czemu Twój newsletter muszą szukać w spamie wink.gif
darney
co myślicie o tym może to by miało jakieś zastosowanie w zaistniałym problemie ?
http://email.about.com/od/emailprogramming...hentication.htm

A może znacie jakieś gotowe systemy bo nie wiem czy mam zbytnio aktualnie czas żeby pisać od zera taki mailing. Widzę że to nie łatwe wyzwanie.

Nie rozumiem też jednej rzeczy. Jak ustawić skrypt aby wysyłał coś poza moją obecnością? Pakuje wiadomość do bazy do userów i wysyła już potem sam? przecież skrypt nie może się wykonywać dłużej niż 30 sek. Moja główka jeszcze tego nie ogarnia. Proszę o wyrozumiałość i wyjaśnienia:)
Proszę o opisanie mi drogi jak to ma wyglądać. Skrypt wysyła do bazy ->wiadomość-> poczekalnia w bazie -> co dalej ? czegoś nie rozumiem. SQL ma wysłać to tongue.gif ?
Też nie rozumiem co to jest ten cron. Ide czytać na google wink.gif
thek
CRON to unixowy demon chodzący w tle i co określony czas wywołujący zdefiniowane polecenia, czyli przykładowo uruchamiający skrypt wysyłający maile. Ustawiasz, że ma co ileś minut odpalić skrypt wysyłki i zapominasz wink.gif

Inna wariacja to napisac skrypt, który odpala sam siebie. Ale to już ciutkę wyższa szkoła jazdy bo można zapętlić go tak, że będziesz miał problem z zatrzymaniem wink.gif
darney
hehehe smile.gif Wtedy hulaj dusza admin netart piekła niema:) Powiedz mi co sądzisz o linku wyżej który dałem. Gdzieś odpowiedzieli że problem limitu mail() na serwerze można ominąć tym. Czy to prawda ? (wypowiedź wyżej - link)
Wilu88
Coś nie chce mi się wierzyć ale to thek jest tutaj specem. Co do tego hulaj dusza to też radziłbym uważać żeby za pomocą crona za bardzo nie obciążyć serwera wykonując masę skryptów w krótkich odstępach czasu wink.gif
thek
Można tak rozwiązywać, ale różne SMTP też mają swoje limity i moga Ci uwalić wysyłkę gdy zaczniesz przesadzać. Aby tego uniknąć najczęściej się stosuje rotowanie serwerów, czyli bierzesz kilka conajmniej SMTP i wysyłasz raz jednym, raz innym. Najprościej uzyć przygotowanych pod takie działania skryptów/bibliotek w stylu Swift Mailer.

Co do netart, to tam z CRONem jest kiepskawo o ile pamiętam... Można tylko raz na godzinę odpalać skrypt, no chyba że zrobisz kilka regułek do tego samego skryptu.
darney
Zgadza się jak narazie mój mailing liczy 150 osób tylko 2 wykonania skryptu 2 razy dziennie. W tygodniu 1x tongue.gif Musze poważnie obmyślić plan jak to napisać i ustawić w bazie. Moja programistyczna główka dopiero się rozwija. smile.gif

PIERWSZY ETAP
Widział bym to tak. Skrypt ma ustawione
Sprawdzam czy w bazie nie ma wiadomości które trafiły do TABELI "OCZEKUJĄCE"
Jeżeli PRAWDA to wysyłam 1-50 ID z oczekujących.

DRUGI ETAP - Godzinę póżniej tongue.gif
Sprawdzam czy w tabeli oczekujące nie ma jakiś maili
Jeżeli PRAWDA to wysyłam 50-100.

TRZECI ETAP - Godzinę póżniej tongue.gif
Sprawdzam czy w tabeli oczekujące nie ma jakiś maili
Jeżeli PRAWDA to wysyłam 100-150.

CZWARTY ETAP
Sprawdzam.........
FAŁSZ brak maili powyżej 150
nic nie robię i idę się nawalić smile.gif-> np. Informuje o tym admina serwisu tongue.gif mail to (admin@serwis.pl)

Czy dobrze myślę ?


Jak by miała pętla przykładowa sprawdzająca wyglądać ?


Wilu88
No nie możesz iść po id i założyć że od 1-50 od 50-100 itd. Dlatego że nei przekazujesz id pomiędzy etapami. Najprościej chyba usuwać wysłane z listy oczekujących. A kod powinien wyglądać tak:


1. Pobierz 50 rekordów z tabeli sortując ID od najmniejszego do największego.

2. W pętli wykonaj wysłanie maila, jeśli wyśle poprawnie usuń rekord z tabli oczekującej

darney
a drugie powtórzenie skryptu wywołanego CRONEM ? Jak będzie sprawdzać te 1-50 czy są puste ?
Wilu88
Po prostu ich już w bazie nei będzie. Powiedzmy masz w tabli oczekujących 150 maili do wysyłki z ID od 1 do 150.

Pierwszy etap:

Pobierz 50 maili sortując rosnąco (czyli pobiera maile od 1 do 49)

Wyślij maila i usuń rekord

Na końcu etapu zostaje ci w tabeli id od 50 do 150

Drugi etap:

Pobierz 50 maili sortując rosnąco (czyli pobiera maile od 50 do 100)

Wyślij maila i usuń rekord

Na końcu etapu zostaje ci w tabeli id od 101 do 150

Trzeci etap:

Pobierz 50 maili sortując rosnąco (czyli pobiera maile od 101 do 150)

Wyślij maila i usuń rekord

Na końcu etapu zostaje ci pusta tabela


Czwarty etap:

Pobierz 50 maili sortując rosnąco (Brak jakichkolwiek maili reszta kodu nie wykonuje się)


thek
Wilu... Zależy od tego jak podejdzie do problemu maili. Tak jak napisałeś jest ok, ale co jeśli maili więcej jest i osiągasz "masę krytyczną" czyli liczba wiadomości nie wysłana z powodu błędów osiąga wielkość określoną w zapytaniu przy LIMIT? Blokujesz cała kolejkę wysyłania, bo czekające błedne nie dopuszczą do przeskoczenia na możliwe do wysyłki wink.gif To też trzeba rozpatrzyć. Oczywiście w sytuacji gdy przewidujesz sprawdzanie czy mail został wysłany, a nie że walisz wysyłke i nawet nie sprawdzasz czy wszystko jest cacy. Mi się już zdarzały różne hece gdy warstwa transportowa skryptu się burzyła, że za żadne skarby nie pośle, bo mu serwer poczty docelowej adresata się nie podoba. Dlatego teraz zazwyczaj daje każdemu adresowi 3 próby i dopiero potem daję ignorowanie w kolejce, oczywiście statystyki mnie informują, że taki a taki mail nie załapał i tam mam szukać winowajcy potencjalnego.
Wilu88
Cytat(thek @ 28.07.2011, 15:09:30 ) *
Wilu... Zależy od tego jak podejdzie do problemu maili. Tak jak napisałeś jest ok, ale co jeśli maili więcej jest i osiągasz "masę krytyczną" czyli liczba wiadomości nie wysłana z powodu błędów osiąga wielkość określoną w zapytaniu przy LIMIT? Blokujesz cała kolejkę wysyłania, bo czekające błedne nie dopuszczą do przeskoczenia na możliwe do wysyłki wink.gif To też trzeba rozpatrzyć. Oczywiście w sytuacji gdy przewidujesz sprawdzanie czy mail został wysłany, a nie że walisz wysyłke i nawet nie sprawdzasz czy wszystko jest cacy. Mi się już zdarzały różne hece gdy warstwa transportowa skryptu się burzyła, że za żadne skarby nie pośle, bo mu serwer poczty docelowej adresata się nie podoba. Dlatego teraz zazwyczaj daje każdemu adresowi 3 próby i dopiero potem daję ignorowanie w kolejce, oczywiście statystyki mnie informują, że taki a taki mail nie załapał i tam mam szukać winowajcy potencjalnego.



Oczywiście że tak. To taki przykład tylko dla zobrazowania dzielenia na etapy. A to jak podejdziesz do sprawdzania czy maile przeszły do sprawa indywidualna. Osobiści skłaniam się ku dodatkowemu polu w którym będzie zapisany status wysyłki.
darney
Cytat(darney @ 27.07.2011, 10:10:22 ) *
  1. while ($row = mysqli_fetch_array($result)){
  2. $to = $row['mailer_email'];
  3. $mailer_imie = $row['mailer_imie'];
  4. $mailer_nazwisko = $row['mailer_nazwisko'];
  5. $msg = "Drogi $mailer_imie $mailer_nazwisko,\n$text";
  6. $from = 'From: "xxx@xxx.pl" <xxx@xxx.pl>' . PHP_EOL .
  7. //'Cc: "CC Display Name" <xxx@xxx.pl>' . PHP_EOL .
  8. 'X-Mailer: PHP-' . phpversion() . PHP_EOL;
  9. $from .= "Content-type: text/html; charset=utf-8\n";
  10. //$from .= "Content-Transfer-Encoding: 8bit\n";
  11.  
  12. mail($to, $subject, $txt_mail, $from);
  13. echo 'Wysłano wiadomość pod adres: ' . $to . '<br />';
  14.  


słuchajcie a jak ustawić pętle żeby ten skrypt wysłał do ludzi o ID zaczynających się od 50-100 np ?
Póki co zrobię sobie osobne skrypty tzn.
Link do skryptu1 wysyłam od 1-50
Link do sktyptu2 wysyłam od 50-100
i wtedy tylko kopiuj wklej pośle list o newsach. Na razie ich dużo nie mam więc tyle mi starczy lecz wiedzę którą tu poruszyliście sobie zapisze tongue.gif

Póki rozwijam swój serwis to tyle mi wystarczy. jak będę dobijał do 1000 osób to wtedy zacznę zmartwienia co dalej.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.