Skip to content

Instantly share code, notes, and snippets.

@krazybean
Last active July 1, 2025 19:47
Show Gist options
  • Save krazybean/73644086980c5dca1a92246f01de568e to your computer and use it in GitHub Desktop.
Save krazybean/73644086980c5dca1a92246f01de568e to your computer and use it in GitHub Desktop.
Yahoo email validation
import sys
import time
import urllib
import requests
class Yahoo(object):
"""
Hokey way of Yahoo validation since their SMTP check returns
250 for every request.
"""
def __init__(self):
"""
Putting together some constants needed or maybe for PEP8 fashion.
"""
ua = []
ua.append('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1)')
ua.append('AppleWebKit/537.36 (KHTML, like Gecko)')
ua.append('Chrome/63.0.3239.108 Safari/537.36')
content_type = 'application/x-www-form-urlencoded; charset=UTF-8'
url = 'https://login.yahoo.com/account/module/create'
params = 'validateField=yid'
self.url = '{0}?{1}'.format(url, params)
self.headers = {'origin': 'https://login.yahoo.com',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
'user-agent': ' '.join(ua),
'content-type': content_type,
'accept': '*/*',
'referer': self.url,
'authority': 'login.yahoo.com',
'x-requested-with': 'XMLHttpRequest'}
def _valid_response_(self, response):
""" Internal function for checking the response code.
Args:
response (:obj:): Requests response object.
Returns:
bool: True or False based on if 2xx status code.
"""
if response and response.status_code:
if response.status_code in range(200, 299):
return True
return False
def _extract_crumb(self, cookies):
""" Crumb needed for the post body element.
Args:
cookies (:obj:): Requests.cookies response object.
Returns:
acrumb (str): Parsed out string from AS cookie for body.
"""
acrumb = None
for cookie in cookies:
if cookie.name == 'AS':
dataset = cookie.value.split('&')
for data in dataset:
if data.startswith('s='):
acrumb = data[len('s='):]
return acrumb
def _browser_data(self, acrumb, mailbox):
""" Construct of the post return data for second request.
Args:
acrumb (str): Hash value returned to post body.
mailbox (str): {mailbox}@yahoo.com also needed for post body.
Returns:
browser, dict_args (tuple): 2 sets of prepared data for response.
"""
ftime_start = int(time.time())
ftime_end = ftime_start + 10
hash1 = '24700f9f1986800ab4fcc880530dd0ed'
hash2 = 'd52a1516cfb5f1c2d8a427c14bc3645f'
browser_fp_data = {"language": "en-US",
"colorDepth": 24,
"deviceMemory": 8,
"pixelRatio": 2,
"hardwareConcurrency": 8,
"resolution": {"w": 1440,
"h": 900},
"availableResolution": {"w": 1440,
"h": 846},
"timezoneOffset": 300,
"timezone": "America/Chicago",
"sessionStorage": 1,
"localStorage": 1,
"indexedDb": 1,
"openDatabase": 1,
"cpuClass": "unknown",
"platform": "MacIntel",
"doNotTrack": 1,
"canvas": "canvas winding:yes~canvas",
"webgl": 1,
"webglVendorAndRenderer": "Google Inc. (ATI Technologies Inc.)~ANGLE (ATI Technologies Inc., AMD Radeon Pro 555 OpenGL Engine, OpenGL 4.1)",
"adblock": 0,
"hasLiedLanguages": 0,
"hasLiedResolution": 0,
"hasLiedOs": 0,
"hasLiedBrowser": 0,
"touch_support": {"points": 0,
"event": 0,
"start": 0},
"plugins": {"count": 0,
"hash": hash1},
"fonts": {"count": 27,
"hash": hash2},
"audio": "124.04347657808103",
"ts": {"serve": ftime_start,
"render": ftime_end}}
dict_args = {'specId': 'yidregsimplified',
'cacheStored': 'true',
'crumb': 'QFM5cNikkUV',
'acrumb': acrumb,
'sessionIndex': 'QQ--',
'done': 'https%3A%2F%2Fwww.yahoo.com',
'attrSetIndex': 0,
'googleIdToken': '',
'authCode': '',
'tos0': 'oath_freereg|us|en-US',
'firstName': '',
'lastName': '',
'attrSetIndex': 0,
'userid-domain': 'yahoo',
'userId': mailbox,
'yidDomainDefault': 'yahoo.com',
'yidDomain': 'yahoo.com',
'password': '',
'shortCountryCode': 'US',
'phone': '',
'mm': '',
'dd': '',
'yyyy': '',
'multiDomain': '',
'signup': '',
'freeformGender': ''}
return browser_fp_data, dict_args
def _reshape_cookie(self, cookies):
""" Returns string representation of cookie body
Args:
cookies (:obj:`list`): List of cookies
Returns:
string: Concatenated string of cookie name+body
"""
string = []
for cookie in cookies:
string.append('{0}={1}'.format(cookie.name, cookie.value))
return ';'.join(string)
def _digest_response(self, response):
""" Tests response output if mailbox exists.
Args:
response (:obj:): Requests response object.json()
Returns:
string: "exists" or "does not exist"
"""
output = None
if 'errors' in response:
for error in response['errors']:
if error['name'] == 'userId':
output = error['error']
if output == 'IDENTIFIER_EXISTS':
return 'exists'
return 'does not exist'
def _clean_mailbox(self, mailbox):
""" Incase someone passes in a full email in instead of a mailbox
Args:
mailbox (str): "[email protected]"
Returns:
mailbox (str): "test" without the "@yahoo.com"
"""
if '@' in mailbox:
return mailbox[:mailbox.find("@") - 1]
return mailbox
def validate(self, mailbox):
""" Validation method that runs the check against the validation.
Args:
mailbox (str): mailbox to check validation against.
Returns:
string: "{mailbox} exists" or "{mailbox} does not exist"
"""
mailbox = self._clean_mailbox(mailbox)
r = requests.get(self.url)
if not self._valid_response_(r):
return {'Error': 'Initial request error'}
acrumb = self._extract_crumb(r.cookies)
self.headers['cookie'] = self._reshape_cookie(r.cookies)
browser_fp_data, dict_args = self._browser_data(acrumb, mailbox)
payload = {'browser-fp-data': browser_fp_data}
payload.update(dict_args)
params = {'validateField': 'userId'}
req = requests.post(self.url, headers=self.headers, cookies=r.cookies,
data=payload, params=params)
if not self._valid_response_(r):
return {'Error': 'Validation call error'}
return '{0} {1}'.format(mailbox, self._digest_response(req.json()))
if __name__ == '__main__':
yahoo = Yahoo()
mailbox = 'krazybean1'
if len(sys.argv) == 2:
mailbox = sys.argv[1]
print(yahoo.validate(mailbox))
@tvr121
Copy link

tvr121 commented May 6, 2023

The code has stopped working. Now it's giving "email does not exist" for everything. Can you please check and provide an update? Thanks.

@krazybean
Copy link
Author

The code has stopped working. Now it's giving "email does not exist" for everything. Can you please check and provide an update? Thanks.

This code is outdated, but i can write something new if need be.

@krazybean
Copy link
Author

The code has stopped working. Now it's giving "email does not exist" for everything. Can you please check and provide an update? Thanks.

This has been updated. Sorry for the delay.

@huynhphuong10284
Copy link

I've tested and it works

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment