Om at sende nyhedsbreve
Jeg synes det er problematisk at sende mange nyhedsbreve ud. Især hvis alle nyhedsbrevene skal være unikke.
Jeg står tit i en situation hvor jeg har et site som fx BedsteVen.dk der er kodet i PHP op mod en MySQL database. For at kunne bruge al den logik der i forvejen findes på sitet, vælger jeg typisk at udsende de enkelte e-mails gennem PHP ved at kalde et script via wget.
Det er dejlig nemt at kode, men det er utrolig svært hvis man via et script skal sende mange mails (mange er mere end 300 mails).
PHP har en max_execution_time der afgør levetiden for scriptet. Typisk er den på 90 sekunder, og hvis man er længere tid om at sende end det, dør scriptet.
Jeg lavede nogle test på BedsteVen.dk, og via PHP’s mail() funktion kunne jeg over en periode på 90 sekunder udsende ca. 300 mails. Det svarer til 3,33 mails i sekundet.
Min løsning blev to-trins.
Først valgte jeg at begrænse mængden af mails til hvad serveren sikkert kunne klare:
1 2 3 4 | $count = 3 * ini_get(max_execution_time); foreach(getUsers($count) as $user) { $user->sendNewsletter(); } |
Ovenstående skulle gerne illustrere at jeg henter 3×90=270 brugere ud, og sender dem et nyhedsbrev. Det burde gøre at scriptet ikke dør undervejs.
Næste trin var at jeg i bunden af scriptet indsatte et link til scriptet igen, og kalder wget rekursivt så den blev ved med at hente siden — indtil der ikke længere er noget link. Ovenstående eksempel skal derfor udvides til at checke for at jeg ikke sender samme mail to gange.
For at få wget til at opføre sig som jeg vil, kalder jeg den på følgende måde:
1 | wget -q -erobots=off -w 5 -l 100 -r --delete-after -nd [URL] |
-q gør at der ikke kommer noget output
-erobots=off gør at den ikke henter robots.txt
-w 5 gør at wget venter 5 sek. mellem hver download
-l 100 sætter en grænse for hvor mange niveauer wget må følge
-r er rekursiv
--delete-after og -nd gør at wget rydder op efter sig selv
Om det er den smarteste måde at gøre det på ved jeg ikke rigtig. Det er én måde :)
Sende HTML-mails med billeder
At sende HTML-mails er nemt. Man skal bare sætte Content-Type til text/html. Skal man inkludere billeder i ens mail linker man bare til den på en server (<img src="http://www ..." alt=""/>). Alternativt kan man vedhæfte billederne.
Om man gør det ene eller det andet har nogle fordele og ulemper.
Når man linker til billeder
1) Man kan se om brugeren har åbnet ens mail ved at indsætte noget uniks i adressen til billederne.
2) Ens e-mails fylder mindre.
3) Man kan ændre billederne efter man har sendt e-mailen.
Når man vedhæfter billeder
1) Brugeren bliver typisk spurgt om mail-klienten skal vise billederne.
2) Ens e-mails fylder mere.
3) Brugeren har ikke fysisk modtaget hele mailen og visningen afhænger af mange ting. Er brugeren online, er serveren oppe, ligger billederne der stadig osv.
Jeg vil typisk være fortaler for at vedhæfte billederne. Det er dog lidt mere kompliceret. Fremgangsmåden er i grove træk følgende:
Fælgende headere skal sættes:
1 2 | Content-Type: multipart/mixed; boundary="-----boundary-123" |
Hvor man selv vælger hvad boundary skal være. Det skal bare være unikt.
Efterfølgende skal indholdet af ens mail splittes op i stykker der adskilles af det man har valgt som boundary. Bemærk at der tilføjes to ekstra -- til starten af ens boundary, og at der tilføjes endnu to til slutningen af den sidste.
Føste stump er HTML-dokumentet. Bemærk værdien i src.
1 2 3 4 | -------boundary-123 Content-Type: text/html <img src="cid:img123.png"> |
Sidste del af e-mailen er en base64-encodet version af billedet. For at kæde billedet sammen med img-tag’et skal Content-ID matche. Dog uden < og >.
5 6 7 8 9 10 11 12 | -------boundary-123 Content-Type: image/png Content-Transfer-Encoding: base64 Content-ID: <img123.png> [DATA] -------boundary-123-- |
Ovenstående er lidt simplificeret. Normalt ville jeg inkludere nogle flere ting. Charset m.m. Men det illustrerer godt den overordnede fremgangsmåde.

Jeg hedder Morten, og jeg har udviklet webapplikationer siden slutningen af 90'erne.