Archive for December, 2007

Lookup using MX record to validate mail server

The best you can do to verify if an email address is real is to verify if there is a mail server registered to the domain name.

import  java.util.Hashtable;
import  javax.naming.*;
import  javax.naming.directory.*;

public class MXLookup {
  public static void main( String args[] ) {
    if( args.length == 0 ) {
      System.err.println( "Usage: MXLookup host [...]" );
      System.exit( 99 );
    }
    for( int i = 0; i < args.length; i++ ) {
      try {
        System.out.println( args[i] + " has " +
          doLookup( args[i] ) + " mail servers" );
      }
      catch( Exception e ) {
        System.out.println(args[i] + " : " + e.getMessage());
      }
    }
  }

  static int doLookup( String hostName ) throws NamingException {
    Hashtable env = new Hashtable();
    env.put("java.naming.factory.initial",
            "com.sun.jndi.dns.DnsContextFactory");
    DirContext ictx = new InitialDirContext( env );
    Attributes attrs =
       ictx.getAttributes( hostName, new String[] { "MX" });
    Attribute attr = attrs.get( "MX" );
    if( attr == null ) return( 0 );
    return( attr.size() );
  }
}

The output is

<java MXLookup rgagnon.com realhowto.com
rgagnon.com has 1 mail servers
realhowto.com : DNS name not found [response code 3]

From T. Orbaker, more infos on that subject (thanks to him).

There are other methods by which to validate an email address to a higher degree of than just the mail server.

One:
Use the VRFY command (see RFCs 821/2821). Because this was abused by spammers, it have typically been disabled on most mail servers. Some recent servers don't even support this command as they are so frequently shut off.

When it works, connect to the server, issue the HELO command and then send 'VRFY '. If it is enabled, and the address is valid, you should get a 250 if the address is valid and a 550 if it isn't. Note that some servers (qmail) return 252 as a means of pleading the fifth. Others will return a failure even if the address exists but the command has been disables (although this is typically a 450 error).

