Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw. (https://www.delphipraxis.net/148194-indy-smtp-mailversand-fehler-bei-umlauten-aeoeue-ss-usw.html)

alleinherrscher 24. Feb 2010 19:14


Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
Hi@all!

Ich versuche gerade mit Indy ne Mail zu schicken, die anschließend in Mozilla Thunderbird anständig, mit umlauten angezeigt wird.
Wie muss ich vorgehen, damit das klappt? Ich habe bereits hier gesucht und 3-4 Themen gefunden, allerdings haben die Tips hier nicht funktioniert.

Ich benutze die neuste Indyversion u. D2009

Verwende die TIdMessage und TIdSMTP Komponenten. Habe gerade etwas mit den Komponenten TIdEncoderMIME und TIdEncoderQuotedPrintable rumgespielt, aber das ergebnis ändert sich nicht.

Könnt ihr mir ein paar tips geben?

LG und besten Dank,
Michael

alleinherrscher 26. Feb 2010 11:17

Re: Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
hier mal der Code, wie gesagt mit Indy10 und Delphi2009:


Delphi-Quellcode:

procedure TfoEMail.Senden;
var
   AR,VN,NN,BC,filename: string;
begin

  with Mail do
   begin
         Body.Text:='öäüÄÜÖß';
   
         From.Text := foEMailSetup.UserEMail;
    ReplyTo.EMailAddresses := foEMailSetup.UserEMail;
    Recipients.EMailAddresses:= '';
    CCList.Clear;
    BccList.Clear;

    Recipients.Add;
    Recipients[Recipients.Count-1].Text:= MAILADRESSE;


         Subject := 'Testöäü' { BetreffZeile }

    Priority := TIdMessagePriority(2); { Message Priority }

         filename:= GetTempDir +'Angebot.pdf'

         if fileexists(filename) then
       TIdAttachmentFile.Create(Mail.MessageParts, filename);

   0: SMTP.AuthType:= satNone;

    SMTP.Username := foEmailSetup.SmtpServerUser;
    SMTP.Password := foEmailSetup.SmtpServerPassword;

    {General setup}
    SMTP.Host := foEmailSetup.SmtpServerName;
    SMTP.Port := foEmailSetup.SmtpServerPort;

    {now we send the message}
    SMTP.Connect;
    try
         SMTP.Send(Mail);
         ShowMessage('Die eMail wurde verschickt.')
    finally
         //ShowMessage('Ein Fehler im Mailversand ist aufgetreten.'+#13+'Bitte prüfen Sie ihre Einstellungen.');
         SMTP.Disconnect;
    end;
end;

Astat 26. Feb 2010 11:25

Re: Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
Hallo alleinherrscher, ich verwende zwar die Indys nicht, aber für
SMTP sollte der Stream Base64 Encoded sein. Hab bei den Indys auch eine solche Komponente gesehen.
Versuchs mal.

lg. Astat

shmia 26. Feb 2010 14:27

Re: Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
Wahrscheinlich ist das Encoding des Zeichensatz falsch.
Schicke mal eine Test Email an echo@TU-Berlin.de
Du bekommst nach etwa einer Minute eine Antwort (hier ein Ausschnitt):
Code:
From: <meineEMail@meineDomain.de>
To: <echo@TU-Berlin.de>
Subject: Test EMail mit Indy SMTP
MIME-Version: 1.0
Content-Type: text/plain; charset="iso-8859-1"
Wichtig ist, dass charset auf "iso-8859-1" steht.
Wenn die Zeile fehlt oder charset="us-ascii" ist, dann klappt das mit den Umlauten nicht.

Manche EMail-Clients sind so "schlau" und stellen die Mail trotzdem als iso8859-1 dar.
Das macht es nicht gerade einfach dann festzustellen, dass der Fehler eigentlich beim Sender der EMail liegt.

alleinherrscher 26. Feb 2010 15:37

Re: Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
Ich schreibe gleich mal die Testmail. Aber das mit den Charsets hab ich schon getestet - selbes ergebnis. Poste gleich mal die zurückgeschickte mail, moment... Muss dazu sagen, dass der Code unter D2006 anständig lief. Wahrscheinlich ein Kompatibilitätsproblem zwischen Indy10 und D2009???

//edit: da als codierung 8bit in der Mail stand, habe ich nun den sourcecode so ergänzt:

Delphi-Quellcode:
        IdText:= TIdText.Create(Mail.MessageParts,nil);
        IdText.CharSet:= 'iso-8859-1';
        IdText.ContentTransfer:='quoted-printable';
        IdText.Body.Text:=Text;
Die Mail hat dann an der Stelle, wo der Textteil kommt folgenden Kopf:

Code:
--sVeUSiU0mpvxr19=_Wrrpk8HAtGmlQoNmf
Content-Type: text/plain; charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline
Wird aber immer noch nicht richtig angezeigt (fehler bleibt bestehen)...

idefix2 31. Mär 2010 23:58

Re: Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
Hallo,

ich habe exakt das gleiche Problem - nachdem ich hier im Forum gesucht und diesen schon ein Monat alten Thread gefunden habe, möchte ich ihn reaktivieren. Ich habe jetzt bei der message das charset-Attribut auf iso-8859-1 gesetzt, aber Indy konvertiert anscheinend die Umlaute und accents zu Zeichen ohne Umlaut oder accent, ä wird zu a, é wird zu e, ß wird zu ?, und so kommt das Mail dann an.

So geht das Mail hinaus (Der Zeichensatz scheint also richtig zu sein, die Zeichen trotzdem nicht):
Content-Type: multipart/mixed; charset="iso-8859-1"; boundary="Vccs5ac9ZB8YJ64yuqesm=_qvpQbuSmPLm"
MIME-Version: 1.0

Nicht nur im Mailbody, auch schon im From Eintrag ist aus dem ü ein u geworden:
From: Franz Muller

Bin für jeden zielführenden Tip dankbar.

Liebe Grüsse

s.h.a.r.k 1. Apr 2010 00:11

Re: Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
Schon mal "utf-8" probiert?

idefix2 1. Apr 2010 00:35

Re: Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
eben jetzt, gleich probiert - leider genau das gleiche Ergebnis:

Content-Type: multipart/mixed; charset="UTF-8"; boundary="O5GFk43o1CBR6svtr6K9ahl8Ob=_ZYpnUs"
MIME-Version: 1.0
Sender: "Franz Muller" <franz@focusdata.at>

Wieder werden im Feld Sender (sollte Müller heissen), und erst recht im Mailtext, die Umlaute zu normalen Nicht-Umlauten. Es schaut für mich so aus, als würde Indy alle Umlaute und dgl. vor dem Versenden wegkonvertieren, egal wie der charset des zu versendenden Mails aussieht. Die Umlaute kommen nicht irgendwie falsch codiert heraus, sondern als den jeweiligen Umlauten entsprechende Nicht-Umlaute.

idefix2 8. Apr 2010 01:09

Re: Indy SMTP Mailversand, Fehler bei Umlauten äöü,ß usw.
 
So, nachdem zu dem Thema nirgends eine Information zu finden war, habe ich mich durch den Indy-Code durchgebissen und die Ursache gefunden.

Die Indy Routinen sind derart undurchsichtig programmiert, dass es einem die Haare aufstellt, ich habe letztlich an vier Stellen den Code geändert, und jetzt versenden die Komponenten meine Mails sowohl mit als auch ohne Anhang unter Beibehaltung der Umlaute. Nachdem ich aber nicht wirklich ganz durchblicke, ist leider nicht sichergestellt, dass die Änderungen, die in meinem Programm funktionieren, nicht in anderen Programmen unerwünschte Nebeneffekte haben, wenn die Mails anders aufgebaut sind. Trotzdem poste ich hier diese Änderungen, wenn jemand Mails mit Umlauten oder Sonderzeichen mit den aktuellen Indy Komponenten versenden will, kann er ja versuchen, ob die Anpassungen auch für ihn tun, was er braucht.

Für den Normalfall eines Mails mit einem Messagebody und keinem, einem oder mehreren Anhängen sollte es, glaube ich, einwandfrei funktionieren, wobei ich, offenbar entgegen den Vorstellungen der Indy Entwickler, den Mailtext auch dann im Message.body übergebe, wenn es Dateianhänge gibt (beim Studium des Indy Codes habe ich festgestellt, dass eigentlich, wenn ein Mailanhang existiert, auch der Mailbodytext als Messagepart übergeben werden sollte; nur, wenn man das so macht, bin ich nicht sicher, ob mit den Umlauten im Bodytext wieder irgend ein Unfug passiert, ich habe es gar nicht erst versucht). Was das Ding mit Bildern im Mailbody oder mit mehr als einem textpart macht (gibt es solche Mails überhaupt?), weiss ich nicht.

Im den auskommentierten Codezeilen steht jeweils die ursprüngliche, von mir geänderte Quelltextversion

Viel Erfolg!

Delphi-Quellcode:

procedure TIdMessageClient.SendHeader(AMsg: TIdMessage);
begin // notwendig für Umlaute im Betreff oder Absender
  AMsg.GenerateHeader;
//  IOHandler.Write(AMsg.LastGeneratedHeaders);
// geändert:
  IOHandler.Write(AMsg.LastGeneratedHeaders, false, en8bit);
// Ende der Änderung
end;


in procedure TIdMessageClient.SendBody(AMsg: TIdMessage);
// Umlaute in einem Mailtext ohne Anhang handhaben
    ....
    else if AMsg.Encoding = mePlainText then begin
      IOHandler.WriteLn;    //This is the blank line after the headers
      //CC2: It is NOT Mime. It is a body followed by optional attachments
      DoStatus(hsStatusText, [RSMsgClientEncodingText]);
      // Write out Body first
      LHeaderCoder := HeaderCoderByCharSet(ISOCharSet);
      if LHeaderCoder <> nil then begin
        for i := 0 to AMsg.Body.Count - 1 do begin
          LBodyLine := LHeaderCoder.Encode(ISOCharSet, AMsg.Body[i]);
//          IOHandler.WriteLnRFC(LBodyLine); {do not localize}
// geändert:
          IOHandler.WriteLnRFC(LBodyLine,en8bit); {do not localize}
// Ende der Änderung
        end;
      end else begin
        EncodeAndWriteText(AMsg.Body);
      end;
      ....


procedure TIdMessageClient.EncodeAndWriteText(const ABody: TStrings);
begin
  Assert(ABody<>nil);
  Assert(IOHandler<>nil);
//  IOHandler.WriteRFCStrings(ABody);
// geändert:
  IOHandler.WriteRFCStrings(ABody, False, en8bit);
// Ende der Änderung
end;



// Umlaute in einem Mailtext mit Anhängen
  procedure WriteTextPart(ATextPart: TIdText);
  var
    LData: TStringList;
    li, j: Integer;
    LQuotedPrintableEncoder: TIdEncoderQuotedPrintable;
    LHeaderCoder: TIdHeaderCoderClass;
    LFileName: String;
  begin
    if ATextPart.ContentType = '' then begin
      ATextPart.ContentType := 'text/plain'; {do not localize}
    end;
    if ATextPart.ContentTransfer = '' then begin
      ATextPart.ContentTransfer := 'quoted-printable'; {do not localize}
    end
    else if (PosInStrArray(ATextPart.ContentTransfer, ['quoted-printable', 'base64'], False) = -1) {do not localize}
      and ATextPart.IsBodyEncodingRequired then
    begin
//        ATextPart.ContentTransfer := '8bit';                   {do not localize}
// geändert:
        ATextPart.ContentTransfer := 'quoted-printable';                   {do not localize}
// Ende der Änderung - ich bin nicht sicher, ob diese Änderung nötig ist,
// aber so kommen die Umalute jedenfalls richtig an
    end;
    if ATextPart.ContentDisposition = '' then begin
      ATextPart.ContentDisposition := 'inline'; {do not localize}
    end;

    LFileName := EncodeHeader(ExtractFileName(ATextPart.FileName), '', HeaderEncoding, ISOCharSet); {do not localize}

    //ContentType may contain the charset also, but CharSet overrides it if it is present...
    if ATextPart.CharSet <> '' then begin
      IOHandler.Write('Content-Type: ' + RemoveHeaderEntry(ATextPart.ContentType, 'charset') {do not localize}
         + '; charset="' + ATextPart.CharSet + '"'); {do not localize}
    end else begin
      IOHandler.Write('Content-Type: ' + ATextPart.ContentType); {do not localize}
    end;
    if LFileName <> '' then begin
      IOHandler.Write(';' + EOL + '       name="' + LFileName + '"'); {do not localize}
    end;
    IOHandler.WriteLn;

    IOHandler.WriteLn(SContentTransferEncoding + ': ' + ATextPart.ContentTransfer); {do not localize}
    IOHandler.WriteLn('Content-Disposition: ' + ATextPart.ContentDisposition); {do not localize}
    if LFileName <> '' then begin
      IOHandler.Write(';' + EOL + '       filename="' + LFileName + '"'); {do not localize}
    end;
    IOHandler.WriteLn;

    if ATextPart.ContentID <> '' then begin
      IOHandler.WriteLn('Content-ID: ' + ATextPart.ContentID); {do not localize}
    end;

    LX := ATextPart.ExtraHeaders.Count; {Debugging}
    IOHandler.Write(ATextPart.ExtraHeaders);
    IOHandler.WriteLn;

    if TextIsSame(ATextPart.ContentTransfer, 'quoted-printable') then begin {do not localize}
      if ATextPart.Body.Count > 0 then begin
        LQuotedPrintableEncoder := TIdEncoderQuotedPrintable.Create(Self);
        try
          LData := TStringList.Create;
          try
            LHeaderCoder := HeaderCoderByCharSet(ISOCharSet);
            for li := 0 to ATextPart.Body.Count - 1 do begin
//              LQuotedPrintableEncoder.Encode(ATextPart.Body[li] + EOL, LData);
//              for j := 0 to LData.Count-1 do begin
//                if (LData[j] <> '') and (LHeaderCoder <> nil) then begin
//                  LData[j] := LHeaderCoder.Encode(ISOCharSet, LData[j]);
//                end;
//              end;
//              IOHandler.WriteRFCStrings(LData, False);
//            end;
// geändert:
              ldata.add (ATextPart.Body[li]+EOL);
            end;
            IOHandler.WriteRFCStrings(LData, False, en8bit);
// Ende der Änderung
          finally
            FreeAndNil(LData);
          end;
        finally
          FreeAndNil(LQuotedPrintableEncoder);
        end;
      end;
    end
    else if TextIsSame(ATextPart.ContentTransfer, 'base64') then begin {do not localize}
      EncodeStrings(ATextPart.Body, TIdMessageEncoderMIME);
    end else
    begin
      LX := ATextPart.Body.Count;

//      IOHandler.WriteRFCStrings(ATextPart.Body, False);
      { No test for last line break necessary because IOHandler.WriteRFCStrings() uses WriteLn(). }
// geändert:
      IOHandler.WriteRFCStrings(ATextPart.Body, False, en8bit);
// Ende der Änderung
    end;
  end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:57 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz