[PHP] Massenmails versenden

flaschenkind

Well-known member
ID: 118459
L
20 April 2006
4.507
337
Ich bin grade dabei ein Newsletterscript zu schreiben. Voraussichtlich werden einige tausend Mails verschickt. Jetzt stellt sich die Frage, wie sich das am besten realisieren lässt.

Ich hatte bis jetzt folgende Ideen:
  1. Alles zwischenspeichern und immer in nem Paket zu verschicken, nur da stellt sich die Frage, wie groß ich die Pakete mache. 50 Mails, mehr oder weniger?
  2. Einmal die Mailfunktion aufrufen, mit allen BCC Email Adressen im Header. Allerdings ist die Frage, ob das gut geht mit nen paar tausend BCCs?

Was würdet ihr machen, oder hättet ihr andere Lösungen?
 
Ich würde für jede Mail einen Eintrag in der Datenbank halten.

Per Cronjob wird dann alle paar Minuten (um die Serverlast vielleicht weng zu verteilen) ein*) Eintrag geholt, Mail geschickt und die Zeile gelöscht (oder mit einem Fehlerflag versehen, wenn mail() scheitert).

*) Zeilenweise arbeiten is halt nicht gut für die DB. Auf der anderen Seite, wenn ich mir n 1000er-Paket hol und mir bricht der Cron nach 999 Stück ab, kriegen 999 Empfänger die Mails doppelt.
Hier sollte man n gesundes Mittelmaß gefunden werden. Ich persönlich würde in 50er-Paketen alle 5 Minuten senden. Da deine Gesamtanzahl aber größer is, würd ich dann halt minütlich das Paket bearbeiten. Imho lieber kleinere Pakete und öfter senden, als zu große Pakete.
 
Bei mysqldumper wird das abbrechen des Skriptes so umgangen indem die Seite nachdem einige tausend datensätzte heruntergeladen wurden neu geladen wird. Dann werden wieder ein paar Datensätze heruntergeladen und die Seite wird neu geladen. Das kannst man auch gut beim mailversand anwenden, allerdings funktioniert das eventuel nicht wenn du das per cronjop aufrufst.
 
Um mal auf die Masse nen gutes Mittel zu finden:
Mein Server braucht für die Bearbeitung einer E-Mail, also vom PHP nehmen bis das es der Mailserver vollständig an den Empfänger geschickt hat im Durchschnitt 1,5 bis 2 Sekunden.

Das Versenden erfolgt jedoch sowieso im Hintergrund und auch mehrere Mails simultan (ich weiß jetzt nicht wie viele aber ich glaube 5 gleichzeitig ist Limit), also kann man Locker pro Minute 150 Versenden. Und wenn es mehr werden, landen die inner Mail-Queue und werden vom Mailserver nach und nach abgearbeitet.
 
Ich würde für jede Mail einen Eintrag in der Datenbank halten.
Hatte ich so auch vor, und dann löschen wenn die Mail versendet wurde, bzw. stehen lassen wenn nicht.

Per Cronjob wird dann alle paar Minuten (um die Serverlast vielleicht weng zu verteilen) ein*) Eintrag geholt, Mail geschickt und die Zeile gelöscht (oder mit einem Fehlerflag versehen, wenn mail() scheitert).
Das mit dem Cronjob find ich nicht so gut, weil man nie weiß wie der Auftraggeber das einzurichten weiß. Wie wäre es denn wenn ich einfach die Datei immer neu laden lasse (mit header('Location: versand.php');) und vorher nen sleep() von z.B. 5 Sekunden, damit das abgearbeitet werden kann, bevor weitergeleitet und neu versendet wird? Und dann im Paket z.B. 100 Mails.

Jo, so ähnlich, mit aufteilen, hatte ich mir das ja auch schon überlegt.

Also dann lieber 100 Stück versenden, nen sleep() von einer Minute und dann weiter machen?
 
Wie wäre es denn wenn ich einfach die Datei immer neu laden lasse (mit header('Location: versand.php');) und vorher nen sleep() von z.B. 5 Sekunden, damit das abgearbeitet werden kann, bevor weitergeleitet und neu versendet wird?
Wenn dir nicht grad der Server alleine gehört, hast du ja immer ein Zeitlimit, wie lange dein Script laufen darf und alle Mails kriegst du in der Zeit niemals durch, drum der Vorschlag mit den Cronjobs.

Wenn du beliebiglange Scripts laufen lassen kannst, ist ein Script mit
PHP:
while(!all_done)
{
  process(50);
  sleep(300);
}
natürlich gleichbedeutend mit einem Cron alle 5 Minuten, der nur
PHP:
if(!all_done)
  process(50);
macht.
 
Nein, so meint ich das nicht. Ich meinte sowas:

PHP:
while($mails_vorhanden){ //kleiner 50 oder so
    sendmail();
}
sleep(5); //oder wielang auch immer
header('Location: sendmail.php'); //erst nach der sleep() Pause weiter senden, dmait der Mailserver Zeit hatte zum Mails verarbeiten
 
Ich weiß nicht in wie weit du dich damit auskennst, aber PHP öffnet ja bei jedem mail() ein SMTP-Socket.
Nun könnte man doch den SMTP-Socket einmal öffnen, alle E-Mails ablegen zum versenden, und dann erst den Socket schließen.
So würde es, denke ich, sehr gut gehen. Ob man dann auch alle 100 Mails oder so das Script neuladen sollte, kann ich nicht beurteilen ;)
Aber wenn das Script durchgehend laufen sollte, hilft set_time_limit(0); und ignore_user_abort(1);. Aber diese Einstellungen könnten glaube ich vom Serveradmin abgeschaltet sein, bzw. es gibt trotzdem noch eine maximale Ausführungszeit.

PS: Hier noch 2 PEAR-Klassen: Mail_Queue und Mail