eMail über AsiNet mit falschem Datum !

Vom Front-End bis SOAP.

Moderator: Moderatoren

Antworten
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15688
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

eMail über AsiNet mit falschem Datum !

Beitrag von brandelh »

Hallo,

bei der aktuellen AsiNet Version (bis 1.90.355) wird der DATE Header falsch gesetzt, wenn er nicht explizit angegeben wird.
Darum wird eine solche eMail z.B. bei GMX mit Datum vom 01.01.70 in der Liste angezeigt.
Sie selbst kennt aber das richtige Datum. Im erweiterten eMail-Header kann man die Zeile:

Date: Date: ... finden, richtig wäre
Date: ...

Nach Auskunft von Alaska ist der Fehler im nächsten Release behoben.
Er ist aber auch leicht selbst zu verbessern:

Code: Alles auswählen

oMail:addHeader( "Date", cDateTimeString )  // z.B. "Mon, 24 Jan 2011 17:22:22 +0100"
Wenn man es genau und flexibel machen will, muss man die timezone berechnen, wenn es einem nicht so darauf ankommt, ginge es auch einfacher ;-)

Ich habe meine Funktion TimeStamp() umgebaut zu TimeStampSMTP(), somit ist das die richtige Zeile:

Code: Alles auswählen

oMail:addHeader( "Date", TimeStampSMTP() )  // z.B. "Mon, 24 Jan 2011 17:22:22 +0100"
hier nun die Funktion:

Code: Alles auswählen

*----------------------------------------------------------------------------------------
#include "Dll.ch"
#define TIME_ZONE_ID_INVALID   0xFFFFFFFF
#define TIME_ZONE_ID_UNKNOWN   0
#define TIME_ZONE_ID_STANDARD  1
#define TIME_ZONE_ID_DAYLIGHT  2

function TimeStampSMTP()

   local cST  := replicate(W2bin(0),8)  // TimeStamp 8x Word = SYSTEMTIME Struktur     16 End
   local cTZI := l2bin(0)+;             // LONG   Bias;             TZI _TimeZoneInfo   4   1-  4
                 space(64)+;            // WCHAR  StandardName[32];                    64   5- 68
                 replicate(W2bin(0),8)+;// SYSTEMTIME StandardDate;                    16  69- 84
                 l2bin(0)+;             // LONG   StandardBias;                         4  85- 88
                 space(64)+;            // WCHAR  DaylightName[ 32 ];                  64  89-152
                 replicate(W2bin(0),8)+;// SYSTEMTIME DaylightDate;                    16 153-168
                 l2bin(0)               // LONG       DaylightBias;                     4 169-172
                                        // wir brauchen hiervon nur die 3 Bias !
   local nTZI_Return, cTimeZoneInfo := ""
   local cTimeStamp, nH, x
   local nYear,nMonth,nDayOfWeek,nDay,nHour,nMinute,nSecond,nMilliseconds
   local nHourOffsetUTC, nMinuteOffsetUTC
   local nBias, nStandardBias, nDaylightBias
   local aDay   := { "Sun","Mon","Tue","Wed","Thu","Fri","Sat"}
   local aMonth := { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }


   nH := DllLoad("KERNEL32.DLL")

   DllCall(nH,DLL_STDCALL,"GetLocalTime",@cST)

   nTZI_Return := DllCall(nH,DLL_STDCALL,"GetTimeZoneInformation",@cTZI)
   if nTZI_Return = TIME_ZONE_ID_INVALID .or. nTZI_Return = TIME_ZONE_ID_UNKNOWN
      // bei ungültiger Zeitzonen Information UTC liefern
      // if TZI is invalid or unknown, use UTC.
      DllCall(nH,DLL_STDCALL,"GetSystemTime",@cST)
      cTimeZoneInfo := "???("+alltrim(str(nTZI_Return))+")"
      nBias         := 0
      nStandardBias := 0
      nDaylightBias := 0
   else
      nBias         := bin2l(substr(cTZI,  1,4))
      nStandardBias := bin2l(substr(cTZI, 85,4))
      nDaylightBias := bin2l(substr(cTZI,169,4))
   endif

   do case
      case nTZI_Return = TIME_ZONE_ID_STANDARD
           nBias := nBias + nStandardBias
      case nTZI_Return = TIME_ZONE_ID_DAYLIGHT
           nBias := nBias + nStandardBias + nDaylightBias
      otherwise
           nBias := 0
   endcase

   // SYSTEMTIME structure, the right sequence is important.
   // Reihenfolge ist wichtig, je 2 Byte, bei Stunde wird auch die SystemTime (UTC) ermittelt.
   x := 1
   nYear            := Bin2w( substr(cST,x,2)) ; x += 2
   nMonth           := Bin2w( substr(cST,x,2)) ; x += 2
   nDayOfWeek       := Bin2w( substr(cST,x,2)) ; x += 2
   nDay             := Bin2w( substr(cST,x,2)) ; x += 2
   nHour            := Bin2w( substr(cST,x,2)) ; x += 2
   nMinute          := Bin2w( substr(cST,x,2)) ; x += 2
   nSecond          := Bin2w( substr(cST,x,2)) ; x += 2
   nMilliseconds    := Bin2w( substr(cST,x,2)) // ENDE

   cTZI := cST := ""

   // ISO 8601 - wikipedia
   //
   // die BIAS Angaben beziehen sich immer auf  UTC = LOCAL + BIAS + ...
   // wir brauchen hier aber die Angabe       LOCAL = UTC - BIAS
   // denn     ...232010+0100 => LOKALEZEIT+UTC_Offset
   // The BIAS values have to be added on LOCAL time:   UTC = LOCAL + BIAS + ...
   // but we need it like                             LOCAL = UTC - BIAS
   // because  ...232010+0100 => LOCALTIME+UTC_Offset

   do case
      case nBias > 0
           cTZI := "-"
      case nBias < 0
           cTZI := "+"
           nBias := abs(nBias)
      otherwise
           cTZI := "Z"
   endcase

   if cTZI # "Z"
      nHourOffsetUTC   := int(nBias/60)
      nMinuteOffsetUTC := int(nBias - int(nHourOffsetUTC*60))
      cTZI += strZero(nHourOffsetUTC,2)+strZero(nMinuteOffsetUTC,2)
   endif

   // Windows nDayOfWeek geht von 0 bis 6, wir brauchen aber wie dow() 1 bis 7
   nDayOfWeek++ // 0 bis 6 -> 1 bis 7

   cTimeStamp := aDay[nDayOfWeek]+", "+StrZero(nDay,2,0)+" "+aMonth[nMonth]+" "+StrZero(nYear,4,0)+" "+time()+" "+cTZI

   // "Date: Mon, 24 Jan 2011 17:22:22 +0100"
   //       "Mon, 24 Jan 2011 17:22:22 +0100"

return cTimeStamp
Gruß
Hubert
Antworten