Massenemailversand mittels PHP und Javascript
Daniel Petratsch
- programmiertechnik
Hallo!
Ich habe folgendes Problem: Ich bin gerade dabei eine Benutzerverwaltung zu programmieren und es können Benutzer zu verschiedenen Gruppen zugeordnet werden. Nun möchte ich gerne einen automatischen "Email an gesamte Gruppe-Versand" realisieren. Ich habe das einmal mit 500 Mails versucht, das Script braucht dann schon fast 5 Sekunden, also wäre bei grösseren Mengen ein Timeout fast unumgänglich.
Was die ganze Sache noch erschwert, ist dass ich gerne eine Statusanzeige hätte, die dem Benutzer mitteilt wieviele Mails schon verschickt wurden, damit es Benutzerfreundlicher wird. Nun stellt sich aber das Problem wie sich so etwas realisieren lässt.
Folgende Möglichkeit bezugs des Timeouts hätte ich:
Ich definiere einen iframe, an den ich in einer Schleife die id's übergebe an denen die Mail geschickt werden sollte.Im iframe wird dann jeweils nur 1 Mail an die spezifische Person geschickt, solange bis die Schleife halt abgearbeitet ist. Natürlich müsste ich dann aber die Schleife in Javascript ablaufen lassen, ansonsten wäre es natürlich sinnlos.
Bezugs der Statusanzeige bin ich mir nicht so sicher, ist es vielleicht möglich im Zuge der Abarbeitung der im iframe bearbeiteten Mails auch eine JS Funktion zu schreiben, die nach jedem zumindest angenommenen erfolgreichen Versand der Mail den Counter der verschickten Mails um 1 erhöht und per DOM auf den übergeordneten Frame zugreift und dynamisch den Counter verändert ?
Ich habe da schon lange gegrübelt, bin aber leider auf keine bessere Lösung gekommen.
Vielleicht weiss ja wer von euch eine bessere Lösung(wovon ich eigentlich ausgehe :) )?
Danke,
Daniel
Hi!
Konkret kann ich dir leider nicht weiterhelfen. Aber da ja sonst auch nix zu kommen scheint, kannst du dich vielleicht vorerst mal in einem Skript-Archiv nach ein paar Newsletter-Skripten auf PHP-Basis umschauen und etwas im Quelltext spionieren.
Ich selber habe schon mehrfach den ListMessenger implementiert, der auch eine recht große Menge Mails schicken können soll und beim Versand ein Statusfenster anzeigt. Den gibt's hier zum Runterladen: http://www.listmessenger.com/
Gruß,
Matthias
Hello Daniel,
zum Thema Massenmail und Jobkontrolle gab es gerade eine Diskussion, die Sven Rautenberg durch einige wesentliche Einwände durchaus zu einem möglichen Ziel gelenkt hat...
[pref:t=71592&m=412176]
Grundsätzlich will ich hier nochmal was vom Stapel lassen:
Es gab eine Zeit, so um 1928 rum, da konnte die mechanische Datenverarbeitung durch Überlegeung und schlaue Programmierung ungefähr das leisten, was heutige "Client-Server-Programme" können. Nur dass die heutigen den Müll viel schneller produzieren *grummel*
Damals, da gab es nur die Stapelverarbeitung. Aufgaben wurden definiert und dann nahezu beliebig oft von einer Maschine ausgeführt. Das Ergebnis hat man sich erst angesehen, wenn die Aufgabenstellung auf den gesamten Stapel angewendet war. Also klassisch Eingabe - Verarbeitung - Ausgabe.
Dann kanem irgendwann mit der Elektromechanik die ersten Job-Systeme auf. Man konnte einen Aufgabenstapel nur noch aus einem Job bestehen lassen, dessen Ergebnis betrachten, ggf nachsteuern und dann den nächsten Job (als Teilaufgabe eines Batch-Jobs) freigeben. Das war die frühe Dialogorientierung. Allerdings war das Ziel noch nicht erreicht, denn unter Dialog verstehen Arbeitswissenschaftler/Psychologen/Softwarepsychologen eine möglichst unverzügliche Antwort auf eine Aktion. Über die Zeit, in der beide Ereignisse liegen müssen, streitet man sich immer wieder, aber sie liegt zwischen "sofort" und ca. 800ms. Kann man auch gut beobachten, wenn man sich mal Talkshows ansieht. Wenn die Zeit länger als 800ms wird, haben andere Teilnehmer der Runde die Möglichkeit, "dazwischenzufunken" und aus dem Dialog wird ein Multilog.
Nun gut. Durch die Mehrplatzsysteme und erst recht durch die Arbeitsplatzcomputer wurden dialogorientierte Programme möglich. Dazu muss es eine direkte Prozesskopplung zwischen Eingabe-Verarbeitung-Ausgabe geben, also eine persistente _Verbindung_ und möglichst keine Verzögerung zwischen der Absendung einer Nachricht in einer der Stufen und dem Eintreffen beim Empfänger. Also Verarbeitung sendet Nachricht an Ausgabe, dass jetzt gerade 100 Mails fertig sind, jetzt 101, jetzt 102...
Dieses Verhalten lässt sich mit der Client-Server-Technologie, wie sie mit HTTP realisiert wird, nicht so einfach nachbilden. Jede neue Auskunft erfordert einen neuen Request, jede Eingabe öffnet einen neunen Prozess am Server. Wenn man hier also nun versucht, die Daten, Zustände und Ereignisse der verschiedenen zu einer Aufgabe gehörenden Prozesse zusammenzuführen, vergewaltigt man quasi das System. Es ist dafür nicht gemacht worden. Chat unter PHP ist deshalb auch nicht so praktisch.
Im Grunde ist die Browsertechnik ein Rückschritt in der Datentechnik. Man besinnt sich auf ältere Techniken, die aber nun mit moderneren Mitteln der Eingabe, Ausgabe und Verarbeitung nochmal neu erfunden werden, ca 80 Jahre nach ihrer ersten großtechnischen Umseztung (Holerit), allerdings mit dem Nutzen einer fast weltweiten Verbreitung der Technik.
Was heißt das nun für das Massenmailprogrammm?
Du solltest kein Programm schreiben, das eine direkten Dialogbetrieb erforderlich macht. Du solltest Dein Programm prozessoreintiert schreiben.
Jeder angestoßene "Job" muss alleine zurechtkommen und seine Fehlermeldungen so ablegen, dass sie zur Not auch nach drei Wochen noch gesichtet werden können.
Der Client kann sich durch Requests auf diese Meldungsstapel dann überblick verschaffen über den Zustand des Jobs zum Zeitpunkt der Fehlermeldung. das wird immer in der Vergangenheit liegen. Bei Dialogorentierten Programmen kommt man da ja fast an den Status Quo heran, aber auch nur fast!
Zum Abschluss noch ein kleines Testscript, dass Du mal in mehreren Fenstern gleichzeitig aufrufen kannst:
-----------------------------------------------------------------
<?php #### multimail.php ####
ini_set("track_errors","1");
$php_errormsg = "";
set_time_limit(1);
echo "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.1 Transitional//EN">\n";
echo "<HTML>\n";
echo "<HEAD>\n";
echo " <TITLE>Dauerlauf</TITLE>\n";
echo "</HEAD>\n";
echo "<BODY>\n";
$ok = ignore_user_abort();
if ($ok)
{
echo "Abbruch durch Benutzer wird ignoriert<br />";
}
else
{
echo "Abbruch durch Benutzer stoppt das Script<br />";
}
flush();
$count = 0;
while (!connection_aborted())
{
$count++;
$ok = mail ("thomas@localhost", "Testmail $count", "Nur zum Spass\n\nTschüss");
$fehler = $php_errormsg;
echo "$count | ". getmypid()." | ".time()." $fehler ".(($ok===false)?"FALSE":"TRUE")."<br />";
flush();
sleep(5); # dafür kann man auch usleep() nehmen, wenn es schneller gehen soll *gg*
# sleep() und usleep() setzen das Timeout zurück.
}
echo "</body>\n";
echo "</html>";
?>
---------------------------------------------------------------------
Und nun noch eine Bitte: Das script sollte NICHT zum Spammen
eingestzt werden, sondern nur zum kontrollierten Versand von
erwünschten Newsletters oder Terminmitteilungen o.ä.
Liebe Grüße aus http://www.braunschweig.de
Tom
Hi Tom,
Danke für den netten Rückausflug in die Urzeiten der automatischen Datenverarbeitung :)
Nun gut. Durch die Mehrplatzsysteme und erst recht durch die Arbeitsplatzcomputer wurden dialogorientierte Programme möglich. Dazu muss es eine direkte Prozesskopplung zwischen Eingabe-Verarbeitung-Ausgabe geben, also eine persistente _Verbindung_ und möglichst keine Verzögerung zwischen der Absendung einer Nachricht in einer der Stufen und dem Eintreffen beim Empfänger. Also Verarbeitung sendet Nachricht an Ausgabe, dass jetzt gerade 100 Mails fertig sind, jetzt 101, jetzt 102...
Dieses Verhalten lässt sich mit der Client-Server-Technologie, wie sie mit HTTP realisiert wird, nicht so einfach nachbilden. Jede neue Auskunft erfordert einen neuen Request, jede Eingabe öffnet einen neunen Prozess am Server. Wenn man hier also nun versucht, die Daten, Zustände und Ereignisse der verschiedenen zu einer Aufgabe gehörenden Prozesse zusammenzuführen, vergewaltigt man quasi das System. Es ist dafür nicht gemacht worden. Chat unter PHP ist deshalb auch nicht so praktisch.
Ja leider ist das so wie du sagst nicht so einfach, wenn keine persistente Verbindung hergestellt ist, und wirkt sich auf die Performance des Servers auch nicht gerade positiv aus.
Was heißt das nun für das Massenmailprogrammm?
Du solltest kein Programm schreiben, das eine direkten Dialogbetrieb erforderlich macht. Du solltest Dein Programm prozessoreintiert schreiben.
Jeder angestoßene "Job" muss alleine zurechtkommen und seine Fehlermeldungen so ablegen, dass sie zur Not auch nach drei Wochen noch gesichtet werden können.
Wie genau soll ich das verstehen, das ich das Programm Pozessoientiert schreiben soll ? Ich sollte so eine Art Queue am Server erstellen (zb speichern der unerledigten Aufgaben in Mysql), die automatisch dort in "aller Ruhe" abgearbeitet wird. Also ich gebe den Auftrag XY in Arbeit , und lasse das Script einmal laufen. Zwischendurch kann ich eine Abfrage an das Script starten, dass mir dann über den aktuellen Bearbeitungsstatus Auskunft gibt, zb "237 von 1278 Mails erfolgreich bearbeitet...".
Mich würde noch interessieren, ob ich auf dem Server auch so eine Art Batch Prozess starten kann, der im Hintergrund abläuft und sich zb auch zu bestimmten Zeitpunkten automatisch starten lässt -> Beispiel Online Games, da muss ja auch jede Sekunde einmal die Datenbank aktualisiert werden.
Und nun noch eine Bitte: Das script sollte NICHT zum Spammen
eingestzt werden, sondern nur zum kontrollierten Versand von
erwünschten Newsletters oder Terminmitteilungen o.ä.
Danke für das Script, ich werde es mal einbauen :)
freundliche Grüsse und nochmals Danke,
Daniel