Two (better method):
Connect to the servers determined by your code snippet. BUT (and the code below doesn't do this) they must be tried from lowest preference to highest to be absolutely correct.

Once you have connected, you create the SMTP envelope, but you don't put anything in it. This is the point at which most servers will give up the dirt on whether or not an address is valid. If an envelope cannot be built, we know that the address is invalid.

The reason for connecting in order of preference:

Imagine ABC company has an Internet conneciton and runs their own mail server for abc.com. To prevent bounces and other mail errors if their connection or server should be down, their provider isp.com agrees to set up a 'store and forward' scheme for their mail. If abc.com is not available, then isp.com gets the message and when abc.com is again available, the message gets forwarded. The MX records would look something like:
MX 1 abc.com
MX 5 isp.com

Now, imagine that you connect to isp.com and try to send a message. The mail server at isp.com doesn't have the actual user list to know which addresses are valid, it just accepts everything and relies on abc.com to sort out the bounces.

If these are not checked in the proper order, there will be no errors for invalid addresses.

Yahoo appears to use a store and forward mechanism to its own internal servers, thus conclusively verifying a yahoo address is not possible. I suspect that hotmail is the same.

It is not possible to verify an address on a domain that uses a catch-all account as the catch account will receive the mail (it does, however, mean that someone will at least SEE the message).

import java.io.*;
import java.net.*;
import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;

public class SMTP {
    private static int hear( BufferedReader in ) throws IOException {
      String line = null;
      int res = 0;

      while ( (line = in.readLine()) != null ) {
          String pfx = line.substring( 0, 3 );
          try {
             res = Integer.parseInt( pfx );
          }
          catch (Exception ex) {
             res = -1;
          }
          if ( line.charAt( 3 ) != '-' ) break;
      }

      return res;
      }

    private static void say( BufferedWriter wr, String text )
       throws IOException {
      wr.write( text + "\r\n" );
      wr.flush();

      return;
      }

    private static ArrayList getMX( String hostName )
          throws NamingException {
      // Perform a DNS lookup for MX records in the domain
      Hashtable env = new Hashtable();
      env.put("java.naming.factory.initial",
              "com.sun.jndi.dns.DnsContextFactory");
      DirContext ictx = new InitialDirContext( env );
      Attributes attrs = ictx.getAttributes
                            ( hostName, new String[] { "MX" });
      Attribute attr = attrs.get( "MX" );

      // if we don't have an MX record, try the machine itself
      if (( attr == null ) || ( attr.size() == 0 )) {
        attrs = ictx.getAttributes( hostName, new String[] { "A" });
        attr = attrs.get( "A" );
        if( attr == null )
             throw new NamingException
                      ( "No match for name '" + hostName + "'" );
      }

      // Huzzah! we have machines to try. Return them as an array list
      // NOTE: We SHOULD take the preference into account to be absolutely
      //   correct. This is left as an exercise for anyone who cares.
      ArrayList res = new ArrayList();
      NamingEnumeration en = attr.getAll();

      while ( en.hasMore() ) {
         String x = (String) en.next();
         String f[] = x.split( " " );
         if ( f[1].endsWith( "." ) )
             f[1] = f[1].substring( 0, (f[1].length() - 1));
         res.add( f[1] );
      }
      return res;
      }

    public static boolean isAddressValid( String address ) {
      // Find the separator for the domain name
      int pos = address.indexOf( '@' );

      // If the address does not contain an '@', it's not valid
      if ( pos == -1 ) return false;

      // Isolate the domain/machine name and get a list of mail exchangers
      String domain = address.substring( ++pos );
      ArrayList mxList = null;
      try {
         mxList = getMX( domain );
      }
      catch (NamingException ex) {
         return false;
      }

      // Just because we can send mail to the domain, doesn't mean that the
      // address is valid, but if we can't, it's a sure sign that it isn't
      if ( mxList.size() == 0 ) return false;

      // Now, do the SMTP validation, try each mail exchanger until we get
      // a positive acceptance. It *MAY* be possible for one MX to allow
      // a message [store and forwarder for example] and another [like
      // the actual mail server] to reject it. This is why we REALLY ought
      // to take the preference into account.
      for ( int mx = 0 ; mx < mxList.size() ; mx++ ) {
          boolean valid = false;
          try {
              int res;
              Socket skt = new Socket( (String) mxList.get( mx ), 25 );
              BufferedReader rdr = new BufferedReader
                 ( new InputStreamReader( skt.getInputStream() ) );
              BufferedWriter wtr = new BufferedWriter
                 ( new OutputStreamWriter( skt.getOutputStream() ) );

              res = hear( rdr );
              if ( res != 220 ) throw new Exception( "Invalid header" );
              say( wtr, "EHLO orbaker.com" );

              res = hear( rdr );
              if ( res != 250 ) throw new Exception( "Not ESMTP" );

              // validate the sender address
              say( wtr, "MAIL FROM: " );
              res = hear( rdr );
              if ( res != 250 ) throw new Exception( "Sender rejected" );

              say( wtr, "RCPT TO: <" + address + ">" );
              res = hear( rdr );

              // be polite
              say( wtr, "RSET" ); hear( rdr );
              say( wtr, "QUIT" ); hear( rdr );
              if ( res != 250 )
                 throw new Exception( "Address is not valid!" );

              valid = true;
              rdr.close();
              wtr.close();
              skt.close();
          }
          catch (Exception ex) {
            // Do nothing but try next host
          }
          finally {
            if ( valid ) return true;
          }
      }
      return false;
      }

    public static void main( String args[] ) {
      String testData[] = {
          "tim@orbaker.com", // Valid address
          "fail.me@nowhere.spam", // Invalid domain name
          "arkham@bigmeanogre.net", // Invalid address
          "nosuchaddress@yahoo.com" // Failure of this method
          };

      for ( int ctr = 0 ; ctr < testData.length ; ctr++ ) {
         System.out.println( testData[ ctr ] + " is valid? " +
               isAddressValid( testData[ ctr ] ) );
      }
      return;
      }
}

from http://www.rgagnon.com/javadetails/java-0452.html

Share and Enjoy:
  • Digg
  • del.icio.us
  • Netvouz
  • DZone
  • ThisNext
  • MisterWong
  • Wists
  • BlinkList
  • blogmarks
  • blogtercimlap
  • connotea
  • DotNetKicks
  • Fark
  • Fleck
  • Gwar
  • Haohao
  • IndianPad
  • Internetmedia
  • LinkaGoGo
  • MyShare
  • Netscape
  • NewsVine
  • Rec6
  • Reddit
  • Scoopeo
  • Slashdot
  • StumbleUpon
  • Technorati
  • Webride

Get the full $50 discount on Dreamhost web hosting

This is the maximum savings you can get from Dreamhost! Along with $50 being the maximum amount you can save, we have setup some additional codes that you may select from to add additional features if you need them. Click the promo code beside the offer to activate:

Offer Promo Code
$50 off + 1 domain registration for life(Saving $65) RUBYPDF1DOMAIN50
$50 off + 2 domain registrations for life(Saving $85) RUBYPDF2DOMAIN50
$50 off + 3 domain registrations(Saving $95) RUBYPDF3DOMAIN50
$50 off + 1 domain registrations + Unique IP Address for life(Saving $95) RUBYPDF1D1IP50
$50 off + 1 domain registrations+ 30% bonus to the monthly bandwidth(Saving $92) RUBYPDF1DBW

Unlike a lot of other promo codes, these codes give you the maximum possible discount for ALL dreamhost payment periods. There is no need to look any further, you are guaranteed the maximum discount on whichever payment plan you choose one of the offers above.

Dreamhost has moved to a one-size-fits-all hosting solution, so there are no tricky plans to choose from, though there are different payment periods that you may select from. To see the amount you can save depending on the payment period you select, please see the table below:

Payment Period Cost Max
Discount
This Code’s
Discount
Total cost for
length of Period
Monthly $60.90 (1 month @ $10.95 + $49.95 setup) $50.00 $50.00 $10.90
Yearly $119.40 (+ free setup) $50.00 $50.00 $69.40 Best Deal!
Two Years $214.80 (+ free setup) $50.00 $50.00 $164.80
Three Years $286.20 (+ free setup) $50.00 $50.00 $236.20
Five Years $417.00 (+ free setup) $50.00 $50.00 $367.00
Ten Years $714.00 (+ free setup) $50.00 $50.00 $664.00

Still not sure? Sign onto the Yearly payment plan with promo code “RUBYPDF1DOMAIN50” and you can try out all these features for a whole year for only $69.40 (less than $6/month). If you are not happy with your service, Dreamhost gives you 97 days to cancel and receive your money back.

  • A minimum of 5TB (5000 GB) of monthly bandwidth for the lowest-level plan (increases by 40GB/week)
  • A minimum of 500 GB of disk space for the lowest-level plan (increases by 2GB/week)
  • 1 free domain registration (and free as long as you keep your account)
  • Snapshot backups, which transparently backs up all your files hourly, weekly and monthly. These backups are available online without having to request access to them.
  • Ability to host unlimited domains and subdomains
  • Unlimited accounts with both SSH shell access and FTP access
  • SpamAssassin & Squirrelmail Webmail
  • Mailing lists and Auto Responders
  • Full cron control
  • MySQL, php4, phjp5, FastCGI, Ruby on Rails
  • 1-click installs (Wordpress, phpBB, MediaWiki, Joomla, Gallery and more)
  • View full list of features

With this promotion, we are giving away the maximum discount that Dreamhost allows for referrals. You may be asking why we would do this and what’s in it for us. Well, we do get something. We get a percentage of everyone you refer to Dreamhost. We ask that you refer them from your account, and should you wish to give them a $50 discount as well, you will be able to generate your own customized promo codes for your friends and family.

btw, If you need others Promo Code that I can give, please let me know

Share and Enjoy:
  • Digg
  • del.icio.us
  • Netvouz
  • DZone
  • ThisNext
  • MisterWong
  • Wists
  • BlinkList
  • blogmarks
  • blogtercimlap
  • connotea
  • DotNetKicks
  • Fark
  • Fleck
  • Gwar
  • Haohao
  • IndianPad
  • Internetmedia
  • LinkaGoGo
  • MyShare
  • Netscape
  • NewsVine
  • Rec6
  • Reddit
  • Scoopeo
  • Slashdot
  • StumbleUpon
  • Technorati
  • Webride

Dreamhost Stops $97 Discount Promo Codes from 2007-12-11

Dreamhost webhosting runs a very popular affiliate referral program called Dreamhost rewards where webmasters on Dreamhost web hosting could earn $97 per referral, or pass on the benefit to new subscribers by issuing promo codes for a maximum $97 discount. Dreamhost has now capped the discount ot a maximum of $50. Grab the $97 discount coupons while you can…

Dreamhost Affiliate Program

The Dreamhost Rewards program basically has 2 Options -
Option 1: One Time Payments – Each new customer that you refer get you $97. Each new customer that THEY refer adds $5!

Option 2: Recurring Payments – You’ll earn 10% of EVERY payment that your referrals EVER make! You earn 5% of EVERY payment that THEIR referrals make – for as long as they remain customers.

Dreamhost Promo Codes

Now these webmasters could share a part of the referral revenue by offering promo codes that would discount the offer for new subscribers and make them less money. For example, if I offered a $90 discount promo code, a new subscriber gets $90 discount, while the referrer earns $7 per referral. The promo codes could be to a maximum of $97 which would offer maximum discount while earning zero referral revenue.

Promo Codes Max out at $50

I just recieved the Dreamhost newsletter by email which says that starting from December 11th, NO DreamHost promo code can give a discount greater than $50! All new and existing codes will be capped at this amount.

The wonderful benefit to webmasters is that the affiliate deal is still $97 per referral, and since the discount can’t be more than $50 using any coupon code, you earn $47 at least even if a maxed out promo code is used.

Dreamhost Affiliates will earn more

The lesser discount promo codes rarely worked for me, as there are so many people offering $90+ discounts, that the referral earnings were too low. By this new deal, it will mean that you earn $47 or more per referral as the discounts will be capped at $50. This is great news for affiliates, for whom this might turn out be a high paying affiliate program finally.

Share and Enjoy:
  • Digg
  • del.icio.us
  • Netvouz
  • DZone
  • ThisNext
  • MisterWong
  • Wists
  • BlinkList
  • blogmarks
  • blogtercimlap
  • connotea
  • DotNetKicks
  • Fark
  • Fleck
  • Gwar
  • Haohao
  • IndianPad
  • Internetmedia
  • LinkaGoGo
  • MyShare
  • Netscape
  • NewsVine
  • Rec6
  • Reddit
  • Scoopeo
  • Slashdot
  • StumbleUpon
  • Technorati
  • Webride