blackbook 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/History.txt +18 -0
  2. data/Manifest.txt +55 -0
  3. data/README.txt +71 -0
  4. data/Rakefile +38 -0
  5. data/init.rb +1 -0
  6. data/lib/blackbook.rb +80 -0
  7. data/lib/blackbook/exporter/base.rb +16 -0
  8. data/lib/blackbook/exporter/vcf.rb +45 -0
  9. data/lib/blackbook/exporter/xml.rb +28 -0
  10. data/lib/blackbook/importer/aol.rb +74 -0
  11. data/lib/blackbook/importer/base.rb +39 -0
  12. data/lib/blackbook/importer/csv.rb +61 -0
  13. data/lib/blackbook/importer/gmail.rb +59 -0
  14. data/lib/blackbook/importer/hotmail.rb +125 -0
  15. data/lib/blackbook/importer/page_scraper.rb +86 -0
  16. data/lib/blackbook/importer/yahoo.rb +61 -0
  17. data/test/fixtures/aol_bad_login_response_stage_3.html +565 -0
  18. data/test/fixtures/aol_contacts.html +90 -0
  19. data/test/fixtures/aol_login_response_stage_1.html +158 -0
  20. data/test/fixtures/aol_login_response_stage_2.html +559 -0
  21. data/test/fixtures/aol_login_response_stage_3.html +61 -0
  22. data/test/fixtures/aol_login_response_stage_4.html +48 -0
  23. data/test/fixtures/aol_login_response_stage_5.html +404 -0
  24. data/test/fixtures/gmail.csv +3 -0
  25. data/test/fixtures/gmail_bad_login_response_stage_2.html +560 -0
  26. data/test/fixtures/gmail_contacts.html +228 -0
  27. data/test/fixtures/gmail_login_response_stage_1.html +556 -0
  28. data/test/fixtures/gmail_login_response_stage_2.html +1 -0
  29. data/test/fixtures/gmail_login_response_stage_3.html +249 -0
  30. data/test/fixtures/hotmail_bad_login_response_stage_2.html +31 -0
  31. data/test/fixtures/hotmail_contacts.html +132 -0
  32. data/test/fixtures/hotmail_login_response_stage_1.html +31 -0
  33. data/test/fixtures/hotmail_login_response_stage_2.html +1 -0
  34. data/test/fixtures/hotmail_login_response_stage_3.html +380 -0
  35. data/test/fixtures/yahoo_bad_login_response_stage_2.html +443 -0
  36. data/test/fixtures/yahoo_contacts.csv +3 -0
  37. data/test/fixtures/yahoo_contacts_not_logged_in.html +432 -0
  38. data/test/fixtures/yahoo_contacts_stage_1.html +399 -0
  39. data/test/fixtures/yahoo_login_response_stage_1.html +433 -0
  40. data/test/fixtures/yahoo_login_response_stage_2.html +16 -0
  41. data/test/scripts/live_test.rb +25 -0
  42. data/test/test_blackbook.rb +60 -0
  43. data/test/test_blackbook_exporter_base.rb +16 -0
  44. data/test/test_blackbook_exporter_vcf.rb +52 -0
  45. data/test/test_blackbook_exporter_xml.rb +16 -0
  46. data/test/test_blackbook_importer_aol.rb +107 -0
  47. data/test/test_blackbook_importer_base.rb +24 -0
  48. data/test/test_blackbook_importer_csv.rb +60 -0
  49. data/test/test_blackbook_importer_gmail.rb +96 -0
  50. data/test/test_blackbook_importer_hotmail.rb +143 -0
  51. data/test/test_blackbook_importer_page_scraper.rb +51 -0
  52. data/test/test_blackbook_importer_yahoo.rb +97 -0
  53. data/test/test_helper.rb +47 -0
  54. data/vendor/plugins/blackbook/lib/autotest/blackbook.rb +27 -0
  55. data/vendor/plugins/blackbook/lib/autotest/discover.rb +3 -0
  56. metadata +147 -0
