Inline Grafiken in HTML E-Mails mit Zend_Mail automatisch versenden
Ich (Ralf Eggert) stand neulich vor dem Problem, dass ich alle Grafiken in einer HTML E-Mail automatisch als Inline-Images identifizieren und dann an die E-Mail anhängen wollte. Die Grundidee zur Lösung des Problems ist es, mit einem regulären Ausdruck alle Grafiken zu finden und dann entsprechend anzuhängen. Beim Versand gab es ein paar Probleme, die ich zusammen mit Michaels Hilfe lösen konnte. Und genau deshalb findet ihr hier nun diesen kurzen Gastbeitrag.
Der Code unten zeigt ein komplettes lauffähiges Beispiel. Nach der Konfiguration wird auch gleich ein Zend_Mail Objekt erstellt und der HTML Bereich mit Inhalten bestückt. Über preg_match_all und array_filter werden alle Fundstellen in IMG Tags, im BACKGROUND Attribut sowie im Inline-CSS gefunden. Das Array mit den Ergebnissen wird dann durchlaufen. Abhängig davon, ob es sich um Grafiken auf dem Server oder externe Grafiken handelt, wird dann das entsprechende Attachment erstellt.
Zusätzlich muss im HTML Bereich der E-Mail auch jeweils der alte Verweis auf die Grafik durch den Verweis auf das Attachment ausgetauscht werden. Wichtig ist noch, dass der Typ der E-Mail auf Zend_Mime::MULTIPART_RELATED gesetzt wird. Danach kann der Versand erfolgen.
Ich hoffe, dieses Skript hilft dem einen oder anderen weiter.
<?php set_include_path(implode(PATH_SEPARATOR, array( realpath(dirname(__FILE__) . '/library'), get_include_path(), ))); date_default_timezone_set('Europe/Berlin'); require_once('Zend/Loader/Autoloader.php'); $autoloader = Zend_Loader_Autoloader::getInstance(); $mailSender = 'absender@domain.de'; $nameSender = 'Absender'; $mailRecipient = 'empfaenger@domain.de'; $nameRecipient = 'Empfaenger'; $mailSubject = 'Testmail mit inline img'; $htmlBody = '<b>html</b><br/><img src="sexy-sprite.png"><br/> <table background="error_messages.png"><tr><td>Zelle</td></tr></table> <br/><img src="http://www.fremdedomain.de/bild2.jpg">'; $textBody = 'text here'; // build mail $mail = new Zend_Mail('UTF-8'); $mail->setFrom($mailSender, $nameSender); $mail->addTo($mailRecipient, $nameRecipient); $mail->setSubject($mailSubject); // find images preg_match_all('^url\((.*)\)|src="(.*)"|background="(.*)"^iU', $htmlBody, $imageList); // combine findings $imageList = array_filter(array_merge($imageList[1], $imageList[2], $imageList[3])); // check image list if (count($imageList) > 0) { // loop through image list foreach ($imageList as $key => $value) { if (substr($value, 0, 4) == 'http') { $filePath = 'img/' . basename($value); file_put_contents($filePath, file_get_contents($value)); } else { $filePath = 'img/' . $value; } $fileName = basename($filePath); $fileType = getimagesize($filePath); // create attachment $att = $mail->createAttachment(file_get_contents($filePath)); $att->type = $fileType['mime']; $att->disposition = Zend_Mime::DISPOSITION_INLINE; $att->encoding = Zend_Mime::ENCODING_BASE64; $att->filename = $fileName; $att->id = md5($att->filename); // change body $htmlBody = str_replace($imageList[$key], 'cid:'.$att->id, $htmlBody); } } $mail->setType(Zend_Mime::MULTIPART_RELATED); $mail->setBodyText($textBody); $mail->setBodyHtml($htmlBody); $config = array('auth' => 'login', 'username' => 'absender@domain.de', 'password' => 'SMTPPASSWORD'); $mail->send(new Zend_Mail_Transport_Smtp('mail.domain.de', $config));
Top!
Genau das wollte ich heute nachrüsten. Gut dass ich noch nicht angefangen habe. 😉
Danke!
Otto
6 Mai 10 at 21:34
Danke Ralf! Hat mir sehr geholfen. PS: Habe dein Buch gelesen freu mich auf die zweite Auflage. Weiter so!
Alex
21 Sep 10 at 21:00
Vielen Dank für den super Artikel!
Anbei ein kleiner Verbesserungsvorschlag:
Hab das ganze wie oben beschrieben umgesetzt. In meiner HTML-E-Mail kommen einige Grafiken mehrmals vor (5 x.gif Platzhalter). Eine davon wird in der Mail richtig gesetzt, die restlichen 4 zeigt mit Outlook als Attachment an, weil die Schleife versucht ein und die selbe Grafik mehrmals anzuhängen.
Mit folgender Anpassung lässt sich das ganze recht einfach lösen:
Vorher:
$imageList = array_filter(array_merge($imageList[1], $imageList[2], $imageList[3]));
Nachher:
$imageList = array_filter(array_merge($imageList[1], $imageList[2], $imageList[3]));
$imageList = array_unique($imageList);
JBrooks
22 Sep 10 at 10:49
Whoa Dieser Blog sieht genau wie meine alte! Es ist auf eine ganz different subject, aber es hat so ziemlich das gleiche layout und Design.
Ausstehende Wahl der Farben!
Brustvergrößerung Vorher Nachhe
12 Jan 13 at 19:21