campaignmonitor / createsend-python Goto Github PK
View Code? Open in Web Editor NEWA Python library for the Campaign Monitor API
Home Page: http://campaignmonitor.github.io/createsend-python
License: MIT License
A Python library for the Campaign Monitor API
Home Page: http://campaignmonitor.github.io/createsend-python
License: MIT License
I don't know why this pull request was merged without any test coverage.
Could you add tests? The contributing guidelines exist for very good reasons and apply to everyone who contributes to this repository.
/ping @shennys @richardbremner
File "/home/deploy/virtualenvs/bentobox/build/createsend/setup.py", line 5, in <module>
from createsend import __version__
File "createsend/__init__.py", line 11, in <module>
from transactional import Transactional
ImportError: No module named transactional
Just a suggestion: working with this API has a bit of a learning curve. One easy way to improve the situation would be to add default values to parameters that aren't actually required.
For example, if I just want to change a subscriber's name, it looks something like:
subscriber.update(None,my_new_name,[],False)
And I had to go study the function to figure out that the first parameter is None because I don't want to change the email, but the third is an empty set because it expects a dictionary for custom fields. Yuck.
It sure would be nice if the update() function defaulted to assuming you always want to change everything about the subscriber at once so I could just do:
subscriber.update(name=my_new_name)
Same goes for many similar functions. Would there be interest in a pull request?
This package installs nose, coverage, and coveralls. These packages should be omitted except when testing.
default_user_agent
is built using platform.platform()
, which is not available on Google App Engine.
Is there a way to specify default_user_agent
when using Transactional()
?
Collecting createsend
Downloading createsend-4.2.2.tar.gz (160kB)
100% |████████████████████████████████| 163kB 2.4MB/s
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/private/var/folders/my/cvndjd3s70z22zmybwh59rvc0000gn/T/pip-build-EzVTCF/createsend/setup.py", line 3, in <module>
from createsend.createsend import __version__
File "createsend/__init__.py", line 8, in <module>
from createsend.createsend import *
File "createsend/createsend.py", line 12, in <module>
from createsend.utils import VerifiedHTTPSConnection, json_to_py, get_faker
ImportError: No module named utils
We have some custom fields on one of our lists that use unicode characters specifically the sign for british pounds (£). These cause a unicode decode error when trying to load the custom fields in the python api ( python 2.7 )
the error is in the utils.py:
https://github.com/campaignmonitor/createsend-python/blob/master/createsend/utils.py#L109
This is blunt. This is some of the worst code and worst customer service I and many others have experienced in a long time.
It is extremely unfortunate that your paying customers receive no support for a code base you have decided to drop with no warning. This is a Python 2 project that simply needed to be made compatible with Python 3. Many people who use this are being forced to update to Python 3 due to, well it being 2017, and other libraries dropping support for Python 2. Even the Python Foundation is dropping support for Python 2.
You could have given a intern or junior dev this as busy work. Instead no, you got a professional from another company to spend time to rewrite your library to something that resembles clean code. And now it can't even be pushed and many more of your customers are without a working environment. A number of issues now exist simply because the newest releases I MADE, not your team, needs to be deployed to PyPi. Someone has literally already done the work you were supposed to do, and you can't even spend 30 minutes to deploy the package.
I have reached out to your support team who informed me in ticket reference number: ref:_00Do0eE9F._5001JRs4pf:ref that someone on the "engineering team that work on the Public API" has begun looking at this. Well they certainly have dropped the ball. Still no response, still no commits to the code base from your team. Instead we have myself and @jdennes maintaining your library.
This is pretty frustrating, especially for the great number of engineers out there being forced to maintain connections and write work-arounds to connect to Campaign Monitor simply because we choose Python. I guess the real solution is to not choose Campaign Monitor.
FOR ALL YOU OTHER ENGINEERS THAT HAVE TO DEAL WITH THIS, WE HAVE CREATED AN OPEN SOURCE VERSION OF THIS LIBRARY HERE: https://github.com/getbento/createsend-python
TO USE IT IN YOUR PROJECT SIMPLY ADD git+git://github.com/getbento/createsend-python.git
TO YOUR requirements.txt
The API does not work, if you need to use a http/https outbound proxy, to talk to the internet.
The CreateSend API no longer accepts screenshots when creating or updating a template. Screenshots are now always auto-generated.
See docs for details: http://www.campaignmonitor.com/api/templates/
I want to change the From/Reply-To fields when sending smart email. Is it possible to do this? The from field is not available in the function.
I use createsend-python like this:
transactional = Transactional({"api_key": conf.CAMPAIGN_MONITOR_API_KEY, })
response = transactional.classic_email_send(object.title, '[email protected]', recipient.email,
conf.CAMPAIGN_MONITOR_API_CLIENT_ID, html=body)
print response[0]
how can I access the X-Rate-Limit headers provided by the response? I can only see the json, transformed into a python object (and list?). As seen here: https://www.campaignmonitor.com/api/getting-started/#rate_limiting
Tracking / closing the loop on @jdennes comment in #30 (comment)
I released 4.2.0 on PyPI after someone from Campaign Monitor contacted me asking about this. I'm not an active maintainer of this project, so someone from Campaign Monitor should be added as an owner of the package, since they are the maintainers of it.
hello
when i run
cs = CreateSend(auth)
clients = cs.clients()
campaign_ids = cs.clients()
for cl in clients:
print("Client: %s" % cl.Name)
client = Client(auth, cl.ClientID)
print("- Campaigns:")
for cm in client.campaigns():
print(" - %s" % cm.Subject)
print(" - %s" % cm.CampaignID)
i have this issue
File "C:\Users\eguevara\AppData\Local\Temp/ipykernel_17348/3998498663.py", line 1, in
for i in client.campaigns():
TypeError: 'type' object is not iterable
How can I get all Subscriber with the custom fields for the same Campaign or how can I download Campaign report files from api?
Hi,
I have installed createsend using pip in command line interface.
When I type in from createsend import * in my Python interpreter (spyder), I get an error ModuleNotFoundError: No module named 'createsend'.
Not sure what am I doing wrong here. My goal is to get a list of all subscribers and their activities for a time period.
I am trying to connect to my client / campaign using the Python Wrapper and an API connection.
I apply the following code:
from createsend import *
#Connect via API key
cs = CreateSend({'api_key': '123<api-redacted>'})
clients = cs.clients()
auth = {
'api_key': '123<api-redacted>'
}
#clients.
for cl in clients:
print(cl.Name)
cl = Client(cl.ClientID,auth)
#client = Client(cl.ClientID)
for cm in cl.campaigns():
print(" - %s" % cm.Subject)
But get the following error message:
Unauthorized: The CreateSend API responded with the following error - 50: Must supply a valid HTTP Basic Authorization header
What do I need to pass to the client to provide a valid authorization header? The documentation explains how to do this with OAuth, but does not show the required code when using the API: https://github.com/campaignmonitor/createsend-python/blob/master/README.md
When retrieving a list of subscribers via List.active()
, an empty list has 0 pages and 1 numbered page while a populated list has 1 pages and also 1 numbered page. In both cases the caller receives a 'page', right?
More explicitly:
NumberOfPages > 0
PageNumber > 0
NumberOfPages == 0
PageNumber > 0
Empty List:
'NumberOfPages': 0,
'RecordsOnThisPage': 0,
'PageNumber': 1,
...
Populated List:
'NumberOfPages': 1,
'RecordsOnThisPage': 2,
'PageNumber': 1,
...
Submit createsend-python to http://pypi.python.org/pypi so we can go:
pip install createsend
or:
easy_install createsend
Hi,
It would be great to have python 3 compatibility.
Thanks !
setup.py shouldn't import the module because there's no guarantee the dependencies will be present. See my quick fix here; you may want to implement differently so the version isn't duplicated
version of this module published on pypi is missing dependence of module six. as a result after installation of createsend module gives an error
The ssl.wrap_socket()
function was deprecated in 3.7 and removed in 3.12. Worth reading the Python documentation which suggests that wrap_socket is insecure, incidentally this would be a good reason to drop support for <3.7.
If the API returns a status code beginning 4, the library raises a ClientError.
If it returns a status code beginning 5, the library raises a ServerError.
Why is it not including the HTTP status code in the error?? It's impossible to see what the actual error was if you just return an empty exception with literally no information in it.
Hello, thanks for reading!
I am in a little over my head as python is not my home language, however the company I work for wants to take data from Campaign Monitor and put it into our BI platform (which does not have a connector of course).
Here is what I have so far, mostly from the basic usage:
from createsend import *
auth = {'api_key': 'company's api key}
cs = CreateSend(auth)
clients = cs.clients()
campaign_ids = cs.clients()
for cl in clients:
print("Client: %s" % cl.Name)
client = Client(auth, cl.ClientID)
print("- Campaigns:")
for cm in client.campaigns():
print(" - %s" % cm.Subject)
print(" - %s" % cm.CampaignID)
camp1 = Campaign(auth, 'campaign of interest)
print(camp1.summary())
Now when I print the last line, it returns
<class 'createsend.utils.CreateSendModel'>
I have poured through the documentation and am just really unclear on how to get the data out of here. and into a table that I can convert to a csv and upload etc. (The goal is to eventually automate, I've got some experience with R and google cloud build I'm hoping I can transfer over to python).
Any help you can give would be much appreciated, I've been banging my head on a wall with this for awhile now.
Thanks!
Please change import json to
try:
import json
except ImportError:
import simplejson as json
Legacy Systems use your api
Thanks
This is everywhere in the code:
try:
import json
except ImportError:
import simplejson as json
This is no longer necessary since Python versions pre-json-module (pre 2.6) are not supported and probably already broken since simplejson
is not being installed.
It looks like previous attribute value is retained if the new attribute value given is None
. How does the API handle None
?
This is more of a question (apologies if this is the wrong place for this) about what kind of timing expectations can be expected from the API in regards to data syncing. The position I am in is:
Transactional
message_timeline
to validate that the email went through (yes Service B likely should handle this)I have the lookup wrapped in a "try, wait" loop to give the API some time to sync. I also lookup the last send email id (before making the request) to have an anchor to search from. Here is the code (more or less):
tx = Transactional({"api_key": "#######################"})
# get the last sent id before making the request
timeline = tx.message_timeline(
params={
"group": group
}
)
sent_after_id = timeline[0].MessageID
# send the request (blocking)
actual_email = "[email protected]"
group = "foobar"
result = sent_request_to_service_b(actual_email, group)
found = False
attempts = 30
wait = 10
for i in range(attempts):
timeline = tx.message_timeline(
params={
"group": group,
"sentAfterId": sent_after_id
}
)
sent_emails = [e.Recipient for e in timeline]
found = any([actual_email == e for e in sent_emails])
if found:
break
else:
time.sleep(wait)
There are cases where this works (the email is found) on the very first try (i.e. the API is synced within a few seconds at most) and there are times where it takes 100+ seconds of waiting in order for the email to be found. I can go into the web browser and see the email in the Latest emails sent
table long before the API resolves it. I am just wondering if there is some kind of rate limiting that is going on or some other magic happening? I ask because the behavior is fairly back and forth, it works on the first try, then it takes 100 seconds, then it works on the first try, etc (all with different emails that were sent the same way in the same time frame).
Everything is running createsend==4.2.7
I'd appreciate any advice you might have. Thanks for working on this api!
I tried to publish a new release twice, but the code in master
doesn't allow installation via pip
:
› pip3 install createsend
Collecting createsend
Downloading createsend-4.2.4.tar.gz (161kB)
100% |████████████████████████████████| 163kB 3.2MB/s
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/private/var/folders/9d/glt4w3hn1ng3bp621522kw7h0000gn/T/pip-build-4emdtbbh/createsend/setup.py", line 11, in <module>
from lib.release import __version__, __author__
ModuleNotFoundError: No module named 'lib.release'
----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /private/var/folders/9d/glt4w3hn1ng3bp621522kw7h0000gn/T/pip-build-4emdtbbh/createsend/
I have removed both the bad releases.
I do not have time to resolve this.
Whoever ends up doing it will need to bump the version to 4.2.5 when it's published.
Please create new PyPI release with Python 3 fixes.
This may be intentional - in which case I'd advise adding some documentation in README.md about this - but it appears a 'consent_to_track' parameter (for GDPR) has been added as a required field (with no default) to the .update() and .add() API's on Subscriber:
This has resulted in our app breaking when doing a routine package upgrade. The fix is easy, but this is likely going to bite others.
I'm happy to put in a PR - either for adding some 'beware when upgrading' info to README.md, or having a default for this parameter (with an info.warning() advising the API call should be upgraded).
In the readme, this example is shown:
from createsend import *
cs = CreateSend({'api_key': 'your api key'})
clients = cs.clients()
I installed with pip install createsend
and have version 6.0.0. When I run this code (substituting my api key for the placeholder text, I get this:
File "<stdin>", line 1, in <module>
File "/Users/dharris/src/gdpr/auth.py", line 7, in <module>
clients = cs.clients()
File "/Users/dharris/.virtualenvs/gdpr-campaigner/lib/python3.6/site-packages/createsend/createsend.py", line 272, in clients
response = self._get('/clients.json')
File "/Users/dharris/.virtualenvs/gdpr-campaigner/lib/python3.6/site-packages/createsend/createsend.py", line 240, in _get
return self.make_request(path=path, method="GET", params=params, username=username, password=password)
File "/Users/dharris/.virtualenvs/gdpr-campaigner/lib/python3.6/site-packages/createsend/createsend.py", line 215, in make_request
return self.handle_response(response.status, data)
File "/Users/dharris/.virtualenvs/gdpr-campaigner/lib/python3.6/site-packages/createsend/createsend.py", line 230, in handle_response
raise Unauthorized(json_data)
createsend.createsend.Unauthorized: The CreateSend API responded with the following error - 50: Must supply a valid HTTP Basic Authorization header
Note that this fails on cs.clients()
, suggesting that the authentication on the line before worked.
What's going on?
12:34:47 Downloading createsend-4.2.0.tar.gz (159kB)
12:34:47 Complete output from command python setup.py egg_info:
12:34:47 Traceback (most recent call last):
12:34:47 File "", line 20, in
12:34:47 File "/tmp/pip-build-RzioYi/createsend/setup.py", line 5, in
12:34:47 from createsend.createsend import version
12:34:47 File "createsend/init.py", line 1, in
12:34:47 from .createsend import *
12:34:47 File "createsend/createsend.py", line 6, in
12:34:47 from six import BytesIO
12:34:47 ImportError: No module named six
^^ got this from one of my Jenkins jobs installing the setup.py file for a service that uses "createsend" as a dependency
So I'm pretty sure I'm implementing this correctly (though I've had to just look at the code since the docs don't mention how to subscribe a user).
I'm subscribing a new user to a list, and I'm getting this error response back from the server:
The CreateSend API responded with the following error - 400: Failed to deserialize your request. Please check the documentation and try again. Fields in error: subscriber
Here is my code:
from createsend import *
CreateSend.api_key = MYKEY
sub = Subscriber()
ret = sub.add(MYLIST, user.email, user.first_name + ' ' + user.last_name, False, False)
I'm using Python 2.7.3 on Linux.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.