blackbook 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ ---------------------------------