Jump to content
Ian Branch

Best way to check if an internet SMTP server is available?

Recommended Posts

Hi Team,

I have some SMTP email routines however I want to be able to check/confirm the ISPs smtp server is available before attempting to send the email.

Thoughts/suggestions appreciated.

 

Regards & TIA,

Ian

Share this post


Link to post

How would you check if your cars engine can start before drive? - Start the engine as you would do when you are going to drive?

 

So exactly the same with the SMTP server - connect to it. If it responds try to send the mail.

Share this post


Link to post

Hmmm.  Yes, I could do that but I would rather test if the server is available when the App is started, not when I want to send an email.

Share this post


Link to post

Just open a TCP connection to the server and you should get back a one line reply, that's all you need to see if it's online.  But it might be off-line by the time you send email.  And it might not accept email from you.  The ICS library now has a mail queue component that allows multiple email servers to be specified, and all those servers are attempted if any fail. 

 

Angus

 

Share this post


Link to post
11 minutes ago, Ian Branch said:

Hmmm.  Yes, I could do that but I would rather test if the server is available when the App is started, not when I want to send an email.

Well the result of the availability test is outdated in the moment you receive it. 

 

How will it help if you know the mail server was available 2 minutes ago and now when you want to send a mail it is not?

  • Like 1

Share this post


Link to post
1 hour ago, Ian Branch said:

Are they really that flaky?

Between the time you check connectivity and the time you want to send an email, your Internet connection may go down, or the Internet may encounter problems (DNS outages, DOS attacks, etc), or the server may go into maintenance mode, or ....  So, there is no real benefit to checking the connection ahead of time.  Simply attempt the connection at the time you actually want to send the email, and handle any errors that may occur at that time.  That is your simplest and best option.

  • Like 2

Share this post


Link to post

You have to deal with any errors that arise when you try it for real. Why do you feel the need to do more? 

Share this post


Link to post

Trying to save the User the hassle of creating the email in the first place if the SMTP Server is not available.

Share this post


Link to post
1 hour ago, Ian Branch said:

Trying to save the User the hassle of creating the email in the first place if the SMTP Server is not available.

Mailservers are run by inbound and outbound queues.  One of their main jobs is to handle this issue.  If you are writing a mail server then you are required to properly manage outbound mail queues.  If you are sending a message, just send it unless there is some industry specific requirement for non-standard email delivery.

Share this post


Link to post

Hi Team,

Perhaps I am looking at this from the wrong perspective.

The primary issue is the Customers Internet access/availability.  The Customers are based in the Pacific and their Internet/ISPs tend to be a little iffy.

Yesterday, one of the Customer's Internet access was down for 3 hours. :-(

I think instead of testing for the smtp server I will simply test for the ability to access the internet with something like this..

uses
...., wininet;

Function CheckUrl(url: string): Boolean;
var
  hSession, hfile, hRequest: hInternet;
  dwindex, dwcodelen: dword;
  dwcode: array [1 .. 20] of char;
  res: pchar;
begin
  if pos('http://', lowercase(url)) = 0 then
    url := 'http://' + url;
  Result := False;
  hSession := InternetOpen('InetURL:/1.0', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if assigned(hSession) then
  begin
    hfile := InternetOpenUrl(hSession, pchar(url), nil, 0, INTERNET_FLAG_RELOAD, 0);
    dwindex := 0;
    dwcodelen := 10;
    HttpQueryInfo(hfile, HTTP_QUERY_STATUS_CODE, @dwcode, dwcodelen, dwindex);
    res := pchar(@dwcode);
    Result := (res = '200') or (res = '302');
    if assigned(hfile) then
      InternetCloseHandle(hfile);
    InternetCloseHandle(hSession);
  end;

end;

Just prior to the email creation.

 

Regards,

Ian

Share this post


Link to post

I expect that if you do that you'll have clients complaining that your program refuses to send mail when it would succeed if it tried to do so. 

Share this post


Link to post
12 hours ago, David Heffernan said:

I expect that if you do that you'll have clients complaining that your program refuses to send mail when it would succeed if it tried to do so. 

David, Can you be more clear why you're saying that?

Is the test he's doing not reliable, or are you simply saying if the test succeeds, the server may come back up during the interval between the test and the email send.

Share this post


Link to post
26 minutes ago, Tom F said:

Is the test he's doing not reliable

It's very hard to reproduce the exact series of steps which are undertaken when sending an email. And why bother? Since you have to handle the case when it fails for real, why not use that? 

 

The best code is the code that doesn't exist. Can't be a defect in code that doesn't exist. 

Share this post


Link to post

What we all want to say:

 

If there is a mail to send, then try to send the mail and catch the exception if it was not successful. Notify the user that it cannot deliver the mail in this moment but it will retry in x minutes.

Share this post


Link to post

<o>

 

And what if the smtp server works when your app starts, but then I shut it down?
 

on every IO, file / network / etc.... try it / catch the error / do what you want

Share this post


Link to post
Posted (edited)

I agree to what was said before, but maybe this and this info helps for additional tests.

Edited by Rollo62

Share this post


Link to post

This is where it helps to be an old-timer and remember how things worked back in the early days of the internet. 

 

The internet was developed by DARPA in the 60s during the Cold War, when the threat of nuclear war lingered in the air and shaped the way people designed things.

 

DARPA wanted to design a large network of independent computers that had no single-point-of-failure in case major cities with central servers got nuked -- literally. 

 

Everything was done by dial-up at the time. That is to say, unless you could afford a dedicated phone line, there was no such thing as an "always-on connection" the way we experience things today.

 

And dial-up was slower than molasses in the winter time. I remember 150 baud in the early 70's. Then 300 baud. In 1990, 2400 baud was fast. In the mid-90s, a "high-speed connection" was a dial-up line with a modem that ran at 9600 baud.

 

In effect, virtually 100% of home users experienced what you're trying to argue against as their "normal" use-case. The server (or wherever your emails went next) was NEVER connected. Guaranteed. 

 

In fact, the solution for eliminating a single-point-of-failure scenario was to make the entire internet backbone work using store-and-forward mechanisms.

 

They also took this approach because it would be unworkable to have thousands of computers attempting to dial-in to your computer directly just to drop a couple of emails. 

 

(In 1988 I did some work for a guy who literally had 25 phone lines coming into his office to support a couple thousand users who'd dial in to connect to his minicomputer that was used to allow search and download county assessor tax records. They charged something like $500/mo per account. He had me write some special driver software that tweaked the 1200 baud modems connected to each of those phone lines.)

 

So servers were set up to collect stuff, then forward it on to the next server closer to the destination, until each email finally made it to an ISP that hosted that email.

 

ONE SIMPLY DID NOT CONNECT DIRECTLY TO THE DESTINATION MTA! EVER!!!!

 

That's just not how things were designed to work.

 

Back in the days of dial-up access, we all remember times when we'd try to connect and the line would be dead. Or someone would be on the phone (or party line). Or it would be busy. Or the number was disconnected. 

 

THIS WAS  N-O-R-M-A-L.

 

It was also pretty normal to be in the middle of a dial-up session and someone in your home would pick up the phone in another room and the line would drop.

 

So we'd get online late at night when we knew nobody was going to try to make a call. (Generally speaking, nobody called anybody after 10PM.)

 

And THIS is EXACTLY how the internet in general, and mail delivery specifically, was designed to work.

 

You seem to want to be able to assume otherwise.

 

Just build a mail agent designed to work they way MTAs are SUPPOSED to work and save yourself some grief.

 

You can find the actual RFC spec for how SMTP was designed to work here:  https://tools.ietf.org/html/rfc5321

 

If you go back and look at earlier specs, you'll see that not much has changed since the original specs were written in the 60's.

 

  • Like 1

Share this post


Link to post
Posted (edited)
6 hours ago, Rollo62 said:

I agree to what was said before, but maybe this and this info helps for additional tests.

You do not really have to read that. A simple TIdSMTP.Connect will do this

Edited by Schokohase

Share this post


Link to post

I prefer to defer the actual sending to a regular mail client.  Then it gets sent whenever mail is actually working.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×