1211chef: mime::light

hi @all, ich hab da so nen ökoladen der möchte newsletter an seine kunden verschicken. nur text/plain. die DB umfasst derzeit knapp 10000 kunden. ich lade also die emailadressen in eine liste und lasse sie in einer schleife abarbeiten.

use MIME::Lite;

......

foreach (@mails)
{
  my $msg = MIME::Lite->new 
  ( 
   From =>"Peter Lustig News <lustig@rueben.laden>", 
   Organization =>'Peters lustiger Rübenladen',
   To=>$_,
   Subject =>$some_dingens,
   Type =>'text/plain',
   Data =>$some_news."\n\nDas ist ein Newsletter den sie bestellt haben und kein sPaM ... bla ..."
  );

  $msg->send;
}

Funzen wird das wohl. Ich hab nur keine Erfahrung damit und würde gerne wissen was ich da alles falsch machen kann. Kann ich mime::light einfach zack mit 10000 mails füttern? Wie lange dauert eigentlich so ein einzelner Sendevorgang? Sollte ich das Script vielleicht sagen wir alle 500 mails ein paar sekunden schlafen lassen? Hab keinen Plan ...

Erst mal schönes WE

Gustl

  1. Hi,

    für Massenmails/Newsletter gibts dedizierte Provider und ich denke, bei 10 T Empfängern bist Du da richtig, auch wg. der Haftung.

    Ansonsten ist das kein Problem eines Perl-Moduls, Massenmails zu senden. Guck Dir an, ob die Maildatei richtig erstellt wird, ob die Header stimmen und die Zeichenkodierung und ob das ein handelsüblicher Mailclient darstellen kann. Bei MIME gibts unendlich viele Möglichkeiten, multipart Mails zu erzeugen und mindestens genausoviele Fehlerquellen ;)

    Wenn Du das mit den Massenmails wirklich slbst erledigen willst, üblich ists die Mails auf /usr/sbin/sendmail zu pipen. Dann ist der Perlprozess längst zuende, wenn sendmail noch rattert.

    1. .. üblich ists die Mails auf /usr/sbin/sendmail zu pipen ..

      hi, ich dachte irgendwo gelesen zu haben dass mime-light das automatisch macht.

      .. Dann ist der Perlprozess längst zuende, wenn sendmail noch rattert.

      so wird das sein. ich würde mein dingens deshalb gern so schreiben, dass ich sehen kann wie lange sendmail rattert, also sozusagen die schleife erst fortsetzen wenn mail x definitiv gesendet ist.

      dafür fehlen mir die tieferen kenntnisse, deshalb frag ich euch.

      eine nette ajax-fortschrittsanzeige mit balken hab ich schon gebaut. das problem ist natürlich, dass ich keine echten testläufe machen kann. ich simuliere das derzeit nur indem ich das script pro schleifendurchlauf ein paar hundertstel sec. warten lasse ohne eine mail rauszuschicken.

      wie läuft das denn ab? ... wenn ich den einzelnen sendeprozess innerhalb der schleife (w.o.) anstosse und wieder beende, muss die schleife bis zum neuen prozess warten, oder? (ich kann mir das irgendwie nur "mechanisch" vorstellen.) falls das so ist, kann ich mir von meinem sendescript die zeitunterschiede während des schleifendurchlaufs liefern lassen und verarbeiten.

      dann seh ich aber nur die prozesszeit von mime-light, aber nicht die von sendmail?

      wie muss ich mir das vorstellen?

      im gunde möcht ich folgendes:

      schleife { mail schicken; frage an sendmail, ist die mail raus? wenn ja, nächste mail schicken }

      gruss gustl

      1. Hallo,

        im gunde möcht ich folgendes:

        schleife { mail schicken; frage an sendmail, ist die mail raus? wenn ja, nächste mail schicken }

        ich glaube nicht, dass du das möchtest. Denn sendmail kann auch ein Alias für einen ausgewachsenen Mailserver wie Exim oder postfix sein, zu dessen Aufgaben es unter anderem gehört, Mails zunächst zurückzustellen und nach gewisser Zeit (das können Stunden sein!) erneut zu probieren, wenn etwa der Zielserver gerade nicht erreichbar ist oder sonst ein temporäres Problem meldet. In dem Fall würdest du dein Script ebenfalls mehrere Stunden lang aufhalten.

        Abgesehen davon sieht die übliche Infrastruktur dieses Beobachten und Abwarten gar nicht vor. Der Mailversand soll normalerweise asynchron im Hintergrund laufen; sendmail nimmt praktisch nur den Versandauftrag entgegen und macht dann im Untergrund allein weiter. Wenn alles durchgenudelt ist, kannst du also mit Sicherheit nur sagen: Ich habe alle Nachrichten eingeworfen. Ja, genau so darf man sich das vorstellen: Du hast eben hundert Briefe in den gelben Kasten geworfen. Was ab jetzt damit passiert, entzieht sich deiner Kontrolle.

        So long,
         Martin

        --
        Logik ist die Theorie, Chaos die Praxis.
        1. Hallo,

          im gunde möcht ich folgendes:

          schleife { mail schicken; frage an sendmail, ist die mail raus? wenn ja, nächste mail schicken }

          ich glaube nicht, dass du das möchtest.

          mögen möcht ich schon, aber können kann ich nicht, deshalb will ich dann auch nicht mehr wollen :-)

          Abgesehen davon sieht die übliche Infrastruktur dieses Beobachten und Abwarten gar nicht vor. Der Mailversand soll normalerweise asynchron im Hintergrund laufen; sendmail nimmt praktisch nur den Versandauftrag entgegen und macht dann im Untergrund allein weiter. Wenn alles durchgenudelt ist, kannst du also mit Sicherheit nur sagen: Ich habe alle Nachrichten eingeworfen. Ja, genau so darf man sich das vorstellen: Du hast eben hundert Briefe in den gelben Kasten geworfen. Was ab jetzt damit passiert, entzieht sich deiner Kontrolle.

          das ist (für mich) sehr gut erklärt martin, ich kann nämlich nur in bildern denken.

          ich mach jetzt noch nen anderen test und melde mich danach nochmal.

          gustl

        2. Hallo Martin,

          Denn sendmail kann auch ein Alias für einen ausgewachsenen Mailserver wie Exim oder postfix sein, […]

          rotfl danke, made my day ;)

          LG,
          CK

      2. Tach!

        ich würde mein dingens deshalb gern so schreiben, dass ich sehen kann wie lange sendmail rattert, also sozusagen die schleife erst fortsetzen wenn mail x definitiv gesendet ist.

        Das ist nicht wirklich erstrebenswert. Definiere aber erstmal "definitiv gesendet"! Ist das der Zeitpunkt, wenn der Brief in den Briefkasten geworfen wurde? Oder ist das der Zeitpunkt, wenn der Briefkasten geleert wurde, die Briefe im Postamt gestempelt wurden und zum Transport in die Zielregion einsortiert wurden? Oder ist das der zeitpunkt, wenn der Brief das Zielpostamt erreicht hat? Oder ist das der Zeitpunkt, wenn der Postbote den Brief beim Empfänger eingeworfen hat? Und was ist mit unvorhergesehenen Zwischenfällen? Zum Beispiel, wenn ein Brief heute nicht zugestellt werden kann, weil der Postkasten voll ist, oder die Andresse falsch geschrieben wurde? Müssen dann die restlichen Briefe warten, bis das Problem geklärt ist?

        dafür fehlen mir die tieferen kenntnisse, deshalb frag ich euch.

        Normalerweise hat man keine Überwachungsmöglichkeit des Sendevorgangs. Man übergibt Sendmail (oder einem Ersatz) die Mail und Sendmail kümmert sich um den Rest, so wie es eben grad geht. Wenn die Zustellung auch nach wiederholten Versuchen nicht geklappt hat, gibt es eine Bounce-Mail.

        Es gibt nämlich auch absichtliche Verzögerungen, wie Graylisting, bei dem die Annahme erstmal verweigert wird und die Mail erst nach dem zweiten oder dritten Versuch reingelassen wird. Dazwischen liegen aber gern mal 15 Minuten. Solange willst du sicherlich nicht warten.

        dedlfix.

        1. Tach!

          och tach!

          ich würde mein dingens deshalb gern so schreiben, dass ich sehen kann wie lange sendmail rattert, also sozusagen die schleife erst fortsetzen wenn mail x definitiv gesendet ist.

          Das ist nicht wirklich erstrebenswert. Definiere aber erstmal "definitiv gesendet"! Ist das der Zeitpunkt, wenn der Brief in den Briefkasten geworfen wurde?

          genau. "in den briefkasten geworfen" == der brief hat das haus verlassen.

          gruss gustl

          1. Tach!

            genau. "in den briefkasten geworfen" == der brief hat das haus verlassen.

            Dann ist das die Übergabe an sendmail. Ob der Briefkasten an deinem Haus hängt oder drei Querstraßen weiter, ist dabei unerheblich. sendmail wird dir die Einlieferung sofort bestätigen. Als Fehlerquelle bleibt dann im Prinzp nur, dass sendmail nicht aufgerufen werden konnte.

            dedlfix.

            1. Dann ist das die Übergabe an sendmail. Ob der Briefkasten an deinem Haus hängt oder drei Querstraßen weiter, ist dabei unerheblich. sendmail wird dir die Einlieferung sofort bestätigen. Als Fehlerquelle bleibt dann im Prinzp nur, dass sendmail nicht aufgerufen werden konnte.

              das sollte mir dann wohl last_send_successful() sagen können.

              wenn eine rückgabe durch diese funktion möglich ist, muss der prozess ja beendet sein bevor die nächste addy verarbeitet wird, also läuft mein script solange, bis alle sendeprozesse einzeln gestartet und beendet wurden? ist doch so oder?

              gruss gustl

              1. Tach!

                das sollte mir dann wohl last_send_successful() sagen können.

                Wenn es Perl-spezifisch wird, muss ich passen.

                dedlfix.

  2. die DB umfasst derzeit knapp 10000 kunden. ich lade also die emailadressen in eine liste und lasse sie in einer schleife abarbeiten.

    foreach (@mails)
    {
      my $msg = MIME::Lite->new 
      ( 
       To=>$_,
      );
    
      $msg->send;
    }
    

    Funzen wird das wohl.

    Furzen ist wohl der richtige Ausdruck. Bei 10.000 Empfängern möchtest du nicht jede Mail einzeln senden, sondern die Empfänger en bloc angeben, damit das Mailsystem wenigstens die Chance hat, den Vorgang ein wenig abzukürzen.
    Nur mal als Gedankenspiel: Stehen in der Liste 1000 Empfänger bei web.de, braucht die Mail nur einmal an web.de übertragen werden, nicht tausendmal, wie bei deinem Ansatz.

    Benutze den Bcc-Kopf, probiere es erstmal mit 100 Mails à 100 Adressen und steigere danach langsam, bis Perl, sendmail oder ein empfangender Server dir das vor die Füße kotzt. Sortiere die Adressen unbedingt nach Empfängerdomain vor, besser noch nach MX, also nach die Mails für die Domain verarbeitendem Server. Zwischen den Aufrufen keine Pause einlegen, das bringt nichts.

    1. Hallo,

      Bei 10.000 Empfängern möchtest du nicht jede Mail einzeln senden, sondern die Empfänger en bloc angeben, damit das Mailsystem wenigstens die Chance hat, den Vorgang ein wenig abzukürzen.
      Nur mal als Gedankenspiel: Stehen in der Liste 1000 Empfänger bei web.de, braucht die Mail nur einmal an web.de übertragen werden, nicht tausendmal, wie bei deinem Ansatz.

      technisch ist das absolut sinnvoll. Aber dagegen steht, dass Mails schon bei der Einlieferung beim Postausgangsserver (SMTP) ein umso höheres Risiko haben, als SPAM abgelehnt zu werden, je mehr Empfänger in To:, CC: und BCC: stehen. Manche Mailserver machen schon bei "nur" 30 Empfängern die Schotten dicht, wie eine Bekannte von mir neulich erfahren musste, die eine Info an ihre Vereinskollegen schicken wollte.

      Für solche Massenmailings ist es daher sinnvoller, entsprechende dafür vorgesehene Software zu verwenden. Die sorgt zum Beispiel auch dafür, dass eine große Zahl von Mails über einen gewissen Zeitraum verteilt werden und umgeht (oder reduziert) so das Risiko, an einer SPAM-Schwelle zu scheitern.

      So long,
       Martin

      --
      Bei der Umsetzung von guten Ideen hapert es meist viel mehr an der Wolle als an der Könne.
  3. also. ich hab die sache nun am rattern.

    auf meinem dedicated vautronserver braucht mime-light ca. 0.156 sec. für das "verbringen" einer reinen text-email zu sendmail. das ist ganz schön lange. getestet habe ich einen durchlauf mit knapp 10.000 adressen auf meine eigene testadresse. neben einem 504 hat mime-light angefangen jede mail doppelt zu verschicken. KA.

    ich bilde also jetzt mehrere teilmengen die der anwender selbst einstellen kann. also zb. ab DBpos1 500 emails, und erhöhe die startposition danach jeweils automatisch um den sendeauftrag/stück. das ganze kann der anwender auf einem echtzeit-fortschrittsbalken beäugeln, den ich mir per ajax liefern lasse. wenn die anzahl der mails durchgelaufen ist kann der anwender also ab der neuen position einen weiteren sendeauftrag starten. falls die sache irgendwie serverseitig abbricht speichere ich pro schleifendurchlauf die zuletzt bearbeitete position, bei der man im badarfsfall neu anfangen kann. wenn die internetverbindung abbricht arbeitet das script auf dem server ja trotzdem weiter, einem anwender ist das aber idr. nicht bekannt und er würde wieder von vorne anfangen.

    der anwender gibt also eine anzahl emails an und ich berechne mit js während der eingabe gleich die ca. dafür benötigte zeit. hab ihm gesagt er soll besser je sendeauftrag unter 2 minuten bleiben :-)

    danke dass ihr mir geholfen habt die technischen abläufe so einigermassen einzuordnen.

    falls euch nochwas dazu einfällt ...?

    wünsche schönes wochenende, ihr findet mich im garten ► ☼ ◄

    gruss gustl