Recent

Author Topic: Sending email with Indy  (Read 4421 times)

justnewbie

  • Full Member
  • ***
  • Posts: 225
Re: Sending email with Indy
« Reply #45 on: April 26, 2019, 09:49:16 pm »
Something extremely strange happened with my Lazarus.
I got errors when I type the code. For example: I type that Label1 and when I type the dot (ie: Label1.) the following error occurs when the code hint bubble should be appeared, see the picture.
Also, I dropped any component on the form, it doesn't appear in the Form's class definition and I got "Identifier not found" error, although the component is visible on the form.
?!?

Furthermore, DateTimeToStr(OffsetFromUTC()) gives 30-12-99.
« Last Edit: April 26, 2019, 10:14:15 pm by justnewbie »

lucamar

  • Hero Member
  • *****
  • Posts: 2086
Re: Sending email with Indy
« Reply #46 on: April 27, 2019, 12:40:20 am »
Furthermore, DateTimeToStr(OffsetFromUTC()) gives 30-12-99.

That's quite logical: the offset is a time delta, without date portion, so the date is set to zero, which means ... you guessed it: 30-12-99. See for yourself what DateTimeToStr(0.5) gives you.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 677
    • Lebeau Software
Re: Sending email with Indy
« Reply #47 on: April 27, 2019, 10:16:42 pm »
Furthermore, DateTimeToStr(OffsetFromUTC()) gives 30-12-99.

FYI, Indy has a UTCOffsetToStr() function, which would make more sense to use than DateTimeToStr().

But, in any case, OffsetFromUTC() returns a TDateTime which is used to adjust other TDateTime values from local to UTC and vice versa.  TDateTime represents dates as an integral number of days relative to December 30 1899.  Which means that OffsetFromUTC() is returning 0, either because:

  • your machine is really located at UTC offset +0000
  • Indy is not able to determine your machine's offset from UTC, either because:
    • the underlying platform API (ie, gettimeofday() and localtime_r() on Nix platforms) is failing, or is returning incorrect data.
    • you are running Indy on an unsupported platform, in which case there is a global GOffsetFromUTC variable that you would need to set manually.

What platform is your app compiled for when OffsetFromUTC() is returning 0?
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

lucamar

  • Hero Member
  • *****
  • Posts: 2086
Re: Sending email with Indy
« Reply #48 on: April 28, 2019, 01:54:18 am »
TDateTime represents dates as an integral number of days relative to December 30 1899.  Which means that OffsetFromUTC() is returning 0, either because:
[... etc ...]

IIRC, TDateTime is a floating point value: the date is represented in the integral part (as days after 1899-12-30) and the time in the decimal part as a fraction of the day.

If OffsetFromUTC() returns a TDateTime or TTime value, then the "date" part will be 0, i.e. 1899-12-30 no matter what is in the "time" part.

Unless the offset is greater than 24 hours, of course :D
« Last Edit: April 28, 2019, 01:56:46 am by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

justnewbie

  • Full Member
  • ***
  • Posts: 225
Re: Sending email with Indy
« Reply #49 on: April 28, 2019, 12:29:50 pm »
My machine runs a Linux system and all Time(), Date() and Now() works well.
So, how can I get the proper "email-time"? If I send the email to myself for example at 14:32 (my local time), my email client shows 15:32. What should I set to get the proper 14:32?

And, as I mentioned above, something strange happens in my editor.
There is a TIdSMTP component on the form named SMTP. When I type SMTP in the editor, and after it I type a dot, instead of code completition bubble I got this idGlobal error, see picture. Why? 

Cyrax

  • Hero Member
  • *****
  • Posts: 758
Re: Sending email with Indy
« Reply #50 on: April 28, 2019, 09:54:34 pm »
My machine runs a Linux system and all Time(), Date() and Now() works well.
So, how can I get the proper "email-time"? If I send the email to myself for example at 14:32 (my local time), my email client shows 15:32. What should I set to get the proper 14:32?

And, as I mentioned above, something strange happens in my editor.
There is a TIdSMTP component on the form named SMTP. When I type SMTP in the editor, and after it I type a dot, instead of code completition bubble I got this idGlobal error, see picture. Why?

Somehow Lazarus CodeTools barfs on that line. Solution is to modify that line so it looks like (or close) this:

Code: Pascal  [Select]
  1. Index: IdGlobal.pas
  2. ===================================================================
  3. --- IdGlobal.pas        (revision 5496)
  4. +++ IdGlobal.pas        (working copy)
  5. @@ -1905,7 +1905,8 @@
  6.    {$IFDEF UNIX}
  7.  
  8.    // For linux the user needs to set this variable to be accurate where used (mail, etc)
  9. -  GOffsetFromUTC: TDateTime = 0{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF};
  10. +(*  GOffsetFromUTC: TDateTime = 0{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF}; *)
  11. +  GOffsetFromUTC: TDateTime = 0;(*{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF}; *)
  12.  
  13.      {$IFDEF DARWIN}
  14.    GMachTimeBaseInfo: TTimebaseInfoData;
  15.  