@@ -0,0 +1,61 @@
1
+ require 'fastercsv'
2
+
3
+ ##
4
+ # Imports contacts from a CSV file
5
+
6
+ class Blackbook::Importer::Csv < Blackbook::Importer::Base
7
+
8
+ DEFAULT_COLUMNS = [:name,:email,:misc]
9
+
10
+ ##
11
+ # Matches this importer to a file that contains CSV values
12
+
13
+ def =~(options)
14
+ options && options[:file].respond_to?(:open) ? true : false
15
+ end
16
+
17
+ ##
18
+ # fetch_contacts! implementation for this importer
19
+
20
+ def fetch_contacts!
21
+ lines = IO.readlines(options[:file].path)
22
+ columns = to_columns(lines.first)
23
+ lines.shift if columns.first == :name
24
+ columns = DEFAULT_COLUMNS.dup unless columns.first == :name
25
+
26
+ contacts = Array.new
27
+ lines.each do |l|
28
+ vals = l.split(',')
29
+ next if vals.empty?
30
+ contacts << to_hash(columns, vals)
31
+ end
32
+
33
+ contacts
34
+ end
35
+
36
+ def to_hash(cols, vals) # :nodoc:
37
+ h = Hash.new
38
+ cols.each do |c|
39
+ h[c] = (c == cols.last) ? vals.join(',') : vals.shift
40
+ end
41
+ h
42
+ end
43
+
44
+ def to_columns(line) # :nodoc:
45
+ columns = Array.new
46
+ tags = line.split(',')
47
+ # deal with "Name,E-mail..." oddity up front
48
+ if tags.first =~ /^name$/i
49
+ tags.shift
50
+ columns << :name
51
+ if tags.first =~ /^e.?mail/i # E-mail or Email
52
+ tags.shift
53
+ columns << :email
54
+ end
55
+ end
56
+ tags.each{|v| columns << v.strip.to_sym}
57
+ columns
58
+ end
59
+
60
+ Blackbook.register(:csv, self)
61
+ end
@@ -0,0 +1,59 @@
1
+ require 'blackbook/importer/page_scraper'
2
+
3
+ ##
4
+ # Imports contacts from GMail
5
+
6
+ class Blackbook::Importer::Gmail < Blackbook::Importer::PageScraper
7
+
8
+ ##
9
+ # Matches this importer to an user's name/address
10
+
11
+ def =~(options = {})
12
+ options && options[:username] =~ /@gmail.com$/i ? true : false
13
+ end
14
+
15
+ ##
16
+ # login to gmail
17
+
18
+ def login
19
+ page = agent.get('http://mail.google.com/')
20
+ form = page.forms.first
21
+ form.Email = options[:username]
22
+ form.Passwd = options[:password]
23
+ page = agent.submit(form,form.buttons.first)
24
+
25
+ raise( Blackbook::BadCredentialsError, "That username and password was not accepted. Please check them and try again." ) if page.body =~ /Username and password do not match/
26
+
27
+ url = page.search('//meta').first.attributes['content'].split('URL=').last rescue nil
28
+ page = agent.get url
29
+ end
30
+
31
+ ##
32
+ # prepare this importer
33
+
34
+ def prepare
35
+ login
36
+ end
37
+
38
+ ##
39
+ # scrape gmail contacts for this importer
40
+
41
+ def scrape_contacts
42
+ unless agent.cookies.find{|c| c.name == 'GAUSR' &&
43
+ c.value == "mail:#{options[:username]}"}
44
+ raise( Blackbook::BadCredentialsError, "Must be authenticated to access contacts." )
45
+ end
46
+
47
+ page = agent.get('http://mail.google.com/mail/h/?v=cl&pnl=a')
48
+ contact_rows = page.search("input[@name='c']/../..")
49
+ contact_rows.collect do |row|
50
+ columns = row/"td"
51
+ {
52
+ :name => ( columns[1] / "b" ).inner_html, # name
53
+ :email => columns[2].inner_html.gsub( /(\n|&nbsp;)/, '' ) # email
54
+ }
55
+ end
56
+ end
57
+
58
+ Blackbook.register(:gmail, self)
59
+ end
@@ -0,0 +1,125 @@
1
+ require 'blackbook/importer/page_scraper'
2
+ require 'cgi'
3
+
4
+ ##
5
+ # imports contacts for MSN/Hotmail
6
+ class Blackbook::Importer::Hotmail < Blackbook::Importer::PageScraper
7
+
8
+ DOMAINS = { "compaq.net" => "https://msnia.login.live.com/ppsecure/post.srf",
9
+ "hotmail.co.jp" => "https://login.live.com/ppsecure/post.srf",
10
+ "hotmail.co.uk" => "https://login.live.com/ppsecure/post.srf",
11
+ "hotmail.com" => "https://login.live.com/ppsecure/post.srf",
12
+ "hotmail.de" => "https://login.live.com/ppsecure/post.srf",
13
+ "hotmail.fr" => "https://login.live.com/ppsecure/post.srf",
14
+ "hotmail.it" => "https://login.live.com/ppsecure/post.srf",
15
+ "messengeruser.com" => "https://login.live.com/ppsecure/post.srf",
16
+ "msn.com" => "https://msnia.login.live.com/ppsecure/post.srf",
17
+ "passport.com" => "https://login.live.com/ppsecure/post.srf",
18
+ "webtv.net" => "https://login.live.com/ppsecure/post.srf" }
19
+
20
+ ##
21
+ # Matches this importer to an user's name/address
22
+
23
+ def =~(options)
24
+ return false unless options && options[:username]
25
+ domain = username_domain(options[:username].downcase)
26
+ !domain.blank? && DOMAINS.keys.include?( domain ) ? true : false
27
+ end
28
+
29
+ ##
30
+ # Login procedure
31
+ # 1. Go to login form
32
+ # 2. Set login and passwd
33
+ # 3. Set PwdPad to IfYouAreReadingThisYouHaveTooMuchFreeTime minus however many characters are in passwd (so if passwd
34
+ # was 8 chars, you'd chop 8 chars of the end of IfYouAreReadingThisYouHaveTooMuchFreeTime - giving you IfYouAreReadingThisYouHaveTooMuch)
35
+ # 4. Set the action to the appropriate URL for the username's domain
36
+ # 5. Get the query string to append to the new action
37
+ # 5. Submit the form and parse the url from the resulting page's javascript
38
+ # 6. Go to that url
39
+
40
+ def login
41
+ page = agent.get('http://login.live.com/login.srf?id=2')
42
+ form = page.forms.first
43
+ form.login = options[:username]
44
+ form.passwd = options[:password]
45
+ form.PwdPad = ( "IfYouAreReadingThisYouHaveTooMuchFreeTime"[0..(-1 - options[:password].to_s.size )])
46
+ query_string = page.body.scan(/g_QS="([^"]+)/).first.first rescue nil
47
+ form.action = login_url + "?#{query_string.to_s}"
48
+ page = agent.submit(form)
49
+
50
+ # Check for login success
51
+ if page.body =~ /The e-mail address or password is incorrect/ ||
52
+ page.body =~ /Sign in failed\./
53
+ raise( Blackbook::BadCredentialsError,
54
+ "That username and password was not accepted. Please check them and try again." )
55
+ end
56
+
57
+ page = agent.get( page.body.scan(/http\:\/\/[^"]+/).first )
58
+ end
59
+
60
+ ##
61
+ # prepare this importer
62
+
63
+ def prepare
64
+ login
65
+ end
66
+
67
+ ##
68
+ # Scrape contacts for Hotmail
69
+ # Seems like a POST to directly fetch CSV contacts from options.aspx?subsection=26&n=
70
+ # raises an end of file error in Net::HTTP via Mechanize.
71
+ # Seems like Hotmail addresses are now hosted on Windows Live.
72
+
73
+ def scrape_contacts
74
+ unless agent.cookies.find{|c| c.name == 'MSPPre' && c.value == options[:username]}
75
+ raise( Blackbook::BadCredentialsError, "Must be authenticated to access contacts." )
76
+ end
77
+
78
+ page = agent.get('PrintShell.aspx?type=contact')
79
+ rows = page.search("//div[@class='ContactsPrintPane cPrintContact BorderTop']")
80
+ rows.collect do |row|
81
+ name = row.search("//div[@class='cDisplayName']").first.innerText.strip
82
+ name = name[0,(name.size-3)] # char 142 is last char of clean text
83
+
84
+ vals = {}
85
+ row.search("/table/tr").each do |pair|
86
+ key = pair.search("/td[@class='TextAlignRight Label']").first.innerText.strip
87
+ val = pair.search("/td[@class='Value']").first.innerText.strip
88
+ vals[key.to_sym] = val
89
+ end
90
+ vals[:name] = name
91
+ vals[:email] = (vals['Personal e-mail'.to_sym] || vals['Work e-mail'.to_sym]).split(' ').first rescue ''
92
+ vals
93
+ end
94
+ end
95
+
96
+ ##
97
+ # lookup for the login service that should be used based on the user's
98
+ # address
99
+
100
+ def login_url
101
+ DOMAINS[username_domain] || DOMAINS['hotmail.com']
102
+ end
103
+
104
+
105
+ ##
106
+ # normalizes the host for the page that is currently being "viewed" by the
107
+ # Mechanize agent
108
+
109
+ def current_host
110
+ return nil unless agent && agent.current_page
111
+ uri = agent.current_page.uri
112
+ "#{uri.scheme}://#{uri.host}"
113
+ end
114
+
115
+ ##
116
+ # determines the domain for the user
117
+
118
+ def username_domain(username = nil)
119
+ username ||= options[:username] if options
120
+ return unless username
121
+ username.to_s.split('@').last
122
+ end
123
+
124
+ Blackbook.register(:hotmail, self)
125
+ end
@@ -0,0 +1,86 @@
1
+ require 'rubygems'
2
+ gem 'mechanize', '>= 0.7.0'
3
+ require 'mechanize'
4
+ require 'generator' # for SyncEnumerator
5
+
6
+ # Patch Mechanize's broken html unescaping Mechanize 0.6.11
7
+ class WWW::Mechanize
8
+ def to_absolute_uri(url, cur_page=current_page())
9
+ unless url.is_a? URI
10
+ url = url.to_s.strip
11
+ url = URI.parse(
12
+ self.class.html_unescape(
13
+ SyncEnumerator.new(
14
+ url.split(/%[0-9A-Fa-f]{2}/), url.scan(/%[0-9A-Fa-f]{2}/)
15
+ ).map { |x,y|
16
+ "#{URI.escape(x||'')}#{y}"
17
+ }.join('').gsub(/%23/, '#')
18
+ )
19
+ )
20
+ # Mechanize here uses #zip to combine the two arrays, which will ignore
21
+ # excessive elements of the second array (the one which is passed as an
22
+ # argument). That means if the URL ends with more than one already escaped
23
+ # character, then only the first one will be restored into the resulting
24
+ # URL.
25
+ end
26
+
27
+ # construct an absolute uri
28
+ if url.relative?
29
+ raise 'no history. please specify an absolute URL' unless cur_page.uri
30
+ url = cur_page.uri + url
31
+ # Strip initial "/.." bits from the path
32
+ url.path.sub!(/^(\/\.\.)+(?=\/)/, '')
33
+ end
34
+
35
+ return url
36
+ end
37
+ end
38
+
39
+ ##
40
+ # A base class for importers that scrape their contacts from web services
41
+
42
+ class Blackbook::Importer::PageScraper < Blackbook::Importer::Base
43
+
44
+ attr_accessor :agent
45
+
46
+ ##
47
+ # creates the Mechanize agent used to do the scraping and sets a nice
48
+ # user agent header for good net educate
49
+
50
+ def create_agent
51
+ self.agent = WWW::Mechanize.new
52
+ agent.user_agent = "Mozilla/4.0 (compatible; Blackbook #{Blackbook::VERSION})"
53
+ agent.keep_alive = false
54
+ agent
55
+ end
56
+
57
+ ##
58
+ # Page scrapers will follow a fairly simple pattern of instantiating the
59
+ # agent, prepping for the scrape and then the actual scrape process
60
+
61
+ def fetch_contacts!
62
+ create_agent
63
+ prepare
64
+ scrape_contacts
65
+ end
66
+
67
+ ##
68
+ # Providers will often require you to login or otherwise prepare to actual
69
+ # scrape the contacts
70
+
71
+ def prepare; end # stub
72
+
73
+ ##
74
+ # Some providers have a single page you can scrape from (like Gmail's HTML
75
+ # Contacts page) while others might require you to navigate several pages,
76
+ # scraping as you go.
77
+
78
+ def scrape_contacts; end # stub
79
+
80
+ ##
81
+ # helper to strip html from text
82
+
83
+ def strip_html( html )
84
+ html.gsub(/<\/?[^>]*>/, '')
85
+ end
86
+ end
@@ -0,0 +1,61 @@
1
+ require 'blackbook/importer/page_scraper'
2
+ require 'fastercsv'
3
+
4
+ ##
5
+ # contacts importer for Yahoo!
6
+
7
+ class Blackbook::Importer::Yahoo < Blackbook::Importer::PageScraper
8
+
9
+ ##
10
+ # Matches this importer to an user's name/address
11
+
12
+ def =~(options = {})
13
+ options && options[:username] =~ /@yahoo.com$/i ? true : false
14
+ end
15
+
16
+ ##
17
+ # login for Yahoo!
18
+
19
+ def login
20
+ page = agent.get('https://login.yahoo.com/config/login_verify2?')
21
+ form = page.forms.first
22
+ form.login = options[:username].split("@").first
23
+ form.passwd = options[:password]
24
+ page = agent.submit(form, form.buttons.first)
25
+
26
+ # Check for login success
27
+ raise( Blackbook::BadCredentialsError, "That username and password was not accepted. Please check them and try again." ) if page.body =~ /Invalid ID or password./
28
+ true
29
+ end
30
+
31
+ ##
32
+ # prepare the importer
33
+
34
+ def prepare
35
+ login
36
+ end
37
+
38
+ ##
39
+ # scrape yahoo contacts
40
+
41
+ def scrape_contacts
42
+ page = agent.get("http://address.yahoo.com/?1=&VPC=import_export")
43
+ if page.body =~ /To access Yahoo! Address Book\.\.\..*Sign in./m
44
+ raise( Blackbook::BadCredentialsError, "Must be authenticated to access contacts." )
45
+ end
46
+ form = page.forms.last
47
+ csv = agent.submit(form, form.buttons[2]) # third button is Yahoo-format CSV
48
+
49
+ contact_rows = FasterCSV.parse(csv.body)
50
+ labels = contact_rows.shift # TODO: Actually use the labels to find the indexes of the data we want
51
+ contact_rows.collect do |row|
52
+ next if !row[7].blank? && options[:username] =~ /^#{row[7]}/ # Don't collect self
53
+ {
54
+ :name => "#{row[0]} #{row[2]}".to_s,
55
+ :email => (row[4] || "#{row[7]}@yahoo.com") # email is a field in the data, but will be blank for Yahoo users so we create their email address
56
+ }
57
+ end
58
+ end
59
+
60
+ Blackbook.register(:yahoo, self)
61
+ end
@@ -0,0 +1,565 @@
1
+ ---------------------------------
2
+
3
+
4
+
5
+
6
+ <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xml:lang="en" lang="en">
7
+ <head>
8
+ <title>Free email address from AOL Mail</title>
9
+ <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8"/>
10
+ <meta name="keywords" content="AOL Mail free web reliable easy IMAP inbox email industry leading antivirus virus spam protection antispam storage pictures photo calendar address calendar personal domain name Blackberry Treo Motorola Q Outlook Thunderbird buddy list access anywhere everywhere on the go personal domain drag and drop blog integration keyword search easy to use"/>
11
+ <meta name="description" content="Get a free email address from AOL now! You no longer need to be an AOL member to take advantage of great AOL Mail features such as industry-leading spam and virus protection, anytime-access on your mobile device, flexibility to work with other email clients using IMAP and more."/>
12
+ <link rel="stylesheet" type="text/css" media="screen" href="https://s.aolcdn.com/art/registration/snslanding_css.css"/>
13
+ <script language="javascript" type="text/javascript" src="https://s.aolcdn.com/art/registration/snslanding_js.js"><!--....--></script>
14
+ <link rel="stylesheet" type="text/css" media="screen" href="https://s.aolcdn.com/art/landing_pages/snslanding10_id1686.css"/>
15
+
16
+ <LINK href="https://sns-static.aolcdn.com/sns/3.5r2/style/snsMiniStyles.css" rel="stylesheet" type="text/css">
17
+ <style type="text/css">
18
+ #sns_MainContentDiv, #sns_MainContentDiv #snsLoginRow,#sns_LoginTitleBar,.sns_noTabs, #sns_NewLoginModule, #sns_LoginContentDiv,.sns_LoginTabs .selected,#sns_LoginTitleBar { color: #000000;background-color: #FFFFFF; }
19
+ #sns_Module #sns_MainContentDiv, #sns_Footer #sPipe, .sns_HeadlineBold, #sns_MainContentDiv label, #sns_MainContentDiv .sns_FieldLabel { color: #000000 }
20
+ #sns_TitleBar { background-color: #3333CC;border:1px solid #3333CC }
21
+ #sns_Module .sLnkSm, #sns_Module .sLnkMd, #sns_Module .sLnkLg, #sns_NewLoginModule .sLnkMd, #sns_NewLoginModule a{ color: #3333CC; }
22
+ #sns_MainContentDiv .sns_Text3, #sns_MainContentDiv td.sns_Text3 { color: #3399FF }
23
+ #sns_NewLoginModule {background-color:#FFFFFF; border:1px solid #3333CC; }
24
+ </style>
25
+ </head>
26
+ <body>
27
+ <div class="port_land">
28
+ <div class="lands">
29
+ <div id="othercontent">
30
+ <div class="aol_hatcontainer">
31
+ <script type="text/javascript">
32
+ //Overwrite Hat 2.0 min-width
33
+ var _aol_hat_commonstyle_ = '#aol_hat2 {min-width:100% !important; _width:100% !important;}';
34
+ var _sns_use_ssl_ = '1';
35
+ </script>
36
+ <script type="text/javascript" src="https://secure.aolhat.com/hat2/webmail_cayman2/jswrite.js"><!--hat jswrite is being included--></script>
37
+ </div>
38
+ <div class="brand">
39
+ <h1>
40
+ <img src="https://s.aolcdn.com/art/landing_pages/cayman_branding.gif" width="169" height="45" alt="FREE AOL Webmail" title="FREE AOL Webmail" border="0"/>
41
+ </h1>
42
+ <div class="logTrouble">
43
+ <a href="http://help.channels.aol.com/topic.adp?topicId=ART_219191&amp;ncid=AOLCMP00300000000128">Trouble Logging In?</a>
44
+ </div>
45
+ <div id="webBeacon" style="display:none;"><!--....--></div>
46
+ <script type="text/javascript">loc=document.getElementById('webBeacon');wBeacon = document.createElement("img");wBeacon.setAttribute('src', 'https://s.aolcdn.com/websuitebeacon/aol/en-us/BeaconLandingPage.html');wBeacon.style.height='1px';wBeacon.style.width='1px';loc.appendChild(wBeacon);</script>
47
+ <!--...--> </div>
48
+ </div>
49
+ <div class="landslt">
50
+ <div class="prim_promo">
51
+ <div class="contCopyTop"><!--....--></div>
52
+ <div class="contCopy">
53
+ <h2>Get your FREE email account<br/>
54
+ with unlimited storage! </h2>
55
+ <h3>Try FREE AOL Mail and we'll transfer your messages<br/>
56
+ and address book from your old email account automatically. </h3>
57
+ <h4>AOL Easy Transfer makes switching your email a snap.</h4>
58
+ <a class="buttonGet" href="https://new.aol.com/freeaolweb?promocode=824087&amp;promocode2=806077&amp;ncid=AOLCMP00300000000126">Get FREE AOL Mail</a>
59
+ <ul>
60
+ <li>Automatically copies your address book</li>
61
+ <li>Notifies all your friends of your new email address</li>
62
+ <li>Forwards emails sent to your old email address</li>
63
+ <li>Copies all your emails, attachments, even your folders</li>
64
+ </ul>
65
+ <a class="linkEasy" href="https://secure5.trueswitch.com/aolweb/?ncid=AOLCMP00300000000129">Transfer My Emails and Address Book Now</a>
66
+ <a class="linkLearnMore" href="http://discover.aol.com/memed/webmail/">Learn More</a>
67
+ <div class="clearme"><!--....--></div>
68
+ </div>
69
+ <div class="contCopyBot"><!--....--></div>
70
+ <div class="sellBlockLeft">
71
+ <p>Rather have a personalized email address that totally expresses who you are, like Emily@Wild4music.com?<strong>It's FREE.</strong>
72
+ <a class="sblButton" href="http://domains.aol.com?ncid=AOLCMP00300000000130">Find a Personalized Address</a>
73
+ </p>
74
+ <img src="https://s.aolcdn.com/art/landing_pages/bl_promo" width="59" height="60" alt="find a personalized address" title="find a personalized address"/>
75
+ <a class="sblLearnLink" href="http://discover.aol.com/memed/webmail/myeaddress.adp">Learn More</a>
76
+ </div>
77
+ <div class="sellBlockRight">
78
+ <h5>AIM<sup>&reg;</sup>
79
+ . Mail. Content. All in one window - New AOL Mail! </h5>
80
+ <img src="https://s.aolcdn.com/art/landing_pages/br_promo" width="158" height="83" alt="AOL Mail screen shot" title="AOL Mail screen shot"/>
81
+ <p>View all your messages on one page - check out new AOL Mail now.</p>
82
+ <a href="http://o.aolcdn.com/cdn.webmail.aol.com/mailtour/aol/en-us/index-noNav.htm?ncid=AOLCMP00300000000131">Take the Tour</a>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ <div class="landsrt">
87
+ <div class="login">
88
+
89
+
90
+
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+
101
+
102
+
103
+
104
+
105
+
106
+
107
+
108
+
109
+
110
+
111
+
112
+
113
+
114
+
115
+
116
+
117
+
118
+
119
+
120
+
121
+
122
+
123
+
124
+
125
+
126
+
127
+
128
+
129
+
130
+
131
+ <SCRIPT LANGUAGE="JavaScript" SRC="https://sns-static.aolcdn.com/sns/3.5r2/js/mainValidations.js"></SCRIPT>
132
+
133
+ <script language="javascript" type="text/javascript">
134
+ prereqchecks('/badbrowser.psp?source=login&null');
135
+ </script>
136
+
137
+
138
+ <div id="sns_miniUiWidget" >
139
+ <div id="snsHelpBlk">
140
+ <span class="hdrText">Sign In</span>
141
+
142
+ <a id="snsHelpLnk" href="javascript:snsInfoPopUp(1,'https://my.screenname.aol.com/_cqr/help/infoPopUp.jsp?help=1')" alt="Help" tabindex="5">Help</a>
143
+
144
+ </div>
145
+
146
+
147
+
148
+
149
+
150
+
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
176
+
177
+
178
+
179
+
180
+
181
+
182
+
183
+
184
+
185
+
186
+
187
+
188
+
189
+
190
+
191
+
192
+
193
+
194
+
195
+
196
+
197
+
198
+
199
+
200
+
201
+
202
+
203
+
204
+
205
+
206
+
207
+
208
+
209
+
210
+
211
+
212
+
213
+
214
+
215
+
216
+
217
+
218
+
219
+
220
+
221
+
222
+
223
+
224
+
225
+
226
+
227
+
228
+
229
+
230
+
231
+
232
+
233
+
234
+
235
+
236
+
237
+
238
+ <SCRIPT type="text/JavaScript" language="JavaScript">
239
+
240
+
241
+
242
+
243
+ function validateAolTab(loginForm){
244
+ var pwderr = new Array(4);
245
+ pwderr[RetVal.EMPTY_ERR]="You must enter a value for Password.";
246
+ pwderr[RetVal.MIN_ERR]="Password you entered is too short.";
247
+ pwderr[RetVal.MAX_ERR]="Password must not be longer than 16 characters.";
248
+ pwderr[RetVal.INVALID_ERR]="Password you entered is invalid. A Valid password should contain 6-16 letters or numbers.";
249
+ var result;
250
+ var loginId = loginForm.loginId;
251
+ stripOffAOLDomains(loginId);
252
+ if((/@/).test(loginId.value)) {
253
+ var err = new Array(4);
254
+ err[RetVal.EMPTY_ERR]="You must enter a value for E-mail Address.";
255
+ err[RetVal.MIN_ERR]="E-mail Address you entered is too short.";
256
+ err[RetVal.MAX_ERR]="E-mail Address must not be longer than 97 characters.";
257
+ err[RetVal.INVALID_ERR]="E-mail Address you entered is invalid. A valid E-mail address should look like: joe@aol.com. Please be sure that the E-mail Address doesn't contain any spaces.";
258
+ }
259
+ else {
260
+ var err = new Array(5);
261
+ err[RetVal.EMPTY_ERR]="You must enter a value for Screen Name.";
262
+ err[RetVal.MIN_ERR]="ScreenName you entered is too short.";
263
+ err[RetVal.MAX_ERR]="ScreenName must not be longer than 16 characters.";
264
+ err[RetVal.INVALID_ERR]="ScreenName you entered is invalid. A valid Screen Name consists of 3-16 characters and can contain letters, numbers, spaces, and must start with a letter (e.g., johndoe123). Please re-type your Screen Name.";
265
+ err[RetVal.ICQ_INVALID_ERR]="The ICQ UIN you entered is invalid. A valid ICQ UIN consists of 5-10 digits. Please re-type your ICQ UIN.";
266
+ }
267
+
268
+ result=snsCheckSignInForm(loginForm,err,pwderr);
269
+ return result;
270
+ }
271
+
272
+
273
+ function validateIcqTab(loginForm){
274
+ var pwderr = new Array(4);
275
+ pwderr[RetVal.EMPTY_ERR]="You must enter a value for Password.";
276
+ pwderr[RetVal.MIN_ERR]="Password you entered is too short.";
277
+ pwderr[RetVal.MAX_ERR]="Password must not be longer than 16 characters.";
278
+ pwderr[RetVal.INVALID_ERR]="Password you entered is invalid. A Valid password should contain 6-16 letters or numbers.";
279
+ var result;
280
+ var loginId = loginForm.loginId;
281
+ if((/@/).test(loginId.value)) {
282
+ var err = new Array(3);
283
+ err[RetVal.EMPTY_ERR]="Please enter an ICQ UIN or ICQ email alias";
284
+ err[RetVal.MIN_ERR]="ICQ e-mail alias you entered is invalid. A valid E-mail address should look like:joe@aol.com.";
285
+ err[RetVal.MAX_ERR]="E-mail Address must not be longer than 97 characters.";
286
+ err[RetVal.INVALID_ERR]="ICQ e-mail alias you entered is invalid. A valid E-mail address should look like:joe@aol.com.";
287
+ }
288
+ else {
289
+ var err = new Array(4);
290
+ err[RetVal.EMPTY_ERR]="Please enter an ICQ UIN or ICQ email alias";
291
+ err[RetVal.MIN_ERR]="An ICQ UIN is at least 5 numeric digits ";
292
+ err[RetVal.MAX_ERR]="ICQ UIN must not be more than 10 numeric digits";
293
+ err[RetVal.INVALID_ERR]="The ICQ UIN you entered is invalid. A valid ICQ UIN consists of 5-10 digits. Please re-type your ICQ UIN.";
294
+ }
295
+
296
+ result=checkIcqForm(loginForm,err,pwderr);
297
+ return result;
298
+ }
299
+
300
+
301
+
302
+
303
+
304
+
305
+
306
+
307
+
308
+
309
+
310
+
311
+
312
+
313
+
314
+
315
+
316
+
317
+
318
+
319
+
320
+
321
+
322
+ </SCRIPT>
323
+
324
+
325
+ <div id="SLT" class="snslogintypes snslogintypes_content">
326
+
327
+
328
+ <div class="sns_noTabs"></div>
329
+
330
+
331
+
332
+
333
+
334
+
335
+
336
+
337
+
338
+
339
+
340
+
341
+
342
+
343
+
344
+
345
+
346
+
347
+
348
+
349
+
350
+
351
+
352
+
353
+
354
+
355
+
356
+
357
+
358
+
359
+
360
+
361
+
362
+
363
+
364
+
365
+
366
+
367
+
368
+
369
+
370
+
371
+
372
+
373
+
374
+
375
+
376
+
377
+
378
+
379
+
380
+
381
+
382
+
383
+
384
+
385
+
386
+ <div class="content" id="SLT.1">
387
+ <div id="sns_LoginAol">
388
+ <form name="AOLLoginForm" method="POST" action="https://my.screenname.aol.com/_cqr/login/login.psp" onsubmit="return validateAolTab(this);">
389
+ <input type="hidden" name="sitedomain" value="sns.webmail.aol.com">
390
+ <input type="hidden" name="siteId" value="">
391
+ <input type="hidden" name="lang" value="en">
392
+ <input type="hidden" name="locale" value="us">
393
+ <input type="hidden" name="authLev" value="2">
394
+ <input type="hidden" name="siteState" value="ver%3A2%7Cac%3AWS%7Cat%3ASNS%7Cld%3Awebmail.aol.com%7Cuv%3AAOL%7Clc%3Aen-us">
395
+ <input type="hidden" name="isSiteStateEncoded" value="true">
396
+ <input type="hidden" name="mcState" value="initialized">
397
+ <input type="hidden" name="uitype" value="std">
398
+ <input type="hidden" name="use_aam" value="0">
399
+ <input type="hidden" name="_sns_fg_color_" value="">
400
+ <input type="hidden" name="_sns_err_color_" value="">
401
+ <input type="hidden" name="_sns_link_color_" value="">
402
+ <input type="hidden" name="_sns_width_" value="">
403
+ <input type="hidden" name="_sns_height_" value="">
404
+ <input type="hidden" name="_sns_bg_color_" value="">
405
+ <input type="hidden" name="offerId" value="">
406
+ <input type="hidden" name="seamless" value="novl">
407
+ <input type="hidden" name="regPromoCode" value="">
408
+ <input type="hidden" name="idType" value="SN">
409
+
410
+
411
+ <input type="hidden" name="usrd" value="9604003">
412
+
413
+
414
+
415
+
416
+
417
+
418
+
419
+
420
+
421
+
422
+
423
+ <div id="snsmPswdRetry" class="snsmErrorText">
424
+
425
+
426
+
427
+ Invalid Screen Name or Password. Please try again.
428
+
429
+
430
+ </div>
431
+
432
+
433
+
434
+
435
+
436
+
437
+
438
+
439
+ <label for="lgnId1" id="lgnId1lbl">Screen Name or E-mail:</label>
440
+
441
+
442
+
443
+ <input type="text" name="loginId" maxlength="97" size="25" tabindex="1" value="mondragonmichael" id="lgnId1" class="inputBox">
444
+
445
+
446
+
447
+
448
+
449
+
450
+ <div id="snsmCreateAcctLnk"></div>
451
+
452
+
453
+
454
+ <label for="pwdId" alt="enter AOL password" id="pwdId1lbl">Password:</label>
455
+ <input type="password" name="password" maxlength="23" size="25" tabindex="2" value="" id="pwdId1" class="inputBox" alt="enter AOL password">
456
+
457
+ <a href="https://account.login.aol.com/opr/_cqr/opr/opr.psp?sitedomain=sns.webmail.aol.com&authLev=2&siteState=ver%3A2%7Cac%3AWS%7Cat%3ASNS%7Cld%3Awebmail.aol.com%7Cuv%3AAOL%7Clc%3Aen-us&lang=en&locale=us&seamless=novl" id="forgotpswdLnk" target="_top" class="snsmTinyText" tabindex="7" >Forgot Password</a>
458
+
459
+
460
+
461
+ <div id="rmbrBlk">
462
+ <input type="hidden" name="rememberMe" value="off">
463
+ </div>
464
+
465
+
466
+ <div class="alignBtnRt" id="sbmtAol">
467
+ <input type="submit" id="submitAol" value="Sign In" class="artzBtn def" tabindex="3" alt="Sign In" title="Sign In" />
468
+ </div>
469
+
470
+
471
+ </form>
472
+ </div>
473
+ </div>
474
+
475
+
476
+
477
+
478
+
479
+
480
+
481
+
482
+
483
+
484
+
485
+
486
+
487
+ <div style="display:none;">none</div>
488
+
489
+ <script type="text/Javascript">
490
+ _sns_p("SLT.1").style.display="block";
491
+
492
+
493
+
494
+
495
+ if( document.getElementById("pwdId1")){document.getElementById("pwdId1").focus();}
496
+
497
+
498
+
499
+
500
+
501
+
502
+
503
+
504
+ </script>
505
+
506
+ </div> <!-- end SLT -->
507
+
508
+
509
+
510
+
511
+
512
+ </div>
513
+ <script type="text/javascript">
514
+ <!--
515
+ var s_account="aolsnssignin,aolsvc";
516
+ //-->
517
+ </script>
518
+ <script type="text/javascript" src="https://sns-static.aolcdn.com/omni/H.8/omniunih.js"></script>
519
+ <script type="text/javascript">
520
+ <!--
521
+ s_265.linkInternalFilters="javascript:,aol.com";
522
+ s_265.server="my.screenname.aol.com";
523
+ s_265.pfxID="sso";
524
+ s_265.pageName="sso : login";
525
+ s_265.channel="us.snssignin";
526
+ s_265.prop1='ssologin';
527
+ s_265.prop12="/snsUiDriver.jsp";
528
+ s_265.prop15="bW9uZHJhZ29ubWljaGFlbA%3D%3D";
529
+ s_265.prop16="sns.webmail.aol.com";
530
+ s_265.prop17="lp";
531
+ s_265.prop18="2";
532
+ s_265.prop19="wa3";
533
+ s_265.prop20="en-us";
534
+ s_265.prop21="AOLPortal";
535
+ s_265.prop22=".aol.com";
536
+ var s_code=s_265.t();
537
+ if(s_code)document.write(s_code);
538
+ //-->
539
+ </script>
540
+ </div>
541
+ <div class="addl_promo">
542
+ <script type="text/javascript">r1=Math.round(Math.random()*1000000)//;</script>
543
+ <script type="text/javascript">document.write('<script type="text/javascript" src="https://eatps.web.aol.com:9001/open_web_adhoc?subtype=6915amp;r1='+r1+'">');document.write ('</scr'+'ipt>');</script>
544
+ </div>
545
+ </div>
546
+ </div>
547
+ <div class="footer">
548
+ <style type="text/css">#footerlinks{position:relative;display:block;font:10px arial,sans serif;color:#959494;margin:px 0px 0px 0px;}#footerlinks a, #footerlinks a:visited { color:#959494; text-decoration:none;}#footerlinks a:hover { text-decoration:underline; }</style>
549
+ <div id="footerlinks">
550
+ <a href="http://www.corp.aol.com/">AOL LLC.</a>
551
+ | <a href="http://downloads.channel.aol.com/windowsproducts">Download AOL</a>
552
+ | <a href="http://corp.aol.com/accessibility/">Accessibility Policy</a>
553
+ | <a href="http://www.aol.com/aolnetwork/terms_use.html">Terms of Use</a>
554
+ | <a href="http://www.aol.com/aolnetwork/aol_pp.html">Privacy Policy</a>
555
+ | <a href="http://www.aol.com/aolnetwork/trademarks.html">Trademarks</a>
556
+ | <a href="http://postmaster.aol.com/guidelines/bulk_email.html">Email Policy</a>
557
+ | <a href="http://advisor.aol.com/">Advertise With Us</a>
558
+ <br/>
559
+ Copyright 2007 AOL LLC. All Rights Reserved </div>
560
+ </div>
561
+ </div>
562
+ </body>
563
+ </html>
564
+
565
+ ---------------------------------