Sziasztok!
PHP-ból, a mail() függvénnyel szeretnék e-mailt küldeni. Tapasztalatom szerint a legtöbb kliens még mindig az ISO-8859-2-t tudja értelmezni, ezért ilyen kódolású levelet szeretnék küldeni. A rendszerem UTF-8-as, ezért így küldöm ki a mailt:
$headers = 'From: "Feladó" <feladocim@valami.hu>' . "\r\n" . 'X-Mailer: PHP/' . phpversion();
mail(iconv("UTF-8", "ISO-8859-2",'Címzett Neve')." <cimzett@valami.hu>", iconv("UTF-8", "ISO-8859-2", $subject), iconv("UTF-8", "ISO-8859-2", $mailtext), iconv("UTF-8", "ISO-8859-2", $headers), "-ffeladocim@valami.hu")
Ennek hatására a címzett, feladó neve, a subject jó kódolású lesz, de a levél törzse nem, ott az UTF-8-at nem tudó kliens (Squirrelmail) ?-eket jelenít meg az ékezetes karakterek helyett.
Pl. gmail-lel megnézve a küldött levelet, jó a kódolás, mindenhol.
A stringek, amelyeket használok ($subject, $mailtext stb.) mind egy UTF-8 kódolású adatbázisból származnak.
Mi lehet itt a hiba?
Petya
- 7531 megtekintés
Hozzászólások
Headerbe tedd még bele a "Content-type: text/html; charset=iso-8859-2" sort.
- A hozzászóláshoz be kell jelentkezni
Próbáltam:
$headers = 'From: "Feladó" ' . "\r\n" . 'X-Mailer: PHP/' . phpversion() . "\r\n" . 'Content-type: text/html; charset=iso-8859-2';
Nincs változás.
Petya
- A hozzászóláshoz be kell jelentkezni
szerintem ha teheted ne szívasd magad a mail függvénnyel, hanem használj levélküldő lib-et pl.:phpmailer.
- A hozzászóláshoz be kell jelentkezni
Hello!
Így csináltam:
require("libphp-phpmailer/class.phpmailer.php");
$mail = new PHPMailer();
$mail->SetLanguage("hu");
$mail->charSet = "iso-8859-2";
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = "localhost"; // specify main and backup server
$mail->SMTPAuth = false; // turn on SMTP authentication
$mail->From = "felado@valami.hu";
$mail->FromName = iconv("UTF-8", "ISO-8859-2","Feladó neve");
$mail->AddAddress("cimzett@valami.hu", iconv("UTF-8", "ISO-8859-2","Címzett Neve"));
$mail->WordWrap = 50; // set word wrap to 50 characters
$mail->IsHTML(false); // set email format to HTML
$mail->Subject = iconv("UTF-8", "ISO-8859-2",$subject);
$mail->Body = iconv("UTF-8", "ISO-8859-2",$mailtext);
if($mail->Send()) $sent_mail++;
A hiba az, hogy pl a szövegben ($mailtext változő) a normális ő,ű betűket kicseréli hullámvonalas o-ra és kalapos u-ra. Mintha 8859-1-et használna, holott megadtam, hogy 8859-2-t használjon.
Petya
- A hozzászóláshoz be kell jelentkezni
próbáld esetleg iconv helyett mb_convert_encoding-al
nálunk a $mail->charSet = "latin2"; és a $mail->Body = mb_convert_encoding($html, "LATIN2", "UTF-8"); és nincs gond.
- A hozzászóláshoz be kell jelentkezni
Így is hullámvonalas o-t és kalapos u-t kapok.
Petya
- A hozzászóláshoz be kell jelentkezni
A php.net tartalmaz erre vonatkozó javaslatokat, ugyanarról szól mindegyik. Itt az egyik, másik, harmadik:
"If you are getting question-marks in your iconv output when transliterating, be sure to 'setlocale' to something your system supports"
"Please note that iconv('UTF-8', 'ASCII//TRANSLIT', ...) doesn't work properly when locale category LC_CTYPE is set to C or POSIX. You must choose another locale otherwise all non-ASCII characters will be replaced with question marks."
Szóval állítsd be a locale-t.
- A hozzászóláshoz be kell jelentkezni
Hello!
Sem
setlocale(LC_CTYPE, 'hu_HU.UTF-8');
, sem pedig
setlocale(LC_CTYPE, 'hu_HU');
esetén nem jó, mindenféleképp maradnak a kérdőjelek (a php mail függvény használata esetén)
Petya
- A hozzászóláshoz be kell jelentkezni
A setlocale maximum a //translit cucchoz kellhet. Ez arról szól, hogy a nem reprezentálható karaktereket milyen karaktersorozattá alakítsa, például ha ő betűt alakítasz latin1-be, akkor o"-t csinál belőle. Ez az átalakítási szabály függhet a nyelvtől. Ha veszteségmentesen végezhető az átalakítás, vagy nem kérsz transzliterációt, akkor a nyelv lényegtelen.
- A hozzászóláshoz be kell jelentkezni
Nem lehet hogy ->CharSet() kéne nagy C-vel? Csak onnan tippelem, hogy a többi mező is így van.
- A hozzászóláshoz be kell jelentkezni
Hejj de szép is hogy tele van a PHP különféle libekkel amik hibásak/hiányosak/nehezen használhatók/nem elég absztraktak... (ezt a következtetést az eddigi hozzászólásokból vonom le). Nem tudom, van-e olyan lib hozzá, aminek betolod UTF-8-ban a levél összes paraméterét, és ő egyszerűen csak elkódolja helyesen. Tehát olyan lib, ami egyszerűen "csak" működik, anélkül hogy pilótavizsga kellene a használatához.
PHP-től elkalandozva, a levelek formátumáról:
Nem tudom, honnan szeded, hogy a legtöbb kliens az ISO-8859-2-t tudja értelmezni. Mára szerintem már elég kevés olyan kliens maradt, aminek az UTF-8-cal problémája lenne. Lehet hogy tévedek. Attól is függ, mit használ a tipikus felhasználói táborod, mert ha például évtizedes outlookot, akkor nem szóltam... Mindenesetre sokkal tisztább, előremutatóbb megoldás az UTF-8, és nem kell azzal a kérdéssel foglalkoznod, hogy mi van, ha nem lehet latin2-re alakítani az adatot.
Szükség lehet egy Mime-version: 1.0 fejlécre (vagy nagy V? számít egyáltalán? nem tudom). Úgy emlékszem, többek közt a mutt-nak kell ehhez, hogy a további fejléceket is jól kezelje.
A levél törzsét egyszerűbb helyesen elkódolni. Egyszerűen csak kell egy Content-type: text/plain; charset=... fejléc, amiben megnevezed, hogy milyen karakterkódolásban áll a szöveg, aztán az általában mehet simán 8-bitesen az általad választott karakterkészletben. Esetleg ráhúzható egy quoted-printable vagy base64 kódolás, a Content-transfer-encoding fejlécben megnevezett módon. Persze hogy bonyolultabb legyen az élet, lehet hogy van korlát a szabványban megengedett maximális sorhosszra (amit úgysem tart be senki), illetve bizonyos szövegekkel is gond lehet, például sor nem kezdődhet úgy hogy "From ", vagy nem egyezhet meg véletlenül a csatolás esetén használt elválasztóval.
A fejlécmezők (címzett, tárgy stb.) bonyolultabbak. Itt natív 8-bites karakterek használata tilos. Mindenki használja őket agyba-főbe, és aztán csodálkozik, hogy semmelyik levelező nem jeleníti meg jól. A Content-type mező itt nem számít. Az ékezetes tartalmat speciális quoted-printable vagy base64 kódolással kell írni, ami valahogy kábé úgy fest, hogy =?iso-8859-2?q?=C1rv=EDzt=FBr=F5?=. Itt is elég bonyolult a szabvány, pláne ha nekiállsz az ilyen blokkokat a nem ilyenekkel keverni, két szomszédos ilyen típusú blokk között lévő szóköz vagy tab vagy újsor és tab eltűnik (ha tényleges szóköz kell, azt egy ilyen blokkon belül =20-ként kódolhatod), de ha az egyik határoló blokk nem ilyen típusú, akkor megmarad. Állítólag a fizikai sorhosszt 75 karakter alatt illik tartani, valamint egy UTF-8 karakter több byte-ja nem robbantható szét két szomszédos ilyen blokkba, együtt kell hogy maradjanak.
Na ezek után kell egy adag mazochizmus ahhoz, hogy az ember ezt kézzel lekódolja. Akkor jársz a legjobban, ha találsz olyan libet, ami mindezt jól csinálja magától anélkül hogy neked bármit tudnod kellene (de azért nem árt a nyers levélformátumot leellenőrizni hogy tényleg jó-e). Remélem hogy ha csak pilótavizsgás libet találsz, akkor segített ez az összefoglaló tájékozódni abban hogy hogyan tudnád helyesen használni azt a libet.
- A hozzászóláshoz be kell jelentkezni
Van egy lib ami jó e célra, a phpmailer.
- A hozzászóláshoz be kell jelentkezni
Vagy a Swift Mailer, Oempro is ezt használja. Bár ez nem valami bonyolult szkript, PHPMailer-rel is mennie kellene...
- A hozzászóláshoz be kell jelentkezni
Hát épp a phpmailerrel próbálkoztak a srácok fent, és nem jött össze nekik. Ráadásul amit ott látok a rakat iconvval, az nekem már túl bonyolult. (Mármint nem úgy értem, hogy nem tudnám megérteni, hanem úgy, hogy az interface túl bonyolultnak tűnik.) Miért nem lehet egy libet olyanra megcsinálni, hogy odaadom neki az adatokat, és a többit ő _magától_ _jól_ megcsinálja?
- A hozzászóláshoz be kell jelentkezni
A PHPMailer szvsz magatol jol megcsinal mindent, itt az a gond, hogy Petya eroszakolja a latin2 kodolast, holott ez felesleges es ertelmetlen is. Ami kliens nem tudja az utf8-at kezelni, azt ki kell dobni a fenebe. Nem hiszem, hogy tul sok usert veszt.
A Squirrelmail is tudja az UTF8-at, ha megfeleloen van beallitva - ezt illik nem felvallrol venni. Legrosszabb esetbe a Mokus cserelheto RoundCube levelezore, sokkal jobb, es szinte minden fele-fajta levelet megeszik.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
SquirrelMail-hez nem kell külön beállítás, hogy UTF-8 kódolású levelet jelenítsen meg helyesen, ha a levél tartalmazza az ehhez szükséges információkat. (FIXME)
- A hozzászóláshoz be kell jelentkezni
Asszem nekem csak ugy sikerult, ha ot magat is UTF-esre allitottam. Nem tudom, egyetlen helyre tettem csak, mert explicite kertek.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
a problema egyik fele valoban az, hogy a php meg nem teljesen kesz a feladatkorre, miszerint barmirol barmire konvertalva helyes eredmennyel dolgozzunk :) -- raadasul nem egyseges, egyik fuggveny jol csinalja, masik pl. latin2-t mint olyat nem kepes outputkent eloallitani, pl. html_entity_decode utf8-ba tud, latin2-be NEM tud alakitani. ha ez csak kornyezeti beallitas, akkor masik fuggvennyel miert mukodott hasonlo dolog megis?
reszemrol mail cimzes, torzs, barmi: utf8+base64, mukodik. meg outlook alatt is. a kulcsszavak pedig nem kis/nagybetu erzekenyek, emiatt legalabbis meg nem szivtam:D
iconv()-vel csak az a bajom, hogy meg kell neki mondani, MIBOL mibe... eleg sok "idegen" adatbazissal dolgozok, sose tudhatom mire szamitsak, igy kellett egy mindenhova kutyagumit...ize mindenbol utf8-at csinalo gepezet.
- A hozzászóláshoz be kell jelentkezni