MIME::Lite and... just another Schei? encoding...
Patrick Andrieu (noreg)
- perl
Ich arbeite gerade an einem (dieser bereits weit verbreiteten) »Social Bookmarks«-Dingens und habe es soweit geschafft (JavaScript ist NICHT toll :/), dass es konsole-zumüllen-frei läuft.
Nun ja, das Ding ist ein Mix aus JavaScript und Perl, welches zum Teil mißbraucht wird, JavaScript-Ressourcen auszuliefern. Und ja, innerHTML ist leider das A und O, denn auf ellenlange appendChild-Orgien hatte ich keine Lust. So liest z.B. das eine Perl-Skript eine Datei auf meinem Server, führt die notwendigen Ersetzungen oder Anpassungen, und liefert das Ganze als innerHTML eines bestimmten Elements zurück.
Funktioniert auf Opera 9+, neueren Webkits und Geckos, und allen IE ab 6 (nur dass ich für letztere, bzw. für IE 6 und 7, noch am CSS feilen muss) -und wahrscheinlich auf allen Browsern, die getElement(s)By... verstehen.
Kurz und knapp: Die Interessenten binden auf Ihren Webseiten ein DIV ein, dem ein <script ...>-Tag folgt. Das somit eingebundene JavaScript befindet sich auf meinem Server (src="http://example.com/js/foo.js") und »holt sich« die weiteren, benötigten Datei-, CSS- und JavaScript-Ressourcen (läßt sich prima mit Firebug beobachten). Für den Nutzer des Services also relativ einfach.
Beim CSS wird superspezifisch gearbeitet, damit evtl. CSS der Seiten, auf denen der Service eingebunden wird, ihre Gene nicht vererben können. Ferner soll die Service-CSS ebensowenig die Vorgaben des Autors beeinflussen dürfen. Brignt zwar ellenlange Zeilen ala: div#x ul#y li#z a#foo span.bar - aber sicher ist sicher.
So... und nun zur Perl-Frage. Allen Anschein nach besitzt 1und1 nicht die neueste MIME::Lite-Version, denn dieser Tipp mit »encdoe()« führte zu einem Error. Dann habe ich mir mit folgendem Code geholfen:
my $email = MIME::Lite->new( 'Return-Path' => $from,
From => $from,
To => $cgi->param('recipientmail'),
Subject => $subject,
Type => 'multipart/mixed',
Encoding => '7bit');
my $body = MIME::Lite->new( Type => 'multipart/alternative',
Encoding => '7bit');
$body->attach( Type => 'text/plain; charset=UTF-8',
Encoding => 'base64',
Data => $plain
);
$body->attach( Type => 'text/html; charset=UTF-8',
Encoding => 'base64',
Data => $html);
$email->attach($body);
$email->send()
~~~;
Da ich mit meinem Mail-Client nur HTML-Mails prüfen kann (die kommen dank diesem Code fehlerfrei und ohne Schei?-Encoding-Probleme an), hier die Frage: ist das für Empfänger, die nur text/plain akzeptierenm, auch OK? Gerne würde ich eine Testseite vorstellen, doch noch bin ich soweit. Vielleicht, vor allem Alexander(HH) als Verfechter von MIME::Lite, kann was dazu sagen?
Ach ja, zum Thema »JavaScript ist nicht toll«: das ist sicher nicht die Schuld von JavaScript... aber das aggressive Bilder-Caching von vor allem IEs und Opera habe mich an bild.onload mehrere Stunden zweifeln lassen...
MfG,
Patrick (noreg), als bald schlafengehender Schrat letztens bekannt
moin,
[..] Frage: ist das für Empfänger, die nur text/plain akzeptierenm, auch OK?
Poste doch mal eine solch erstellte Maildatei, ich guck mir das an!
Gerne würde ich eine Testseite vorstellen, doch noch bin ich soweit.
Mach ;-)
Patrick (noreg), als bald schlafengehender Schrat letztens bekannt
Schläfst Du mit Mütze?
Viele Grüße,
Horst Schläfer (Name geändert)
Hi,
Gerne würde ich eine Testseite vorstellen, doch noch bin ich soweit.
Aber jetzt...
Mach ;-)
Bitte sehr: http://www.atomic-eggs.com/cwi/cwi_5.shtml#ende
Schläfst Du mit Mütze?
Mit oder ohne... hauptsache schlafen!
Schrat
Mir fehlen hier einige wichtige Dinge.
① Die Werte für die Header Return-Path, From, To müssen RFC-konform kodiert werden.
From => Email::Address->new('Verteiler', $from_address)->format,
② Subject muss kodiert werden.
use Encode qw(encode);
⋮
Subject => encode('MIME-Header', $subject),
③ Data muss kodiert werden, ansonsten gibt es den Fehler Wide character in subroutine entry at .../MIME/Lite.pm line 2264.
Data => encode('UTF-8', $plain),
④ Da die Mail nicht von einem Menschen generiert wird, Header gemäß RFC 3834 §5.2 setzen:
'Auto-Submitted' => 'auto-generated',
⑤ Wie behandelst du Auslieferung an IDN (a.k.a. "Umlaut-Domains")?
Soweit die Pflicht. Für die Kür:
⑥ Als Content-Transfer-Encoding ist 8bit für die text/*-Teile vorzuziehen.
$body->attach(
Encoding => '8bit',
⑦ Kann der Organization-Header sinnvoll verwendet werden? Falls ja, bitte einfüllen.
Werden die o.g. Kodierungen vorgenommen, produziert MIME::Lite standardkonforme Nachrichten. Dementsprechend sieht das Ergebnis in Klartextansicht in KMail 1.13.2 sehr gut aus.
Hallo CPAN!
Mir fehlen hier einige wichtige Dinge.
Deswegen poste ich ja ;)
① Die Werte für die Header Return-Path, From, To müssen RFC-konform kodiert werden.
From => Email::Address->new('Verteiler', $from_address)->format,
> ⑦ Kann der Organization-Header sinnvoll verwendet werden? Falls ja, bitte einfüllen.
Obige Punkte verstehe ich nicht ganz... Was ist »Verteiler«, was ist ein »Organization-header«?
> ② Subject muss kodiert werden.
> ~~~perl
> use Encode qw(encode);
> ⋮
> Subject => encode('MIME-Header', $subject),
>
[x] Done!
③ Data muss kodiert werden, ansonsten gibt es den Fehler Wide character in subroutine entry at .../MIME/Lite.pm line 2264.
Data => encode('UTF-8', $plain),
Damit kann ich zwar im Quelltext der Mail (Datei->Eigenschaften->Details->Quelltext bei Windows Mail, dem Outlook-Express-Nachfolger) dem Plaintext-Part lesen, doch erhalte ich meine Umlaute als Zeichensalat... und Windows-Mail zeig nicht mehr »Unicode (UTF-8)« in der Mail-Titelleiste.
> ④ Da die Mail nicht von einem Menschen generiert wird, Header gemäß RFC 3834 §5.2 setzen:
> ~~~perl
> 'Auto-Submitted' => 'auto-generated',
>
[x] Done. Aber: Erscheint es irgendwo im Mail-Header? Ich kann es im Quelltext nirgends entdecken.
⑤ Wie behandelst du Auslieferung an IDN (a.k.a. "Umlaut-Domains")?
Die behandle ich derzeit gar nicht. Das JavaScript blockt Umlaute in den Mail-Adressen ab.
⑥ Als Content-Transfer-Encoding ist 8bit für die text/*-Teile vorzuziehen.
$body->attach(
Encoding => '8bit',
Das hat zumindest was den Zeichensalat angeht, nichts geändert.
Die Testseite: <http://www.atomic-eggs.com/cwi/cwi_5.shtml#ende>. Ich habe im Titel extra noch »äöüß« notiert. Dieser Seite charset ist ISO-8859-1. Die Datei, die als innerHTML zum Füllen des DIV mit der ID »bms« fungiert, ist in UTF-8. Aber...: Auf einer weiteren Testseite, die UTF-8-kodiert ist, habe ich auch das Skript eingebunden - und die Umlauten kommen, ohne base64 im Perl-Skript, ebenso als Müll an. Das scheint also nicht die Ursache zu sein.
VG,
Patrick (noreg)
From => Email::Address->new('Verteiler', $from_address)->format,
> Was ist »Verteiler«
Ist das mit dem Lesen der Doku von Email::Address nicht klar? Das ist der phrase-Teil einer formatierten Adresse, bspw. »Patrick Andrieu« in »Patrick Andrieu <kontakt@example.org>«.
> was ist ein »Organization-header«?
Der Header namens Organization, siehe RFCs 2076 und 1036.
> > ③ Data muss kodiert werden, ansonsten gibt es den Fehler Wide character in subroutine entry at .../MIME/Lite.pm line 2264.
> Damit kann ich zwar im Quelltext der Mail (Datei->Eigenschaften->Details->Quelltext bei Windows Mail, dem Outlook-Express-Nachfolger) dem Plaintext-Part lesen, doch erhalte ich meine Umlaute als Zeichensalat... und Windows-Mail zeig nicht mehr »Unicode (UTF-8)« in der Mail-Titelleiste.
> > ⑥ Als Content-Transfer-Encoding ist 8bit für die text/\*-Teile vorzuziehen.
> Das hat zumindest was den Zeichensalat angeht, nichts geändert.
Ja, was kann ich dazu sagen… Ich hab kein Windows, kann nicht nachstellen und daher deine Aussagen dazu nicht einordnen – keine Ahnung, was da konkret passiert.
Ignoriere den Rat auf eigenes Risiko.
> > ④ Da die Mail nicht von einem Menschen generiert wird, Header gemäß RFC 3834 §5.2 setzen:
> [x] Done. Aber: Erscheint es irgendwo im Mail-Header? Ich kann es im Quelltext nirgends entdecken.
Das habe ich gar nicht überprüft und mich drauf verlassen, dass der Header verbatim übernommen wird. MIME::Lite verschluckt ihn unanständigerweise. Ich habe keine Lust, mit Legacysoftware herumzupfriemeln, wenn es die Modulfamilie Email::\* gibt.
> Die Testseite: <http://www.atomic-eggs.com/cwi/cwi_5.shtml#ende>. Ich habe im Titel extra noch »äöüß« notiert. Dieser Seite charset ist ISO-8859-1. Die Datei, die als innerHTML zum Füllen des DIV mit der ID »bms« fungiert, ist in UTF-8. Aber...: Auf einer weiteren Testseite, die UTF-8-kodiert ist, habe ich auch das Skript eingebunden - und die Umlauten kommen, ohne base64 im Perl-Skript, ebenso als Müll an. Das scheint also nicht die Ursache zu sein.
Sorry, was hat die Webseite mit dem Erstellen der Mailnachricht zu tun?
From => Email::Address->new('Verteiler', $from_address)->format,
> > Was ist »Verteiler«
> Ist das mit dem Lesen der Doku von Email::Address nicht klar?
Nein... Also, nichts ist klar. Außerdem stehen die Module der Email-Familie bei 1und1 nicht zur Verfügung...
> Das ist der phrase-Teil einer formatierten Adresse, bspw. »Patrick Andrieu« in »Patrick Andrieu <kontakt@example.org>«.
Aargh! Ich lebe, seit ich vor drei oder vier Jahren entsprechende Vorsichtsmaßnahmen getroffen habe, mit allen \_neuen\_ Adressen (wie diese hier) weitestgehend Spamfrei. Mensch, example.com hätte es auch getan!
Jetzt kann ich einen Ex-Kollege aus der Moderation darum bitten, die Adresse zu faken, sobald der Thread im Archiv ist...
Aber zurück zum Thema. Das mache ich händisch im Skript.
> > was ist ein »Organization-header«?
> Der Header namens Organization, siehe RFCs 2076 und 1036.
Scheint optional zu sein, so weit ich aus RFC 1036 entnehmen kann, also who cares?
> [Zeichensalat]
> Ja, was kann ich dazu sagen… Ich hab kein Windows, kann nicht nachstellen und daher deine Aussagen dazu nicht einordnen – keine Ahnung, was da konkret passiert.
Deswegen unter anderem die Testseite, mit welcher Du Dich selbst eine Mail hättest schicken können.
Mittlerweile musste ich auch das Encoden des Subjects entfernen, da auch dort Zeichensalat ankam, falls ein Name Sonderzeichen entählt. Der Subject lautet nämlich: »Eine Linkempfehlung von Name (E-Mail)«. Gut, könnte ich zur Not umformulieren...
Mittlerweile habe ich einige weiteren Tests durch, hier die Ergebnisse:
Text- und HTML-Mails:
Windows Mail (OE-Nachfolger): Umlaute in Nachricht korrekt, Umlaute in Subjekt korrekt.
Windows Live Mail (Unbedienbar): Umlaute in Nachricht korrekt, Umlaute in Subjekt korrekt.
Webmail-Interface Yahoo: Umlaute in Nachricht korrekt, Umlaute in Subjekt korrekt.
Webmail-Interface 1und1 neu: Umlaute in Nachricht korrekt, Umlaute in Subjekt mit Zeichensalat.
Webmail-Interface 1und1 alt: Umlaute in Nachricht korrekt, Umlaute in Subjekt mit Zeichensalat.
Webmail-Interface GMX: Umlaute in Nachricht korrekt, Umlaute in Subjekt mit Zeichensalat.
> Ignoriere den Rat auf eigenes Risiko.
Werde ich wohl oder übel tun müssen, oder?
> > Die Testseite: <http://www.atomic-eggs.com/cwi/cwi_5.shtml#ende>. (...)
> Sorry, was hat die Webseite mit dem Erstellen der Mailnachricht zu tun?
Das hat insofern damit zu tun, dass man es testen kann (dafür ist es ja eine Testseite)... ;)
Zweitens hatte ich ja vergessen zu erwähnen, dass das was bei Perl ankommt bereits UTF8-kodiert ist. Das JavaScript, das für den Aufruf des Perl-Skripts beim Absenden zuständig ist, benutzt zudem encodeURIComponents(foobar).
VG,
Patrick
Heute vormittag ein paar Screenshots gemacht...
Windows Live Mail (Unbedienbar): Umlaute in Nachricht korrekt, Umlaute in Subjekt korrekt.
Und so sieht die Nachritenliste (wie bei Windows Mail auch) aus: http://www.atomic-eggs.com/z_testdir/shots/wlm.gif.
Webmail-Interface Yahoo: Umlaute in Nachricht korrekt, Umlaute in Subjekt korrekt.
Nicht immer: http://www.atomic-eggs.com/z_testdir/shots/yahoo.gif. Hier interessant: »Gök(ök)« wird verhunzt, »Gök the ög« oder »Sherlök« nicht.
Bei den zwei letzten der Liste hatte ich noch encode('UTF-8', $subject) im Programm stehen.
Webmail-Interface GMX: Umlaute in Nachricht korrekt, Umlaute in Subjekt mit Zeichensalat.
Bild: http://www.atomic-eggs.com/z_testdir/shots/gmx.gif
Mittlerweile bin ich fast überzeugt, dass der Murks seitens der Webmail-Anbieter passiert. Doch ärgerlich ist es schon, wenn die Mails bei deren Nutzern so ankommen... - Gerade in der Liste sieht es besch... aus :(
P.
Re!
Mittlerweile bin ich fast überzeugt, dass der Murks seitens der Webmail-Anbieter passiert.
Nach weiteren Versuchen heute nachmittag:
$obigeAusage =~ s/fast/fest davon/;
Ein PHP-Mailer, den ich auf Kundenseiten einsetze, bei deren Hoster Perl nicht zur Verfügung steht, habe ich heute getestet. Gebe ich als Betreff vor: »Kontakt über Kundenseite-Formular«, kommt beim »ü« bei den vorhin genannten Webmailern (nicht bei den Mail-Clients, zumindest nicht bei denen, die ich unter Windows einsetze), Zeichenmüll an.
Nun habe ich die Wahl zwischen:
• alles lassen, wie es in meinem Vorposting aussieht
• oder: jeder Parameter wie der Webseiten-Titel und
die User-Eingaben: Name, Empfänger-Name, Message durch
decode('UTF-8', $param)
zu behandeln, um danach jeweils:
Data => encode('iso-8859-1', $html)
/ $plain bei
der selben charset-Angabe bei »Type« einzugeben.
Dann kommt es sowohl bei den fraglichen Webmailern als auch bei den Windows-Mail-Clients korrekt an - bis auf evtl. Sonderzeichen im »document.title«, Namen und/oder Nachricht, die es in iso-8859-1 nicht gibt - diese erscheinen dann als Fragezeichen.
Ich will mit meinem Service nicht international sein, schön wär's gewesen, aber anscheinend geht es aufgrund dieser allen Anschein nach miserabel programmierter Webmailer nicht anders. Seitzeichen (das ist übrigens der Anbieter, von dem ich den Anstoß hatte, was Eigenes zu machen), macht es nicht anders: iso-8859-x anstatt utf-8.
Die Frage lautet nur: Was ist besser? Die perfektionistische Variante (UTF-8), die in Kauf nimmt, dass Nutzern von Webmailern Zeichenmurks erhalten, oder die rationellere, die einkalkuliert, dass die meisten User hierzulanden sitzen werden, und daher eher auf iso-8859-x setzt?
P.
Meine Güte, du machst dir das Leben vielleicht unnötig schwer. Produzierst du falsch kodierte Mails? Vermutlich ja. (Zeige mal den Rückgabewert von $email->as_string
vor dem Versand. Schade, dass es keinen automatischen Validator für Nachrichten/MIME analog zu HTML und CSS gibt.) Dann musst auch in Kauf nehmen, dass jeder Mailclient den Datenmüll auf eigene Art handhabt. Da bist du nur am Verlieren. Es hilft auch kein anderes Encoding als UTF-8.
Die Lösung ist, es einfach richtig zu machen, statt an sekundären Problemen herumzupfriemeln. An deiner Stelle hätte ich schon längst die Libraries modernisiert. Wenn du Dateien hochladen/mit Perl ausführen kannst, kannst du auch immer Module installieren.
Meine Güte, du machst dir das Leben vielleicht unnötig schwer.
Das merke ich... Wollte eigentlich längst fertig sein :(
Produzierst du falsch kodierte Mails? Vermutlich ja. (Zeige mal den Rückgabewert von
$email->as_string
vor dem Versand.
Falsch kodiert? Don't know...
$email->as_string
=> Du meinst diese eine Methode von LWP::UserAgent?
Hm, muss ich mal gucken, wie. Das Skript schickt die Mail und gibt ein Bild zurück. Nochmals auch für diejenigen die jetzt einsteigen, falls es doch jemand außer uns zweien gibt, der hier noch mitliest ;)
Das was auf der Testseite wie ein Formular aussieht, ist eigentlich gar keins. Beim Klick auf »Absenden« wird eine JS-Funtkion aufgerufen, dessen hier relevante Part der folgdende ist:
gE('spic').src = pf+'/cgi-bin/bmmail.pl?stamp='+parseInt(new Date().getTime()/1000)
+'&page='+encodeURIComponent(lh)
+'&title='+encodeURIComponent(document.title)
+'&sendername='+encodeURIComponent(gE('sname').value)
+'&recipientname='+encodeURIComponent(gE('rname').value)
+'&sendermail='+encodeURIComponent(gE('smail').value)
+'&recipientmail='+encodeURIComponent(gE('rmail').value)
+'&message='+encodeURIComponent(gE('message').value);
Die hier per GET verschickte Parameter lese ich mit der Methode param() des CGI-Moduls aus. Durch encodeURICompenent() kommt es also bereits als UTF-8 an, weswegen die Angaben encode('MIME-Header', $subject
) und fürs Body encode('UTF-8', $data)
nur Zeichenmurks produziert hatten.
Dann musst auch in Kauf nehmen, dass jeder Mailclient den Datenmüll auf eigene Art handhabt. Da bist du nur am Verlieren. Es hilft auch kein anderes Encoding als UTF-8.
Die Webmailer machen Murks. GMX ruft zum Beispiel den Mail-Inhalt (body) in einem IFrame auf -> dieser Inhalt wird korrekt dargestellt. Die Header-Angaben zum Absender, Empfänger und Betreff aber werden außerhalb dieses IFrames angezeigt und enthalten bei Sonderzeichen Müll.
Seitzeichen (seitzeichen.de) benutzt einen PHP-Mailer, beim Mail-Leser kommt iso-8859-1: Gibt man in deren »Formular« im Namen oder im Text Sonderzeichen wie z.B. ‰ an, werden diese in den Mails als Fragezeichen dargestellt.
Wenn ich jetzt durch die Methode decode() alle Parameter dekodiere, und dann iso-8859-1 ausliefere, erhalte ich die selben Ergebnisse wie bei Seitzeichen [1]: Korrekte Darstellung und ansonsten Fragezeichen bei evtl. Sonderzeichen - beim Letzteren aber leider »Wide character...« im Errorlog...
Die Lösung ist, es einfach richtig zu machen, statt an sekundären Problemen herumzupfriemeln.
Also UTF-8 ausliefern, und damit leben, dass GMX-User (und sicher Nutzer anderer Webmailer) im Sendernamen (From:) und Betreff Unleserliches erhalten?
An deiner Stelle hätte ich schon längst die Libraries modernisiert. Wenn du Dateien hochladen/mit Perl ausführen kannst, kannst du auch immer Module installieren.
Meine Versuche, bei 1&1 Module nachzuinstallieren sind kläglich gescheitert, permission denied hier, permission denied dort... In einem langen Thread im Archiv müsste alles noch dokumentiert sein ;) Ich kann also nur ins eigene cgi-bin kopieren...
P.
[1] Der code hierzu:
Für jeden Parameter, zB:
decode('UTF-8',$cgi->param('sendername'))
MIME::Lite:
my $email = MIME::Lite->new( 'Return-Path' => $from,
From => encode('MIME-Header',$from),
To => $cgi->param('recipientmail'),
Subject => encode('MIME-Header',$subject),
Type => 'multipart/mixed',
Encoding => '8bit'
);
my $body = MIME::Lite->new( Type => 'multipart/alternative',
Encoding => '8bit'
);
$body->attach( Type => 'text/plain; charset=iso-8859-1',
Data => encode('iso-8859-1', $plain)
);
$body->attach( Type => 'text/html; charset=iso-8859-1',
Data => encode('iso-8859-1', $html)
);
$email->attach($body);
$email->send();
Erstaunlicherweise wird hier trotz encode('MIME-Header', $foo)
bei GMX alles korrekt angezeigt. Lasse ich mir von Windows Live Mail den Quelltext anzeigen, sehe ich im Header:
From: =?UTF-8?B?4oCwLVRlc3Qg?=patrickx@example.com
To: patricky@example.com
Subject: =?UTF-8?B?RWluZSBMaW5rZW1wZmVobHVuZyB2b24g4oCwLVRlc3Qg?=(patrickx@example.com)
Zum Vergleich nochmals der Code meiner »UTF-8-Variante«:
Kein »decode()«,
my $email = MIME::Lite->new( 'Return-Path' => $from,
From => $from,
To => $cgi->param('recipientmail'),
Subject => $subject,
Type => 'multipart/mixed',
Encoding => '7bit',
'Auto-Submitted' => 'auto-generated'
);
my $body = MIME::Lite->new( Type => 'multipart/alternative',
Encoding => '8bit'
);
$body->attach( Type => 'text/plain; charset=UTF-8',
Data => $plain
);
$body->attach( Type => 'text/html; charset=UTF-8',
Data => $html
);
$email->attach($body);
$email->send();
From: ‰-Test patrickx@example.com
To: patricky@example.com
Subject: Eine Linkempfehlung von ‰-Test (patrickx@example.com)
‰-Test wird aber korrekt als ‰-Test angezeigt (Mail-Ansicht)
Re!
$email->as_string
=> Du meinst diese eine Methode von LWP::UserAgent?
MIME::Lite bietet auch sowas, na sowas ;)
Ergebnis:
Content-Transfer-Encoding: 7bit Content-Type: multipart/mixed; boundary="_----------=_1270560591270050" MIME-Version: 1.0 X-Mailer: MIME::Lite 3.01 (F2.74; A1.74; B3.07; Q3.07) Date: Tue, 6 Apr 2010 15:29:51 +0200 Return-Path: ‰-Test From: ‰-Test To: patricky@example.com Subject: Eine Linkempfehlung von ‰-Test (patrickx@example.com) This is a multi-part message in MIME format. --_----------=_1270560591270050 Content-Transfer-Encoding: 8bit Content-Type: multipart/alternative; boundary="_----------=_1270560591270051" MIME-Version: 1.0 X-Mailer: MIME::Lite 3.01 (F2.74; A1.74; B3.07; Q3.07) Date: Tue, 6 Apr 2010 15:29:51 +0200 This is a multi-part message in MIME format. --_----------=_1270560591270051 Content-Disposition: inline Content-Length: 550 Content-Transfer-Encoding: binary Content-Type: text/plain; charset=utf-8 Hallo %-Test! ‰-Test (patrickx@example.com) möchte Ihnen diesen Link empfehlen: Atomic Eggs :: Wenn Sie einen Webdesigner suchen... öäüß (http://www.atomic-eggs.com/cwi/cwi_5.shtml#ende) Nachricht von ‰-Test: Man muss unterscheiden können zwischen % und ‰, mon cher mûr du çon! Wichtiger Hinweis: Die Identität des Absenders dieser E-Mail wurde von Atomic Eggs nicht überprüft. Atomic Eggs stellt lediglich die Schnittstelle zur Verfügung, mit deren Hilfe Internetnutzer Linkempfehlungen an Freunde und Bekannte verschicken können. --_----------=_1270560591270051 Content-Disposition: inline Content-Length: 1036 Content-Transfer-Encoding: binary Content-Type: text/html; charset=utf-8
Ergebnis:
Bei mir kam der Code (am 1.) base64 kodiert an - Thunderbird zeigt den auch richtig als utf-8 an.
Struppi.
Bei mir kam der Code (am 1.) base64 kodiert an - Thunderbird zeigt den auch richtig als utf-8 an.
Und heute?
Zu dem zuvor geposteten Ergebnis: Ich habe einfach print $cgi->header() notiert, um mir das ausgeben zu lassen. Klar, dass ohne Charset-Angabe die Zeichen so sind, wie ich es eben gepostet habe. Bei meinen beiden Windows-Mail-Clients kommt es korrekt an, und es wird »Unicode (UTF-8)« in der Titelleiste angezeigt, wenn man die Mail öffnet. Lediglich in der Liste wird das ‰-Zichen entfernt.
P.
Ach du Schreck, das ist ja wohl mal gründlich in die Hose gegangen.
Ich habe die Zeilenumbrüche eingefügt und dann bemerkt, dass die Zeichen mehrfach kodiert sind, nämlich zuerst Windows-1252 und danach UTF-8. Siehst du, wieviel informativer das ist als deine Angabe »Zeichensalat«? :-) Jetzt weiß ich zwar immer noch nicht, ob das deine vorinstallierte Asbach-Uralt-Version von MIME::Lite macht (wahrscheinlich, denn früher im Thread haben wir ja etabliert, dass wir beide ein unterschiedliches Verhalten bezüglich encode von Feld Data haben), und/oder dein Copy/Paste noch eine Schuld oder Mitschuld hat. (Weißt du schon, wie man Daten mittels Dump inspiziert, der Perls eventuell vorhandene eigene Ausgabekodierung für Dateihandles, inklusive STDOUT, sowie eventuell implizite Upgrades im Zusammenhang mit dem SvUTF8-Flag unterläuft? Eine Möglichkeit ist die Funktion Dump aus Devel::Peek.)
Ich kann also nur ins eigene cgi-bin kopieren...
Ich bitte dich, mal die aktuelle Library zu installieren, erhältlich von http://search.cpan.org/dist/MIME-Lite/, und noch mal da capo durchprobieren. Da es kein XS-Modul ist, funktioniert die primitive Holzhammermethode:
1. Extrahiere das Archiv.
2. Kopiere lib/MIME/Lite.pm mit Verzeichnisstruktur in dein cgi-bin. Das Ergebnis ist eine Datei .../cgi-bin/lib/MIME/Lite.pm.
3. Führe im cgi-bin das folgende Testprogramm aus:
use lib 'lib';
use CGI qw();
use MIME::Lite qw();
my $c = CGI->new;
$c->header('text/plain');
$c->print(join "\t", MIME::Lite->VERSION, $INC{'MIME/Lite.pm'});
Als Ausgabe erhältst du »3.027 lib/MIME/Lite.pm«.
Ach du Schreck, das ist ja wohl mal gründlich in die Hose gegangen.
Meinst Du? :)
Ich habe die Zeilenumbrüche eingefügt und dann bemerkt, dass die Zeichen mehrfach kodiert sind, nämlich zuerst Windows-1252 und danach UTF-8.
Hm, siehe meine Ergänzung in der letzten Antwort an Struppi: für die Ausgabe habe ich im Skript lediglich einen print $cgi->header() ohne charset-Angabe notiert. Mit charset=uft-8 gäbe es sicher keine Probleme.
Windows-1252 kommt sicher von der Copy&Paste-Orgie, schließlich wollte ich die Mail-Adresse noch faken: aus dem Browser kopiert, im Editor eingefüft (der hat blöderweise per default 1252), Adressen geändert, im Posting gepasted.
Devel::Peek
Zumindest ist das Modul vorhanden... Ist ja Core...
[MIME::Lite 3.027]
Ich hab's etwas anders gemacht, mittels ppm erstmals bei mir installiert, dann Lite.pm direkt in /cgi-bin/MIME/ kopiert.
Erste Überraschung:
»Can't locate Email/Date/Format.pm in @INC (...)«
Also auch dieses Modul in cgi-bin/Email/Date kopiert...
Jetzt lasse ich mir die Version im HTML-Part der Mails ausgeben, und erhalte : 3.027 :)
Doch ändert es nichts an die GMX-Darstellung :(
P.
Doch ändert es nichts an die GMX-Darstellung :(
Mangels GMX-Zugang kann ich nicht selber testen, daher sanity check: ich möchte so eine korrekt kodierte, von M::L 3.027 verfasste Email noch einmal stringifiziert sehen, die Salat bei der Darstellung in GMX macht. Bitte gib mir sowohl »print $email->as_string
« als auch »Devel::Peek::Dump($email->as_string)
« (wird wohl ziemlich viel und schwurbelig) und vermeide Verunreinigungen durch den Texteditor zwecks Zensur.
Ich denke, es ist okay, einmal die Forumsregel zu ignorieren, relevantes Material immer hier zu posten. Ich weiß, du möchtest Spambots nicht aufmerksam machen. Ich kann pastebin.com empfehlen, da kann man ein Ablaufdatum von einem Monat einstellen. Sage dann die URL ohne Verlinkung.
PS: Promillezeichen war eine sehr gute Idee, weil es ein Zeichen außerhalb von Latin1 ist.
Mangels GMX-Zugang kann ich nicht selber testen, daher sanity check: ich möchte so eine korrekt kodierte, von M::L 3.027 verfasste Email noch einmal stringifiziert sehen, die Salat bei der Darstellung in GMX macht. Bitte gib mir sowohl »
print $email->as_string
« als auch »Devel::Peek::Dump($email->as_string)
« (wird wohl ziemlich viel und schwurbelig) und vermeide Verunreinigungen durch den Texteditor zwecks Zensur.
Ich denke, es ist okay, einmal die Forumsregel zu ignorieren, relevantes Material immer hier zu posten. Ich weiß, du möchtest Spambots nicht aufmerksam machen. Ich kann pastebin.com empfehlen, da kann man ein Ablaufdatum von einem Monat einstellen. Sage dann die URL ohne Verlinkung.
PS: Promillezeichen war eine sehr gute Idee, weil es ein Zeichen außerhalb von Latin1 ist.
Trotz mehr Promille hatte ich eine bessere Idee. Anstatt mit dem Editor herum zu pfuschen, poste hier einen perfekt encodeURIComponent-encoded URI, so wie er vom JavaScript generiert wird (ich habe es der Einfachheit halber aus den Logfiles 'rausgefischt) mit gefakten E-Mail-Adressen. Ist doch egal, die Links pointen auf Kopien des Originalskripts, es wird keine Mail verschickt (Mailserver von 1und1 scheint heute seit ca.13:oo Uhr eh down zu sein):
Mit print $cgi->header(-type => 'text/plain', -charset => 'utf-8');
:
Für Devel::Peek, musste leider in die eigens hierfür angelegte error-Datei schauen, denn wie es scheint, werden die Ausgabe an STDERR geschickt? Jedenfalls, wenn ich den Beat-Errordatei-Trick nicht anwende:
BEGIN {
use CGI::Carp qw(carpout);
open(LOG, ">>errorCPAN") or die;
carpout(*LOG);
}
komme ich an die Ausgabe nicht heran - mangels Zugriffs auf die error.log bei 1und1.
Also bitte hier lang.
Und hier die Ausgabe mit print $cgi->header(-type => 'text/plain');
(ohne Angabe zum Charset):
Hinweis fürs Archiv: Diese Links werden nicht mehr funktionieren, da ich die Scripts nach den Tests löschen werde.
P.
Danke für die Mühe! Ich habe mir den Dump angeschaut.
Ich bestätige, die beiden text/*-Teile sind MIME-konform (und sehen gut aus im Mailclient).
Die Top-Level-Header sind nicht konform. Es steht dort (Oktette kodiert als UTF-8):
Return-Path: ‰-Test <patrickx.com>
From: ‰-Test <patrickx.com>
Subject: Eine Linkempfehlung von ‰-Test (patrickx.com)
Es muss aber nach RFC 2047 bspw. so aussehen:
Return-Path: =?UTF-8?B?4oCwLVRlc3Qg?=<patrickx.com>
From: =?UTF-8?B?4oCwLVRlc3Qg?=<patrickx.com>
Subject: =?UTF-8?B?RWluZSBMaW5rZW1wZmVobHVuZyB2b24g4oCwLVRlc3Qg?=(patrickx.com)
Das erreichst du, wie in meinem ersten Posting geschrieben, mit Encode::encode('MIME-Header', $subject)
, analog $from usw. Wenn du das änderst, ist die Mailnachricht vollständig konform. Wenn es dann noch Darstellungsprobleme geben sollte, hat die andere Partei schuld.
Danke für die Mühe!
Ich danke _Dir_ für die Mühe!
Bin vor einer halben Stunde von einem Transportaufrag nach Torino zurück: Donnerstag früh hin mit Röntgengerät, abends angekommen, Gestern Röntgengerät in einem Turiner Krankenhaus ausgetauscht (haben Techniker gemacht, ich 'abe gar keine Ausbildung für sowas), altes Gerät mitgenommen und zurück. Übernachtung im 4-Sterne-Hotel auf Kosten des Auftraggebers! Solche Aufträge hätte ich gerne jede Woche, bitte schön!
Ich antworte Dir nach einer Mütze Schlaf ;)
Schrat
Hallo CPAN,
Die Top-Level-Header sind nicht konform. Es steht dort (Oktette kodiert als UTF-8):
Return-Path: ‰-Test <patrickx.com>
From: ‰-Test <patrickx.com>
Subject: Eine Linkempfehlung von ‰-Test (patrickx.com)
Ja, weil durch encodeURICompenent() im JavaScript bereits UTF-8 bei Perl ankommt!
Es muss aber nach RFC 2047 bspw. so aussehen:
Return-Path: =?UTF-8?B?4oCwLVRlc3Qg?=<patrickx.com>
From: =?UTF-8?B?4oCwLVRlc3Qg?=<patrickx.com>
Subject: =?UTF-8?B?RWluZSBMaW5rZW1wZmVobHVuZyB2b24g4oCwLVRlc3Qg?=(patrickx.com)
Ich weiß es jetzt nach Deinen letzten Hinweisen, aber:
Das erreichst du, wie in meinem ersten Posting geschrieben, mit
Encode::encode('MIME-Header', $subject)
,
Hatten wir ja schon, das ergibt doppeltgemoppeltes Encoding! Warum? Weil die Strings bereits UTF-8 sind, wie erwähnt wegen encodeURIComponent()... Und encode('MIME-header, $foo) wandelt auch in UTF-8 um, alore l'abbiamo, il doppeltes Encoding, il Schei?-Encoding!
Abärre ich habe es jetzt dank Deiner Tipps geschafft, dass alles (Header und Body) in allen Mail-Clients und Webmail-Interfaces, die ich zum Testen habe, korrekt ankommt... Die Lösung: erst UTF-8 decoden, dann MIME-header encoden - und zwar nur die kritischen Header-Teile:
Ohne decode und ohne encode('MIME-header', $from) zeigen GMX und die 1und1 Interfaces bei ‰-Test als gewähltem Sendernamen:
‰-Test
Yahoo und die Windows-Clients zeigten korrekt:
‰-Test
Ohne decode und mit encode('MIME-header', $from) zeigen _alle_ Clients:
â°-Test
Mit decode und mit encode('MIME-header', $from) bringen _alle_ Clients das korrekte Ergebnis, nämlich:
‰-Test
Hier der komplette Code:
#!/usr/bin/perl -w
##### Atomic Eggs #####
BEGIN {
use CGI::Carp qw(carpout);
open(LOG, ">>error") or die;
carpout(*LOG);
}
use strict;
use lib '.';
use CGI;
use MIME::Lite;
use Encode qw(encode decode);
my $cgi = CGI->new();
my $pic = '/pics/sb/ok.gif';
if(scalar($cgi->param())!=8) {
print $cgi->header(-Status => 403); exit
} elsif(length(decode('UTF-8',$cgi->param('sendername'))) > 50 || length(decode('UTF-8',$cgi->param('recipientname'))) > 50 || length(decode('UTF-8',$cgi->param('message'))) > 250) {
print $cgi->header(-Status => 403); exit
} else {
for ($cgi->param('recipientmail'), $cgi->param('sendermail')) {
my $tmp1 = my @tmp1 = split(/\,/, $_); my $tmp2 = my @tmp2 = split(/\\n/, $_);
if ($tmp1> 1 || $tmp2 > 1) { print $cgi->header(-Status => 403); exit }
if ($_ =~ /&b?cc=/i) { print $cgi->header(-Status => 403); exit }
if (length($_) > 100) { print $cgi->header(-Status => 403); exit }
}
}
my $mlVersion = join(" ", MIME::Lite->VERSION, $INC{'MIME/Lite.pm'});
my $sender = $cgi->param('sendername') ? $cgi->param('sendername').' ('.$cgi->param('sendermail').')' : $cgi->param('sendermail');
my $senderForSubjectline = $cgi->param('sendername') ? decode('UTF-8',$cgi->param('sendername')).' ('.$cgi->param('sendermail').')' : $cgi->param('sendermail');
my $from = $cgi->param('sendername') ? decode('UTF-8',$cgi->param('sendername')).' <'.$cgi->param('sendermail').'>' : $cgi->param('sendermail');
my $mailTo = $cgi->param('recipientmail');
my $subject = 'Eine Linkempfehlung von '.$senderForSubjectline;
my $headline1 = $cgi->param('recipientname') ? 'Hallo '.$cgi->param('recipientname').'!' : 'Hallo!';
my $headline2 = $sender.' möchte Ihnen diesen Link empfehlen:';
my $headline3 = $cgi->param('sendername') ? 'Nachricht von '.$cgi->param('sendername').':' : 'Nachricht:';
my $plainTextMessage = $cgi->param('message') ? $headline3.$/.$cgi->param('message') : '------';
my $htmlMessage = $cgi->param('message') ? qq~<h3>$headline3</h3>\n<p>~ . $cgi->param('message') ."</p>" : " ";
my $hlink = $cgi->param('title') ne '' ? '<a href="'.$cgi->param('page').'">'.$cgi->param('title').'</a>' : '<a href="'.$cgi->param('page').'">'.$cgi->param('page').'</a>';
my $note = 'Wichtiger Hinweis: ';
my $disclaimer = 'Die Identität des Absenders dieser E-Mail wurde von Atomic Eggs nicht überprüft.'.$/.'Atomic Eggs stellt lediglich die Schnittstelle zur Verfügung, mit deren Hilfe Internetnutzer Linkempfehlungen an Freunde und Bekannte verschicken können.';
my $plain = $headline1.$/.$/.$headline2.$/.$/.$cgi->param('title').' ('.$cgi->param('page').')'.$/.$/.$plainTextMessage.$/.$/.$/.$note.$disclaimer;
my $html = qq~<body style="font-family:Arial, sans-serif">\n
<h1>$headline1</h1>\n
<h2>$headline2</h2>\n
<p><strong>$hlink</strong></p>\n
<p>$htmlMessage</p>
<p style="margin-top: 100px; font-size:10px"><b>$note</b>$disclaimer</p>
<img src="http://www.atomic-eggs.com/pics/atomicegg.gif"><br>
ML-VERSION: $mlVersion
</body>~;
my $email = MIME::Lite->new( 'Return-Path' => $from,
From => encode('MIME-Header', $from),
To => $cgi->param('recipientmail'),
Subject => encode('MIME-Header', $subject),
Type => 'multipart/mixed',
Encoding => '7bit',
'Auto-Submitted' => 'auto-generated'
);
my $body = MIME::Lite->new( Type => 'multipart/alternative',
Encoding => '8bit'
);
$body->attach( Type => 'text/plain; charset=UTF-8',
Data => $plain
);
$body->attach( Type => 'text/html; charset=UTF-8',
Data => $html
);
$email->attach($body);
$email->send();
returnOk();
sub returnOk {
print "Location: $pic\n\n";
}
Ergebnis:
GMX-Webmailer: OK
Yahoo-Webmailer: OK
1&1-Webmailer alt: OK
1&1-Webmailer neu: OK
Windows Mail: OK
Windows Live Mail: OK
Die schwere Geburt ist Vergangenheit!
Danke Dir nochmals für all die Geduld!
Patrick - wieder nach Italien will!
Re!
#!/usr/bin/perl -w
my $email = MIME::Lite->new( 'Return-Path' => $from,
Soll natürlich heißen:
~~~perl
#!/usr/bin/perl -w
my $email = MIME::Lite->new( 'Return-Path' => encode('MIME-Header', $from),
sonst: Wide character... ;)
GMX-Webmailer: OK
Yahoo-Webmailer: OK
1&1-Webmailer alt: OK
1&1-Webmailer neu: OK
Windows Mail: OK
Windows Live Mail: OK
Wer kann berichten, was andere Mail-Clients/Webmail-Interfaces ausgeben?
Das Skript auf der Noch Testseite ist jetzt frei von Cc, Bcc und sonstige Elemente, die ich zum Testen gebraucht hatte. Jeder kann also ruhig sich selbst eine Mail schicken, ich bekomme das gar nicht mit - halt doch: im Mail-Log von 1und1 könnte ich die E-Mail-Adresse noch sehen... Also, wer will, kann aber mit einer »unwichtigen« E-Mail-Adresse testen!
Il Schratto
Re!
Die schwere Geburt ist Vergangenheit!
Aber es gibt Nachwehen... Wo kommen der Zeilenumbruch und das Leerzeichen her, die ich _manchmal_ zu sehen bekomme:
Subject: =?UTF-8?B?RWluZSBMaW5rZW1wZmVobHVuZyB2b24gTWFtYW1pYSDigLAg?=(\n tutnichtzursache@example.com)\n\n
Das Leerzeichen ist manchmal im Subject-, manchmal im From-Teil. Den Zeilenumbruch sehe ich nur in der Ausgabe von Devel::Peek...? Manchmal ist diese Zeichenfolge (»\n «) direkt hinter der Klammer (< oder (, je nach dem ob From oder Subject) wie hier zitiert, manchmal hinter dem @-Zeichen... Eine Überraschung von encode('MIME-header', )?
Wow, wohl das erste Mal das ich... obwohl, eine »Seitenbewertung« ist es nicht, geht es mir doch nicht darum, wie das Atomic-Eggs-Layout ankommt – das hat sich trotz (oder wegen) der ungewohnten Navigation bewährt.
Vielmehr interessieren mich Tipps und Anregungen zur Bookmark-Service-Box, die durch ein Mouseover auf die Grafik ganz unten zu finden ist (also ja: nur mit JavaScript testen).
Der Button »Fehler!« ist nur für die Testphase da und wird später verschwinden. Damit will ich zeigen, was passieren würde, sollte mal beim Aufruf von einer fremden Seite aus mein Server gerade mal down sein, oder das Perl-Skript aus irgendeinem Grund nicht wollen. Bei dem Anbieter, von dem ich die Idee zu diesem Service habe, weiß ich nämlich nicht, ob so ein Fallback eingebaut ist. Auf jeden Fall laufen bei dieser »Testbox« viele Sachen besser, als bei ihm ;)
Nun ja, frei zum Zerreißen: http://www.atomic-eggs.com/cwi/cwi_5.shtml#ende
Was funzt™ nicht richtig, was kann ich wo verbessern (die Farbwahl ist betont, ich sach mal, dezent - schließlich will ich nicht mit grellen Farbtönen die Besucher meiner User verprellen!). Barrierefrei ist sicher was anderes, ich weiß, aber nun... Ohne JavaScript geht eh nix, bzw. auch da ist ein Fallback geplant - da kommt beim Klicken auf die Icons-Grafik eine spezielle Seite zum Vorschein.
Das JavaSript ist noch optimierungsbedürftig... I know. Aber bitte! Auch hiefür habe ich ein Ohr offen (falls ich nicht auf beiden Ohren schlafe!).
Schrat aka Patrick (noreg)
Vielmehr interessieren mich Tipps und Anregungen zur Bookmark-Service-Box, die durch ein Mouseover auf die Grafik ganz unten zu finden ist (also ja: nur mit JavaScript testen).
Hmmm? Ich weiß nicht was man da testen soll.
Es geht ein Fenster/Layer mit Links zu Anbietern auf, bei denen ich (sofern ich dort Mitglied bin) die Seite Bookmarken kann - mir ist aber nicht klar was für eine Rolle dein Skript dort spielt.
Struppi.
Hallo Struppi!
Es geht ein Fenster/Layer mit Links zu Anbietern auf, bei denen ich (sofern ich dort Mitglied bin) die Seite Bookmarken kann - mir ist aber nicht klar was für eine Rolle dein Skript dort spielt.
Bookmarken Weiterempfehlen...
^^^^
Um den geht's mir ;)
P.S.: Komme eben aus Mainz zurück (Weisenau)
VG,
Patrick