5

Long time listener, first time caller.

I have been trying to get some repetitive tasks automated in order to make some lives easier and I have run up against a bit of a wall. FuelSDK doesn't have any native classes that support POST requests to the Marketing Cloud API Asset management endpoints. As a result I wrote my own class following the FuelAPI's format:

########
##
##  wrap an Exact Target Asset Creation
##
########
class ET_Content_Builder_Asset(ET_CUDSupportRest):
    def __init__(self):
        super(ET_Content_Builder_Asset, self).__init__()
        self.endpoint = 'https://www.extracttargetapis.com/asset/v1/content/assets'
        self.urlProps = []
        self.urlPropsRequired = []

which I modeled after classes with similar functionality that I tested and confirmed were working such as:

########
##
##  wrap an Exact Target Campaign and associated Assets
##
########
class ET_Campaign(ET_CUDSupportRest):
    def __init__(self):
        super(ET_Campaign, self).__init__()
        self.endpoint = 'https://www.exacttargetapis.com/hub/v1/campaigns/{id}'
        self.urlProps = ["id"]
        self.urlPropsRequired = []

In practice, I have used ET_Campaign successfully and have seen the results represent on my page, so I know that the CLIENT_ID and CLIENT_SECRET are correct and am not completely off base. This is the functioning sample code running getting ET_Campaigns:

# Next, create an instance of the ET_Client class:
myClient = FuelSDK.ET_Client()

# Create an instance of the object type we want to work with:
list = FuelSDK.ET_Campaign()

# Associate the ET_Client to the object using the auth_stub property:
list.auth_stub = myClient

# Utilize one of the ET_List methods:
response = list.get()

# Print out the results for viewing
print 'Post Status: ' + str(response.status)
print 'Code: ' + str(response.code)
print 'Message: ' + str(response.message)
print 'Result Count: ' + str(len(response.results))
print 'Results: ' + str(response.results)

I have also successfully posted new campaigns as well as got those newly posted campaigns through my python code, AND logged in to the Marketing Cloud App Center to ensure that read and write permissions existed on Assets in Data Access.

The code that runs my custom class which extends the ET_CUDSupportRest class within FuelSDK is, for the time being, and is used in the following method:

def sendRequest(name, content):
    global TOKEN
    global CATEGORY_STRING
    global ASSETTYPE_STRING

    payload = {
        'category':CATEGORY_STRING,
        'assetType':ASSETTYPE_STRING,
        'content':content,
        'description':name,
        'name':name
        }
    print payload

    # Create an instance of the object type we want to work with:
    asset = FuelSDK.ET_Content_Builder_Asset()

    # Associate the ET_Client to the object using the auth_stub property:
    asset.auth_stub = TOKEN

    # Add payload to the asset
    asset.props = payload

    # Utilize one of the ET_List methods:
    response = asset.post()

    # Print out the results for viewing
    print 'Post Status: ' + str(response.status)
    print 'Code: ' + str(response.code)
    print 'Message: ' + str(response.message)
    print 'Result Count: ' + str(len(response.results))
    print 'Results: ' + str(response.results)

When I attempt to run my code with the custom class I see the following errors:

Name-MacBook-Pro:automated-snippet-addition Name$ sudo python script.py -p ~/Downloads/Automate\ Code\ Snippets/snippets/test
you are accessing: /Users/Name/Downloads/Automate Code Snippets/snippets/test
{'category': {'id': 4275, 'name': 'Programmatic Test'}, 'assetType': {'id': 220, 'name': 'codesnippetblock'}, 'content': '<div class="field vertical">\n\t\t<label for="control_COLUMN97">ab_test_value</label>\n\t\t<input type="text" name="ab_test_value" id="control_COLUMN97" value="" class="input text form-control"/>\n</div>\n', 'description': 'ab_test_value.html', 'name': 'ab_test_value.html'}
Error: HTTPSConnectionPool(host='www.extracttargetapis.com', port=443): Max retries exceeded with url: /asset/v1/content/assets (Caused by <class 'socket.gaierror'>: [Errno 8] nodename nor servname provided, or not known)

