Solved

Indy 10 and sendmail configuration

Posted on 2007-11-22
18
2,366 Views
Last Modified: 2010-04-21
Hello,
I use the latest indy10 with Kylix 3 to send emails. The program I developed is a CGI (CGI stand-alone). But then when the CGI send mails, it turns out that at times the CGI crashes, the mail is not sended, and released following the timeout on the execution of the program.

From a script (bash), which runs the CGI every 20 seconds here is the result:
19 h48 --> 19h52: 11 mails
20 h53 --> 20h59: 21 mails
22 h00 --> 22h07: 21 mails
23 h08 --> 23:14: 21 mails
...
And so on over 1000 mails

In short, and apart from the start with the mailing of 11 e-mails:
- 21 mails are sent
- The 22nd mail is waiting (I do not know why)
- There is therefore a Timeout (seen in the log file / var / log / maillog) after 1:01
- 21 new e-mails are sent
- The 22nd mail is pending during 1:01
...

This scenario occurs in extremely regularly. One could think of a bad sendmail configuration on the server. But then why sends mail by the mail function of php (a site is hosted on the server) has never had a problem?

Here is the test code for the CGI :

var
    SMTP : TIdSMTP;
    MailMessage: TIdMessage;
    aHost, aUserName, aPassWord, cIniSmtpFileName, aFrom, aTo: string;
    aPort: integer;
    IniFile: TIniFile;
begin
  try
    cIniSmtpFileName := 'smtp.kp';

    if FileExists(ApplicationPath + cIniSmtpFileName) then
    begin
      IniFile := TIniFile.Create(ApplicationPath + cIniSmtpFileName);
      try
        aHost := IniFile.ReadString('SmtpConfig', 'Host', 'localhost');
        aPort := IniFile.ReadInteger('SmtpConfig', 'Port', 25);
        aFrom := IniFile.ReadString('SmtpConfig', 'From', 'nj@keepcore.com');
        aTo := IniFile.ReadString('SmtpConfig', 'To', 'jardillier@gmail.com');
      finally
        FreeAndNil(IniFile);
      end;
    end;

    SMTP := TIdSMTP.Create(Self);
    SMTP.Host := aHost;
    SMTP.Port := aPort;
    MailMessage := TIdMessage.Create;
    MailMessage.Clear;
    MailMessage.From.Address := aFrom;
    MailMessage.Recipients.EMailAddresses := aTo;

    MailMessage.Subject := 'Un mail pour vous avertir';
    MailMessage.Body.Text := 'Blalala bla bla blabla bla';

  except
    on E:Exception do
      LogException(E, 'Tsendemail.Execute Message');
  end;

  try
    SMTP.Connect;
    try
      SMTP.Send(MailMessage);
    finally
      SMTP.Disconnect;
    end;
  except
    on E:Exception do
      LogException(E, 'Tsendemail.Execute Send');
  end;

Thanks
0
Comment
Question by:KCTeam
  • 10
  • 8
18 Comments
 
LVL 28

Accepted Solution

by:
2266180 earned 250 total points
ID: 20334031
indy does not use sendmail. your indy-cgi acts like sendmail.

basically, sendmail connects to the smtp server and sends the email.

your cgi should do the same: connect to the smtp server and send the email.

my question is: if  if FileExists(ApplicationPath + cIniSmtpFileName) then returns false, what values will the cgi use? just a "minor" bug ;)

also, you should move the second try/except in the first one, after the mail message has been created and filled. because if there is an exception, there is no sense in trying to connect and send the message (that also will create an exception in practically all cases).

so the question is: what smtp sever are you using? the value of host, which defaults to localhost. are you running a smtp server on localhost? if so, is it properly configured? what about network connections? does the smtp server listen on localhost:25 or jsut on the outbound ip? is the firewall blocking the connection? etc.

there are too many questions here. but generaly, we need an error in order to correctly track down the problem. at least a timeout error somewhere (at connect, at send, etc)
0
 

Author Comment

by:KCTeam
ID: 20335555
Thanks for your answer,
i use for the host of the smtp 'localhost' and for the port '25'.
For the configuration of the SMTP i'm confused, i do not really know which kind of stuff i have to check first. Moreover, i only have the command line access to my server.
I will study and work more the smtp configuration. As the system is Fedora Core 5, the smtp should be the default one, i'll check that.