justnewbie

  • Full Member
  • ***
  • Posts: 225
Re: Sending email with Indy
« Reply #51 on: April 29, 2019, 03:04:13 pm »
@Cyrax:
I changed it and now I got no that error. Thanks!

So, this question remained:
How can I get the proper "email-time"? If I send the email to myself for example at 14:32 (my local time), my email client shows 15:32. What should I set to get the proper 14:32?

The UTCOffsetToStr(OffsetFromUTC()) gives +0000, which is incorrect.
I'm using Linux and its time display is good.
« Last Edit: April 29, 2019, 03:46:34 pm by justnewbie »

lucamar

  • Hero Member
  • *****
  • Posts: 2086
Re: Sending email with Indy
« Reply #52 on: April 29, 2019, 06:24:15 pm »
The UTCOffsetToStr(OffsetFromUTC()) gives +0000, which is incorrect.
I'm using Linux and its time display is good.

Strictly as a workaround, you can use this:
Code: Pascal  [Select]
  1. if OffsetFromUTC = 0 {and you know that's not true} then
  2.   FakedTime := LocalToUniversal(Now); {uses dateutils}

Indy will use OffsetFromUTC, so if you see it fails you pass the UTC hour instead of your local one. With your example hours above, LocalToUniversal()  should convert 14:32 to 13:32, which is set in the email as if it were the UTC hour, so your email client see this, reverts the conversion and gets 14:32 again.

Note that this just a workaround while you investigate why OffsetFromUTC is failing. If it's v.g. a system misconfiguration, nothing will help you because any function will return the same bad offset.
« Last Edit: April 29, 2019, 06:32:59 pm by lucamar »
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

justnewbie

  • Full Member
  • ***
  • Posts: 225
Re: Sending email with Indy
« Reply #53 on: April 29, 2019, 07:01:03 pm »
Thank you Lucamar, I'm trying to translate it.

Well, I found that Remy already wrote this: https://github.com/IndySockets/Indy/issues/245
But, to be honest, I dunno what should I do based on this info.
GetLocalTimeOffset() gives the proper offset (in minutes). How can I pass this value to the Indy?

lucamar

  • Hero Member
  • *****
  • Posts: 2086
Re: Sending email with Indy
« Reply #54 on: April 29, 2019, 07:34:04 pm »
Thank you Lucamar, I'm trying to translate it.

Well, I found that Remy already wrote this: https://github.com/IndySockets/Indy/issues/245
But, to be honest, I dunno what should I do based on this info.
GetLocalTimeOffset() gives the proper offset (in minutes). How can I pass this value to the Indy?

Look into the Indy source to see where OfssetFromUTC is set (if it's a var) or implemented (if it's a function) and change whatever is there to use GetLocalTimeOffset when it's compiling under FPC.

Or use the workaround above in your program until Remy fixes it in Indy. (This is what I would do, btw).
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

justnewbie

  • Full Member
  • ***
  • Posts: 225
Re: Sending email with Indy
« Reply #55 on: April 29, 2019, 07:42:31 pm »
Yes, it will be a workaround.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 677
    • Lebeau Software
Re: Sending email with Indy
« Reply #56 on: April 30, 2019, 10:11:18 pm »
IIRC, TDateTime is a floating point value: the date is represented in the integral part (as days after 1899-12-30) and the time in the decimal part as a fraction of the day.

That is correct.

If OffsetFromUTC() returns a TDateTime or TTime value, then the "date" part will be 0, i.e. 1899-12-30 no matter what is in the "time" part.

That is a good point.  And yes, it does returns a TDateTime with the date portion set to 0 and the time portion set to the offset.

Unless the offset is greater than 24 hours, of course :D

Which it never should be, since the lowest/highest UTC offsets defined are only ±12 hours from UTC.

So, how can I get the proper "email-time"? If I send the email to myself for example at 14:32 (my local time), my email client shows 15:32. What should I set to get the proper 14:32?

Emails use UTC timestamps, which means Indy is calculating your machine's UTC as ±1 hour from UTC.  What is your machines ACTUAL UTC offset? 

Somehow Lazarus CodeTools barfs on that line. Solution is to modify that line so it looks like (or close) this:

Code: Pascal  [Select]
  1. Index: IdGlobal.pas
  2. ===================================================================
  3. --- IdGlobal.pas        (revision 5496)
  4. +++ IdGlobal.pas        (working copy)
  5. @@ -1905,7 +1905,8 @@
  6.    {$IFDEF UNIX}
  7.  
  8.    // For linux the user needs to set this variable to be accurate where used (mail, etc)
  9. -  GOffsetFromUTC: TDateTime = 0{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF};
  10. +(*  GOffsetFromUTC: TDateTime = 0{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF}; *)
  11. +  GOffsetFromUTC: TDateTime = 0;(*{$IFDEF HAS_DEPRECATED}{$IFDEF USE_SEMICOLON_BEFORE_DEPRECATED};{$ENDIF} deprecated{$ENDIF}; *)
  12.  
  13.      {$IFDEF DARWIN}
  14.    GMachTimeBaseInfo: TTimebaseInfoData;
  15.  

I'm not having that discussion again.  I've covered that issue MANY times before in this forum, search the archives.  The whole reason USE_SEMICOLON_BEFORE_DEPRECATED even exists is because of FPC.  But if you look in Indy's IdCompilerDefines.inc file, you will notice that USE_SEMICOLON_BEFORE_DEPRECATED is defined only for FPC 2.4.4 through 2.6.1.  From FPC 2.6.2 onwards, it is no longer defined, effectively making the declaration:

Code: Pascal  [Select]
  1. GOffsetFromUTC: TDateTime = 0 deprecated;

Which has already been proven to work fine in modern FPC versions.  If Lazarus's *editor* has a problem with it, that is for the Lazarus team to fix.  That is all I'm saying about that issue.

The UTCOffsetToStr(OffsetFromUTC()) gives +0000, which is incorrect.
I'm using Linux and its time display is good.

Can you please confirm whether both UNIX and either KYLIXCOMPAT or USE_BASEUNIX are defined while compiling IdGlobal.pas when building Indy?

If both are defined, OffsetFromUTC() calculates an offset based on the Posix gettimeofday() function.

If either are not defined, OffsetFromUTC() falls back to Indy's GOffsetFromUTC variable, which is 0 by default and must be set manually.  In which case, this is a bug in Indy, as those conditionals SHOULD be defined when compiling for Linux.

Well, I found that Remy already wrote this: https://github.com/IndySockets/Indy/issues/245

Beat me to it, I was just about to point that out.  As you can see from this discussion referenced by that ticket, I was made aware of the issue only a few months ago, but as you can read in that discussion, I have already considered using FPC's offset functions and am hesitant to use them because FPC's own documentation states that they return stale data after DST changes.  So I haven't applied any fixes to Indy yet.

But, to be honest, I dunno what should I do based on this info.
GetLocalTimeOffset() gives the proper offset (in minutes). How can I pass this value to the Indy?

If Indy is actually calling gettimeofday() (as it should be), and the function is just not returning timezone info back to Indy, then there is nothing you can do about that without altering Indy's source code.  Only when Indy has to fallback to its own GOffsetFromUTC variable can you assign your own timezone offset to Indy.
« Last Edit: April 30, 2019, 10:22:18 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

justnewbie

  • Full Member
  • ***
  • Posts: 225
Re: Sending email with Indy
« Reply #57 on: April 30, 2019, 11:14:27 pm »

Can you please confirm whether both UNIX and either KYLIXCOMPAT or USE_BASEUNIX are defined while compiling IdGlobal.pas when building Indy?

If both are defined, OffsetFromUTC() calculates an offset based on the Posix gettimeofday() function.

If either are not defined, OffsetFromUTC() falls back to Indy's GOffsetFromUTC variable, which is 0 by default and must be set manually.  In which case, this is a bug in Indy, as those conditionals SHOULD be defined when compiling for Linux.


Uhh, it is not my level, yet.  %)
All I can say that I did not modify anything in Indy, it is as it was originally.
I made this workaround:
Code: Pascal  [Select]
  1. if OffsetFromUTC() = 0 then mMessage.Date := LocalTimeToUniversal(Now);
By using this the time is ready in my email client.

lucamar

  • Hero Member
  • *****
  • Posts: 2086
Re: Sending email with Indy
« Reply #58 on: May 01, 2019, 06:52:51 am »
I have already considered using FPC's offset functions and am hesitant to use them because FPC's own documentation states that they return stale data after DST changes.  So I haven't applied any fixes to Indy yet.

It also shows the solution: caling unix.ReReadLocalTime before GetLocalTimeOffset.

I guess they don't do so automatically because it's only a couple times per year and the conditions are (usually) very constrained. In Europe, for example, you would have to have the program running on the last Sunday of March/October before 2:00 and call GetLocalTimeOffset after 2:00 to get a bad offset.
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.2/2.0.4  - FPC 3.0.4 on:
(K|L)Ubuntu 12..16, Windows XP SP3, various DOSes.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 677
    • Lebeau Software
Re: Sending email with Indy
« Reply #59 on: May 01, 2019, 06:32:07 pm »
It also shows the solution: caling unix.ReReadLocalTime before GetLocalTimeOffset.

Yes, I know, but WHEN should that be called?  The documentation only says to call ReReadLocalTime() to reinitialize the timezone info, but it doesn't actually say to call it before GetLocalTimeOffset(), and I'm guessing ReReadLocalTime() should not be called every time GetLocalTimeOffset() is being called, right?  Otherwise GetLocalTimeOffset() could have just done that internally (and why doesn't it?).

Remember, Indy is a library, so should it even try to call ReReadLocalTime() periodically, or should it require the user's app to call it?  And then people forget to call it, the data goes stale, and again Indy gets blamed for being buggy.

Oh well, better than nothing, right?  I'll look into adding use of GetLocalTimeOffset(), LocalTimeToUniversal(), and UniversalTimeToLocal() into Indy when I have some free time.
« Last Edit: May 01, 2019, 07:11:21 pm by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)