Avatar billede aerobee Nybegynder
13. december 2007 - 20:15 Der er 31 kommentarer og
1 løsning

PEAR's mail package og email validering ifølge RFC822

Jeg sidder og leger lidt med PEAR's mail package med indbygget email validering ifølge RFC822 standard format.

Problemet der opstår er når afsender har et dansk tegn (æ,ø,å) i sin email adresse - så bliver denne ikke valideret af RFC822 som jo kommer inkluderet med PEAR's mail package.

Hvordan kan det være at emails indeholdene danske tegn ikke anses for værende gyldig syntax, og har i et råd til hvordan jeg kan afhjælpe problemet og lade danske email adresser validere via PEAR's mail package.
Avatar billede erikjacobsen Ekspert
13. december 2007 - 21:03 #1
Forhåbentlig mener du RFC 2822 - men er det æøå før eller efter @ du mener ?
Avatar billede arne_v Ekspert
13. december 2007 - 21:24 #2
ÆØÅ er ikke valide i emails.

ÆØÅ i 822 headere skal encodes i en speciel quoted printable form:

=?navnpåcharset?Q?textmedæøå?=
Avatar billede aerobee Nybegynder
14. december 2007 - 14:58 #3
æøå både før og efter @

Hvordan skal jeg gøre det arne?
Nu skriver jeg det jo sådan her:


$mail->send("æøå@øæå.dk", $headers, $body);

Emailen herover er naturligvis beregnet til eksemplet her
Avatar billede aerobee Nybegynder
14. december 2007 - 15:00 #4
Eller
$email = "æø@øå.dk"

$mail->send($email, $headers, $body);
Avatar billede aerobee Nybegynder
15. december 2007 - 13:06 #5
efter yderligere søgninger på google ud fra arne v's kommentar fik jeg det til at virke..

svar arne v

Med henvisning til php.net: http://dk.php.net/function.mail
Hvor en bruger skrev følgende kommentar:

"I haven't seen in this page a reference about how to properly handle subject encoding when using non-ascii characters. I've found that info at http://www.johanvanmol.org/content/view/34/37/1/3/, which I paste:

"According to RFC 2822, mail header fields, including the subject, MUST be composed of printable US-ASCII characters (i.e., characters that have values between 33 and 126, inclusive). So if you want a subject with accents, you must encode it from your original character set to a US-ASCII character set. There are 2 of ways to do this: quoted-printable or base64.

[...]

Now we have an encoded subject, but our mail reader won't know that. So we need to tell it by formatting our subject as follows: "=?" charset "?" encoding "?" encoded-text "?=" , where charset is the original character set and encoding is either "Q" for Quoted-Printable or "B" for Base64.
E.g The subject containing the Quoted-Printable ISO-8859-1 string "Voilà une message", is written as:
Subject: =?ISO-8859-1?Q?Voil=E0_une_message?=
The Base64 version of the ISO-8859-1 string is:
Subject: =?ISO-8859-1?B?Vm9pbOAgdW5lIG1lc3NhZ2U=?=
The Quoted-Printable version of the UTF-8 string is:
Subject: =?UTF-8?Q?Voil=C3=A0_une_message?=
The Base64 version of the UTF-8 string is:
Subject: =?UTF-8?B?Vm9pbMOgIHVuZSBtZXNzYWdl?=
"

"Raw" non-encoded subjects can work and modern mail clients handle it properly, but I found that at least using utf-8 as encoding, the spam analizers complain stating "BAD HEADER Non-encoded 8-bit data". To prevent this, and taking the info above, I decided to use base64, which at least seems to have specific functions (and because it works, of course). So, one could use the following code:

<?php
...
$charset='UTF-8';
$subject='Subject with extra chars: áéíóú';
$encoded_subject="=?$charset?B?".base64_encode($subject)."?=\n";
$to=mail@foo.com;
$body='This is the body';
$headers="From: ".$from."\n"
    . "Content-Type: text/plain; charset=$charset; format=flowed\n"
    . "MIME-Version: 1.0\n"
    . "Content-Transfer-Encoding: 8bit\n"
    . "X-Mailer: PHP\n";
mail($to,$encoded_subject, $body,$headers);