The error i had in the file maillog was :
Nov 22 14:19:05 <xxxxx> sendmail[4212]: lAMCJ1nI004212: SYSERR(root): collect: read timeout on connection from localhost.localdomain, from=<opache@kcdeditest.com>
Nov 22 14:19:05 <xxxxx> sendmail[4212]: lAMCJ1nI004212: from=<opache@kcdeditest.com>, size=5, class=0, nrcpts=1, proto=ESMTP, daemon=MTA, relay=localhost.localdomain [127.0.0.1]
0
 
LVL 28

Assisted Solution

by:2266180
2266180 earned 250 total points
ID: 20335611
netstat will show you if there is a smtp server running on port 25 and will also tell you on what interfaces it listents. if there isn't one .. that's your problem.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:KCTeam
ID: 20337623
if i do 'netstat -a' i see:
tcp  0  0 *.smtp  *:*  LISTEN
0
 
LVL 28

Assisted Solution

by:2266180
2266180 earned 250 total points
ID: 20337673
well, that means that the smtp server is listening on all interfaces on the port configured as beeing the smtp port in the services file, which is almost always 25.
so that should be ok.

can you please put an else for the
  if FileExists(ApplicationPath + cIniSmtpFileName) then
and set default values? jsut to be on the safe side ;)
and move the second try/except in the first one, after the mail message has been created and filled, as I said at first time.

then, change the following:
 MailMessage.From.Address := aFrom;
to
 MailMessage.From.text := aFrom;

and add a line
  MailMessage.Sender.text := aFrom;

that should make sure the problem is not because of bad code.

last resort is to send the email without using an inermediary smtp server, but relay it to the recipient smtp server. You have an example here: http://www.ciuly.com/delphi/indy/sendMail/index.html

but if you have multiple recipients, you will have to modify that example :)
0
 

Author Comment

by:KCTeam
ID: 20338360
I had already changed the code, and now i add your new advice :

var
    SMTP : TIdSMTP;
    MailMessage: TIdMessage;
    aHost, aUserName, aPassWord, cIniSmtpFileName, aFrom, aTo: string;
    aPort: integer;
    IniFile: TIniFile;
begin
  try
    cIniSmtpFileName := 'smtp.kp';
    if FileExists(ApplicationPath + cIniSmtpFileName) then
    begin
      IniFile := TIniFile.Create(ApplicationPath + cIniSmtpFileName);
      try
        aHost := IniFile.ReadString('SmtpConfig', 'Host', 'localhost');
        aPort := IniFile.ReadInteger('SmtpConfig', 'Port', 25);
        aFrom := IniFile.ReadString('SmtpConfig', 'From', 'xx@xx.com');
        aTo := IniFile.ReadString('SmtpConfig', 'To', 'xx@xx.com');

        SMTP := TIdSMTP.Create(self);
        SMTP.Host := aHost;
        SMTP.Port := aPort;

        MailMessage := TIdMessage.Create;
        MailMessage.From.Text := aFrom;
        MailMessage.Sender.Text := aFrom;
        MailMessage.Recipients.EMailAddresses := aTo;

        MailMessage.Subject := 'Un mail pour vous avertir';
        MailMessage.Body.Text := 'Blalala bla bla blabla bla';

        SMTP.Connect;
        SMTP.Send(MailMessage);
      finally
        FreeAndNil(IniFile);
        SMTP.Disconnect;
        SMTP.Free;
      end;
    end;
  except
    on E:Exception do
      LogException(E, 'Tsendemail.Execute 1');
  end;
  Response.content := '<html><body>Hello World !!!</body></html>';

I will make the test, with this code.

I have to mention also that i installed postfix-2.4.1-2 by rpm,
made a 'alternatives --config mta' and chose the /usr/sbin/sendmail.postfix program,
and reload postfix.
I ran a bash script to execute 1000 times the CGI. And good surprise, all of them were sent and recieved in my mailbox. As i'm not sure that it will always be like that, i will make again this test with the code i show you above.
0
 

Author Comment

by:KCTeam
ID: 20338751
with the code describe above, I sent 1000 emails, without any problems. As a test, I sent 2000 emails, then, 3 of them were not send with the exception :
An exception has occurred : EIdSMTPReplyError=kcdeditest.localdomain Error: timeout exceeded

The file maillog contains several error messages (more than 3)
 host gmail-smtp-in.l.google.com[72.14.221.27] refused to talk to me:    Our system has detected an unusual amount of unsolicited xxxx mail originating from your IP address. To protect our xxxx users from spam, mail sent from your IP address has been xxxx temporarily blocked. Please visit xxxx http://www.google.com/mail/help/bulk_mail.html to review xxxx our Bulk Email Senders Guidelines.

