Ryan Firth Ryan Firth - 2 months ago 24
JSON Question

Simplejson decoding error only occurs when performing over two iterations

I'm trying to use the names module along with a wrapper for temp-mail.org (https://github.com/saippuakauppias/temp-mail) for part of a project involving creating temporary email addresses. My code is as shown below and works fine unless n is greater than 2.

import names
from random import randint
from tempmail import TempMail

n = input("Please enter number of email addresses: ")
i = 0
while i < n:
first = names.get_first_name()
second = names.get_last_name()
tm = TempMail(login= first + "." + second + str(randint(1,99)))
email = tm.get_email_address()
print email
i = i+1


If n is greater than two the loop will execute twice then I receive the following error:

>>> runfile('/root/voter.py', wdir='/root')
Please enter number of email addresses: 3
Randell.Elkin17@stexsy.com
Michael.Martinez6@stexsy.com
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 714, in runfile
execfile(filename, namespace)
File "/usr/local/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 81, in execfile
builtins.execfile(filename, *where)
File "/root/voter.py", line 12, in <module>
email = tm.get_email_address()
File "/usr/local/lib/python2.7/dist-packages/tempmail.py", line 66, in get_email_address
available_domains = self.available_domains
File "/usr/local/lib/python2.7/dist-packages/tempmail.py", line 36, in available_domains
domains = req.json()
File "/usr/local/lib/python2.7/dist-packages/requests/models.py", line 826, in json
return complexjson.loads(self.text, **kwargs)
File "/usr/lib/python2.7/dist-packages/simplejson/__init__.py", line 516, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.7/dist-packages/simplejson/decoder.py", line 370, in decode
obj, end = self.raw_decode(s)
File "/usr/lib/python2.7/dist-packages/simplejson/decoder.py", line 400, in raw_decode
return self.scan_once(s, idx=_w(s, idx).end())
simplejson.scanner.JSONDecodeError: Expecting value: line 1 column 1 (char 0)


I know this is a longshot as the tempmail module isn't widely used however I was hoping I've made a simple error elsewhere and someone could help? Thanks

Answer

Okay so I looked over your problem.

The package temp-mail seems to make a request to temp-mail.ru each time you call TempMail() to get a list of available domains.

You are encountering the API's rate limiting (in short, you are calling the API too many times in a too short window)

I added some debug to the package to see what was happening. I created a virtualenv to test your code. This makes modules that I install (temp-mail and names only local to the project and not globally installed on the system) and looked at the stacktrace. The line that calls the json part is domains = req.json(), located at /home/arch/tmp-tempmail/env/lib/python2.7/site-packages/tempmail.py.

I then edited the file to add some prints (you have to have some notions about the request module first):

url = 'http://{0}/request/domains/format/json/'.format(
    self.api_domain)
req = requests.get(url)
print req
print req.text
domains = req.json()

The output is:

Please enter number of email addresses: 3
<Response [200]>
["@stexsy.com"]
Larry.Gerald20@stexsy.com
<Response [200]>
["@stexsy.com"]
Darlene.Bullock32@stexsy.com
<Response [429]>

Traceback (most recent call last):
  File "main.py", line 29, in <module>
    email = tm.get_email_address()
  File "/home/arch/tmp-tempmail/env/lib/python2.7/site-packages/tempmail.py", line 68, in get_email_address
    available_domains = self.available_domains
  File "/home/arch/tmp-tempmail/env/lib/python2.7/site-packages/tempmail.py", line 38, in available_domains
    domains = req.json()
  File "/home/arch/tmp-tempmail/env/lib/python2.7/site-packages/requests/models.py", line 826, in json
    return complexjson.loads(self.text, **kwargs)
  File "/usr/lib64/python2.7/json/__init__.py", line 319, in loads
    return _default_decoder.decode(s)
  File "/usr/lib64/python2.7/json/decoder.py", line 339, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib64/python2.7/json/decoder.py", line 357, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

You can see that at the response that fails is the third one and it has the HTTP error code 429 which translates to "Too Many Requests". The JSON parser crashes just because the input is empty.

On the other hand, the API's docs says:

You can generate absolutely any email address without API notification

So if you have the domain, you don't need to make a request to the server for receiving mails on the server.

You could also add a delay inside the loop.

import names
from random import randint
from tempmail import TempMail
import time

n = input("Please enter number of email addresses: ")
i = 0
while i < n:
    first = names.get_first_name()
    second = names.get_last_name()
    tm = TempMail(login= first + "." + second + str(randint(1,99)))
    email = tm.get_email_address()
    print email
    time.sleep(1)
    i = i+1