?>

Of course, this can be "enhanced" by encoding only if there are non-ASCII characters, but I don't think I need it. Maybe the CPU work, used time and results don't deserve it."
Avatar billede arne_v Ekspert
15. december 2007 - 15:57 #6
svar
Avatar billede arne_v Ekspert
15. december 2007 - 15:57 #7
Jeg vil klart anbefale Quoted Printable fremfor Base64 !
Avatar billede aerobee Nybegynder
15. december 2007 - 16:26 #8
Altså sådan her tænker du på?
$ReplyTo="=?iso-8859-1?Q?".base64_encode($email)."?=";

Eller sådan her
$ReplyTo="=?iso-8859-1?Q?".$email."?=";
Avatar billede aerobee Nybegynder
15. december 2007 - 16:30 #9
Men der er så opstået en ny ting. Når teksten (email adressen) er blevet encoded og sendt - og jeg ser den i min indbakke (Outlook 2007), og trykker på besvar, så ser "to" feltet sådan her ud:
me@exæøample.com <:=?UTF-8?Q?me@exæøample.com?=>

Hvad er der gået galt?
Nogle bud arne ?
Avatar billede aerobee Nybegynder
15. december 2007 - 16:31 #10
Email adressen bliver jo vist fint nok med æøå mv.
Men det er "snavset" bagefter jeg tænker på
Avatar billede aerobee Nybegynder
15. december 2007 - 16:33 #11
Her er scriptet jeg tester med:

<?php
$from ="me@exæøample.com";
$charset='UTF-8';
$subject='Subject with extra chars: áéíóú';
$encoded_from="=?$charset?Q?".$from."?=\n";
$to="privasy@gmail.com";
$body='This is the body';
$headers="From: ".$encoded_from."\n"
    . "Content-Type: text/plain; charset=$charset; format=flowed\n"
    . "MIME-Version: 1.0\n"
    . "Content-Transfer-Encoding: 8bit\n"
    . "X-Mailer: PHP\n";
mail($to,$subject, $body,$headers);

?>
Avatar billede arne_v Ekspert
15. december 2007 - 18:54 #12
Du skal bruge:

$ReplyTo="=?iso-8859-1?Q?".qp_encode($email)."?=";

Desværre eksisterer qp_encode ikke i PHP, men du kan finde code snippets her:
  http://php.net/quoted_printable_decode
undre kommentarer til decode funktionen som er der.

Grundliggende skal alle ikke US ASCII tegn konverteres til =nn hvor nn er hex kode
for byte.
Avatar billede aerobee Nybegynder
15. december 2007 - 19:09 #13
Ligemeget hvad jeg gør kan jeg ikke få det til at virke:

Min kode:
----------

function encodeThis($string){

    function qp_encode($str, $wrap=true)
    {
        $return = '';
        $iL = strlen($str);
        for($i=0; $i<$iL; $i++)
        {
            $char = $str[$i];
            if(ctype_print($char) && !ctype_punct($char)) $return .= $char;
            else $return .= sprintf('=%02X', ord($char));
        }
        return ($wrap === true)
            ? wordwrap($return, 74, " =\n")
            : $return;
    }
   
    return "=?iso-8859-1?Q?".qp_encode($string)."?=";
};


$msg = "Hvert site har sin egen identitet, sin egen målgruppe og sit eget formål.";

$body = encodeThis($msg);

--

Ovenstående er et udsnit at en størrere omfang.
Resultatet jeg modtager i min email ser således ud:

=?iso-8859-1?Q?Hvert site har sin egen identitet=2C sin egen mÃ=A5lgruppe og sit eget = formÃ=A5l=2E?=

Altå, selve body i emailen når jeg ser den i outlook.

Jeg jeg fuldstændig misset en pointe et eller andet sted ?
Avatar billede aerobee Nybegynder
15. december 2007 - 19:39 #14
Tror jeg misser alt her.

Så man får den til at encode - fint nok, også står der i den email man modtager =C3 osv osv..
Mailen skal decodes før modtageren får den, ellers kan han jo ikke læse den.
Men før jeg kan sende skal jeg encode, og når den er sendt er det for sent at decode....

Mmmm ja, jeg er helt tabt her mht encode og decode af emails...

Please advise
Avatar billede arne_v Ekspert
15. december 2007 - 22:53 #15
Efter at have eksperimenteret lidt har jeg konkluderet at den PHP kode fra www.php.net
er defekt !!

Erstatter jeg:

if(ctype_print($char) && !ctype_punct($char)) $return .= $char;

med:

if(ord($char) < 128) $return .= $char;

så virker det hos mig !
Avatar billede arne_v Ekspert
15. december 2007 - 22:54 #16
Hvis du vil QP encode body så skal du ændre:

    . "Content-Transfer-Encoding: 8bit\n"

til:

        . "Content-Transfer-Encoding: quoted-printable\n"
Avatar billede aerobee Nybegynder
16. december 2007 - 10:06 #17
Jeg har fortaget rettelserne, men det virker desværre stadig ikke hos mig.
Herunder smider jeg hele scriptet, samt den modtagne email og dens headers.

********Script**********
$email = $_POST['email'];
$msg = nl2br($_POST['msg']);

function encodeThis($string){

    function qp_encode($str, $wrap=true)
    {
        $return = '';
        $iL = strlen($str);
        for($i=0; $i<$iL; $i++)
        {
            $char = $str[$i];
            if(ord($char) < 128) $return .= $char;
            else $return .= sprintf('=%02X', ord($char));
        }
        return ($wrap === true)
            ? wordwrap($return, 74, " =\n")
            : $return;
    }
 
//arne => bruger jeg iso-8859-1 i stedet for utf-8 herunder får jeg samme resultat
    return "=?utf-8?Q?".qp_encode($string)."?=";
};

require_once('Mail.php');
require_once('Mail\mime.php');

$crlf = "\n";
$from = "xxxx <online@xxxx.com>";
$to = "xxxx <mike@xxxx.com>";
$ReplyTo = $email;

$host = "xxxx.com";
$port = 2525;
$username = "xxxx";
$password = "xxxx";

$message = new Mail_mime($crlf);
$subject = 'Henvendelse';

$body = encodeThis($msg);

$textBody = strip_tags($body); 
$htmlBody = '<html><head><title>'.$host.'</title></head><body>'.$body.'</body></html>';

$message->setTXTBody($textBody);
$message->setHTMLBody($htmlBody);

$headers = array (
    'Content-Transfer-Encoding'    => 'quoted-printable',
    'From'                        => $from,
    'To'                        => $to,
    'Reply-To'                    => $ReplyTo,
    'Subject'                    => $subject,
    'Return-Path'                => 'mike@xxxx.com',
    'X-Mailer'                    => $host
);

$smtp = Mail::factory('smtp', array (
    'host'        => $host,
    'port'        => $port,
    'auth'        => true,
    'username'    => $username,
    'password'    => $password
));

$body = $message->get();
$headers = $message->headers($headers);

$mail = $smtp->send($to, $headers, $body);
if (PEAR::isError($mail)) {
    echo $mail->getMessage();
    exit;
}else{
    echo "afsendt";
    exit;
}
********//Script********

*******Headers på modtagne email*******
Received: from localhost ([xxxx]) by xxxx.dk with Microsoft SMTPSVC(6.0.3790.1830);
    Sun, 16 Dec 2007 09:50:41 +0100
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
From: xxxx <online@xxxx.com>
To: xxxx <mike@xxxx.com>
Reply-To: privasy@gmail.com
Subject: Henvendelse
Return-Path: mike@xxxx.com
X-Mailer: xxxx.com
Content-Type: multipart/alternative;
    boundary="=_35e5dbba4b8817e3ac83058a05a16e47"
Message-ID: <xxxxoMk4om1bKT1He0000004d@xxxx.dk>
X-OriginalArrivalTime: 16 Dec 2007 08:50:41.0534 (UTC) FILETIME=[BCE341E0:01C83FC0]
Date: 16 Dec 2007 09:50:41 +0100
*******//Headers på modtagne email*****

*******Email indhold**********
=?utf-8?Q? Du er altid velkommen til at kontakte os.
Benyt venligst = nedenst=C3=A5ende kontakt formular, og vi vil besvare deres henvendelse = hurtigst muligt, via deres oplyste email adresse. ?=
*******//Email indhold********

Jeg har indsat xxxx forskellige steder i koden herover, xxxx er ikke en del af scriptet.
Avatar billede aerobee Nybegynder
16. december 2007 - 10:54 #18
Jeg kom til at tænke på - vi behøver jo ikke at encode body, da hele problemet her sprang ud af at en email med æøå i ikke kunne valideres af RFC822.

Så jeg har nu lavet mit script lidt om sådan at jeg kun kalder encodeThis funktionen ved min $ReplyTo (den kan jo risikere at indeholde æøå da jeg ikke ved hvad brugeren indtaster)

Så bliver emailen også valideret korrekt og afsendt.
Email adressen bliver også vist korrekt når jeg trykker på besvar, med en undtagelse. Den viser æøå osv men efterfølgende er der en masse skidt.

Eksempel:
fdghæ@dfghåø.com <=?iso-8859-1?Q?fdgh=E6@dfgh=E5=F8.com?=>

hvor fdghæ@dfghåø.com er display name og <=?iso-8859-1?Q?fdgh=E6@dfgh=E5=F8.com?=> burde være email adressen.

Hvad er der gået galt her ? Hvorfor ser email adresse så mærkelig ud.

Vil du se hele mit script igen efter de små rettelser på hvor jeg kalder encodeThis funktionen.. Burde vel ikke være nødvendigt da koden er den samme
Avatar billede arne_v Ekspert
16. december 2007 - 18:06 #19
Til body skal du bare bruge qp_encode ikke encodeThis.
Avatar billede arne_v Ekspert
16. december 2007 - 18:08 #20
Du bør bruge quoted printable for body. 8bit er ikke garanteret at virke med
alle mail servere (men gør dog ofte).
Avatar billede arne_v Ekspert
16. december 2007 - 18:09 #21
Du kan ikke have ÆØÅ i selve email-adresser. Det understøttes ikke. Sådan er det bare.

Du kan kun bruge QP til subject text og til navne delen af email adresserne:

Mister rødgrød med fløde <mrroedgroedmedfloede@somewhere.dk>
Avatar billede erikjacobsen Ekspert
16. december 2007 - 20:25 #22
æøå før @ virker bestemt ikke allesteder. Men nogle webhoteludbydere tillader det, og nogle webmails tillader det også (vist ikke Google Mail, og så kan det jo være ligemeget...). Jeg har med held oprettet øl@etellerandetdoma.ine og sendt post til mig selv et andet sted fra.

æøå efter @ understøttes ikke af mange email-klienter eller webmails (jeg har ikke prøvet for nylig). Man kan selv i sin kode oversætte  æøådomænet.xx til versionen renset for mystiske tegn: xn--enmasssesnask.xx, og så sende mailen dertil. Det kan være det kommer til at virke før jeg går på pension ;)
Avatar billede arne_v Ekspert
16. december 2007 - 20:34 #23
Ups ja. Det er efter @ at ÆØÅ ikke er understøttet (ingen IDN support).
Avatar billede aerobee Nybegynder
16. december 2007 - 21:25 #24
Allrigth..
Tænkte blot det kunne lade sig gøre at have en email adresse (fx. børge@sørensen.dk) da det nu er tilladet at have domains med æøåéü osv.
Derfor jeg ville encode - og deraf min frustration over at RFC822 ikke ville validere den.

Men personligt er jeg heller ikke tilhænger af domains med æøå mm. så dem validere jeg bare ikke fremover. Men æøå i subject og body, naturligvis.

Men mange tak for hjælpen i begge.
Avatar billede arne_v Ekspert
16. december 2007 - 21:42 #25
ÆØÅ i Web er understøttet via IDN. Men email kan (normalt) ikke bruge IDN.
Avatar billede aerobee Nybegynder
17. december 2007 - 20:42 #26
Jeg får først mulighed for at teste det imorgen, det du skrev i indlæg 16/12-2007 18:06:42 arne.