The error claims that there is no nodename nor servname provided. After searching the error, the only thing I came up with was perhaps I was making too many requests too quickly, but even with a sleep inserted for testing purposes, I received the same issue.

I have stepped through the stack trace and haven't managed to come up with anything. The stack trace is attached below:

Name-MacBook-Pro:automated-snippet-addition Name$ sudo python script.py -a ~/Documents/automated-snippet-addition/authFile.txt -p ~/Downloads/Automate\ Code\ Snippets/snippets/
Password:
Instance Config File: /Users/Name/Documents/automated-snippet-addition/authFile.txt
Snippet Directory: /Users/Name/Downloads/Automate Code Snippets/snippets/
Getting Marketing Cloud configuration information from file...
SalesForce Marketing Cloud instance configuration loaded.
Getting Application Specific Token...
Token Retrieved.
{'category': {'id': 4275, 'name': 'Programmatic Test'}, 'assetType': {'id': 220, 'name': 'codesnippetblock'}, 'content': '<div class="field vertical">\n\t\t<label for="control_COLUMN1">account_manager</label>\n\t\t<input type="text" name="account_manager" id="control_COLUMN1" value="" class="input text form-control"/>\n</div>\n', 'description': 'account_manager.html', 'name': 'account_manager.html'}
auth_stub: <FuelSDK.client.ET_Client object at 0x100c220d0>
props:     {'category': {'id': 4275, 'name': 'Programmatic Test'}, 'assetType': {'id': 220, 'name': 'codesnippetblock'}, 'content': '<div class="field vertical">\n\t\t<label for="control_COLUMN1">account_manager</label>\n\t\t<input type="text" name="account_manager" id="control_COLUMN1" value="" class="input text form-control"/>\n</div>\n', 'description': 'account_manager.html', 'name': 'account_manager.html'}
Traceback (most recent call last):
  File "script.py", line 247, in <module>
    main(sys.argv[1:])
  File "script.py", line 242, in main
    accessDirectory(path)
  File "script.py", line 45, in accessDirectory
    sendRequest(name, content)
  File "script.py", line 73, in sendRequest
    response = asset.post()
  File "/Library/Python/2.7/site-packages/FuelSDK/rest.py", line 510, in post
    obj = ET_PostRest(self.auth_stub, completeURL, self.props)
  File "/Library/Python/2.7/site-packages/FuelSDK/rest.py", line 335, in __init__
    r = requests.post(endpoint + '?access_token=' + auth_stub.authToken , data=json.dumps(payload), headers=headers)
  File "/Library/Python/2.7/site-packages/requests/api.py", line 88, in post
    return request('post', url, data=data, **kwargs)
  File "/Library/Python/2.7/site-packages/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Library/Python/2.7/site-packages/requests/sessions.py", line 383, in request
    resp = self.send(prep, **send_kwargs)
  File "/Library/Python/2.7/site-packages/requests/sessions.py", line 486, in send
    r = adapter.send(request, **kwargs)
  File "/Library/Python/2.7/site-packages/requests/adapters.py", line 378, in send
    raise ConnectionError(e)
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='www.extracttargetapis.com', port=443): Max retries exceeded with url: /asset/v1/content/assets?access_token=7NwgB3Y4co0GjGJCS4C5c91L (Caused by <class 'socket.gaierror'>: [Errno 8] nodename nor servname provided, or not known)

Any ideas would be appreciated.

3

You have a typo in your endpoint. Try changing your endpoint from

https://www.extracttargetapis.com/asset/v1/content/assets

to

https://www.exacttargetapis.com/asset/v1/content/assets

  • Holy cow. I can't believe that was all it was. I was expecting some yet undocumented endpoint changes. Nope! Another set of eyes was all that it needed. – Near Jan 4 '17 at 14:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.