and also:
Nov 23 13:35:22 xxxx postfix/qmgr[10562]: 9439213003D: from=<xxx@xxx.com>, size=1310, nrcpt=1 (queue active)

It seems that it works.
Here, the configuration :
postfix/scache[24476]: statistics: max simultaneous domains=1 addresses=2 connection=20
0
 
LVL 28

Assisted Solution

by:2266180
2266180 earned 250 total points
ID: 20339511
the second error is obvious, I guess :)
the 3rd I don't know what to make out of it. I never saw that one before (or anything similar).

I would also like to apologies for my bad memory: I totally forgot that sendmail is actualy a very old email server :D so my first post is partially wrong. I was induced in error by me having for about 2-3 years otehr email servers that have a sendmail script that actually sends email and the name is probably kept like that for backward compatibility with the sendmail smtp server that came (comes?) by default with some of the linux distros.

again, sorry.

regarding the timeout, it could be that there were too many attempts to send an email in the same time. you could try and limit the number of concurrent executions of the cgi. unfortunatly I don't have any ideas what a good value that would be as I never needed to find out.
0
 

Author Comment

by:KCTeam
ID: 20351458
Thanks for all your help ;)
Sometimes, the send of the email is freezed, and i dont know why, do you know how to configure the smtp, at least the delay of a try ?
0
 
LVL 28

Assisted Solution

by:2266180
2266180 earned 250 total points
ID: 20351605
that depends on the smtp server. I for example am using xmail and there is no such settings to my knowledge.
probably a good idea would be to post on teh forum/group of the smtp server you are using (postfix, as I understood to be your last installed server)
0
 

Author Closing Comment

by:KCTeam
ID: 31410545
Many thanks for your help
0
 

Author Comment

by:KCTeam
ID: 20365154
Hello,
Just a last question ... sometines i have this exception, when the program try to send an email:
 An exception has occurred : EInvalidOp=Invalid floating point operation

if this exception occurs, it is catched and then i try to disconnect the smtp, before a free. It appears that the smtp can not disconnect. The only way, except to kill it, is to wait the timeout of cgi execution.
Due you have any ideas ? May i have to free the smtp without disconnect it before ? I'l try.
0
 
LVL 28

Expert Comment

by:2266180
ID: 20365372
it's a weird behaviour. It might be a bug in the indy smtp, I've seen (and fixed) a few the past few weeks. you should be able to disconnect the socket at any time. try to force the disconnect on the socket itself (idsmtp.socket.disconect or disconnectsocket or something like that. I don't have an ide open right now).
0
 

Author Comment

by:KCTeam
ID: 20365860
If i use a idsmtp.socket.close or idsmtp.socket.closegracefully, i lost the connexion, and my program stop.
0
 
LVL 28

Expert Comment

by:2266180
ID: 20366743
well .. that's what should happen in a disconnect, no? loose the connection.
0
 

Author Comment

by:KCTeam
ID: 20367303
Yes, but the problem is that the cgi finish as it is killed :

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>500 Internal Server Error</title>
</head><body>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error or
misconfiguration and was unable to complete
your request.</p>
<p>Please contact the server administrator,
 root@localhost and inform them of the time the error occurred,
and anything you might have done that may have
caused the error.</p>
<p>More information about this error may be available
in the server error log.</p>
<hr>

in the error.log of apache, there is:
Premature end of script headers: kp_synchro_debug.exe
0
 
LVL 28

Expert Comment

by:2266180
ID: 20367426
that can mean some other bug. maybe you are not catching a connection closed gracefully? make sure your code is well protected against unhandled exceptions.
0
 

Author Comment

by:KCTeam
ID: 20443109
Hello,
many thanks for your help.
I used indy-10.2.0.3, and i just tried to use indy-10.2.0.1, and now i do not have any problem anymore.
All of these problems seem to be due to bugs in the last version of Indy (use with Kylix).
Best regards
0

Featured Post

Free Tool: Postgres Monitoring System

A PHP and Perl based system to collect and display usage statistics from PostgreSQL databases.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Email security requires an ever evolving service that stays up to date with counter-evolving threats. The Email Laundry perform Research and Development to ensure their email security service evolves faster than cyber criminals. We apply our Threat…

733 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question