Virker det synes jeg bestemt du har fortjent extra points for din flotte indsats. (Det har du under alle omstændigheder)
Jeg giver lyd fra mig efter jeg har fået det testet.
Avatar billede aerobee Nybegynder
19. december 2007 - 18:43 #27
Så har jeg endelig fået tid til at lege mere med det.

Jeg er gået bort fra at encode email adresser, og istedet sende den med i body sådan jeg kan besvare deres email om den så skulle stå med æøå (fx IDN domæner).

Nu bruger jeg så qp_encode() med min body, og Content-Transfer-Encoding er sat til  quoted-printable i min header. Og man må jo sige at den function gør sit job.
Indholdet at mine modtagne emails står nu med kode(=C3=A6=C3=B8=C3=A5 =C3=86) osv.

Men det kan jeg jo heller ikke bruge til noget, hvordan skal jeg kunne læse dette?

Spørgsmålet handler nu om, hvordan kan jeg få æøå med i min body når jeg sender via PEAR's mail/mail_mime. Altså hvordan udskifter jeg =C3 osv til menneskelig læsbar tekst inklusive æøå?
Avatar billede arne_v Ekspert
23. december 2007 - 00:50 #28
Dit mail program bør vise det som ÆØÅ helt automatisk !
Avatar billede arne_v Ekspert
23. december 2007 - 00:51 #29
Testet eksempel med standard mail:

<?php
ini_set('SMTP', 'smtp.myisp.com');
ini_set('smtp_port', 25);
function qp_encode($str, $wrap=true) {
    $res = '';
    for($i = 0; $i < strlen($str); $i++) {
        if(ord($str[$i]) < 128) {
            $res .= $str[$i];
        } else {
            $res .= sprintf('=%02X', ord($str[$i]));
        }
    }
    return ($wrap === true) ? wordwrap($res, 74, "=\n") : $res;
}
function header_encode($str) {
    return '=?ISO-8859-1?Q?' . qp_encode($str) . '?=';
}
function body_encode($str) {
    return qp_encode($str, true);
}
$from = 'someone@somewhere.dk';
$to = 'someone@somewhere.dk';
$subject = header_encode('Dette er en lille test af ÆØÅ');
$body = body_encode('Dette er en lille test af ÆØÅ');
$headers = "From: $from\r\n" .
          "Content-Type: text/plain; charset=ISO-8859-1\r\n" .
          "MIME-Version: 1.0\r\n" .
          "Content-Transfer-Encoding: quoted-printable";
mail($to, $subject, $body, $headers);
?>
Avatar billede arne_v Ekspert
23. december 2007 - 00:51 #30
Testet eksempel med PEAR mail:

<?php
require_once('Mail.php');
require_once('Mail\mime.php');
function qp_encode($str, $wrap=true) {
    $res = '';
    for($i = 0; $i < strlen($str); $i++) {
        if(ord($str[$i]) < 128) {
            $res .= $str[$i];
        } else {
            $res .= sprintf('=%02X', ord($str[$i]));
        }
    }
    return ($wrap === true) ? wordwrap($res, 74, "=\n") : $res;
}
function header_encode($str) {
    return '=?ISO-8859-1?Q?' . qp_encode($str) . '?=';
}
function body_encode($str) {
    return qp_encode($str, true);
}
$from = 'someone@somewhere.dk';
$to = 'someone@somewhere.dk';
$subject = header_encode('Dette er en lille test af ÆØÅ');
$body = body_encode('Dette er en lille test af ÆØÅ');
$message = new Mail_mime();
$message->setTXTBody($body);
$headers = array('From' => $from,
                'Subject' => $subject,
                'Content-Type' => 'text/plain; charset=ISO-8859-1',
                'Content-Transfer-Encoding' => 'quoted-printable');
$smtp = Mail::factory('smtp', array('host' => 'smtp.myisp.com', 'port' => 25));
$realbody = $message->get();
$realheaders = $message->headers($headers, true);
$smtp->send($to, $realheaders, $realbody);
?>
Avatar billede arne_v Ekspert
23. december 2007 - 00:52 #31
Bemærk at det andet argument til $message->headers er nødvendigt !
Avatar billede nielle Nybegynder
28. december 2007 - 20:46 #32
Husk altid at lave en reference begge veje:

http://www.eksperten.dk/spm/812062
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester