def test_build_url(): res = client.build_url('test', 125) assert res == 'test/125' res = client.build_url('test', 125, id='my_id') assert res == 'test/125?id=my_id' res = client.build_url('test', 125, id='my_id', value=123) assert res == 'test/125?id=my_id&value=123'
def create(self, name, as_json=False): """Create new group. https://developers.mailerlite.com/v2/reference#create-group Parameters ---------- name : str group name as_json : bool return result as json format Returns ------- group: :class:Group group object """ url = client.build_url('groups') data = {'name': name} _, res_json = client.post(url, body=data, headers=self.headers) if as_json or not res_json: return res_json return Group(**res_json)
def update(self, group_id, name, as_json=False): """Update existing group. https://developers.mailerlite.com/v2/reference#rename-group Parameters ---------- group_id : int group that you want to rename name : str group name as_json : bool return result as json format Returns ------- group: :class:Group group object """ url = client.build_url('groups', group_id) body = { "name": name, } _, res_json = client.put(url, body=body, headers=self.headers) if as_json or not res_json: return as_json return Group(**res_json)
def get(self, webhook_id, as_json=False): """Get single field by ID from your account. https://developers.mailerlite.com/v2/reference#get-single-webhook Parameters ---------- webhook_id : int ID of a webhook as_json : bool return result as json format Returns ------- webhook: dict the desired webhook. """ url = client.build_url('webhooks', webhook_id) _, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json webhook = Webhook(**res_json) return webhook
def create(self, title, field_type='TEXT'): """Create new custom field in account. https://developers.mailerlite.com/v2/reference#create-field Parameters ---------- title : str Title of field field_type: str Type of field. Available values: TEXT , NUMBER, DATE (default: TEXT) Returns ------- field : :class:Field field object updated """ if field_type.upper() not in ['TEXT', 'NUMBER', 'DATE']: raise ValueError('Incorrect field_type. Available values' ' are: TEXT , NUMBER, DATE') url = client.build_url('fields') data = {'title': title, 'type': field_type.upper()} return client.post(url, body=data, headers=self.headers)
def update(self, data, as_json=False, **identifier): """Update single subscriber. https://developers.mailerlite.com/v2/reference#update-subscriber Parameters ---------- data : dict subscriber object. only the email is required. you can use the following example: data = {'name' : 'John', 'fields' : {'company': 'MailerLite'} } as_json : bool return result as json format identifier : str should be subscriber id or email. e.g: id=1343965485 or email='*****@*****.**' Returns ------- response : int response value content : dict The JSON output from the API Notes ----- The email of a subscriber can not be updated """ path = get_id_or_email_identifier(**identifier) if path is None: raise IOError('An identifier must be define') if 'email' in data.keys(): raise ValueError("Subscriber email can not be updated. Please, " "remove this field or create a new Subscriber. " "For more informations, look at " "http://help.mailerlite.com/article/show" "/29233-how-to-edit-a-subscribers-data") optional_keys = ['name', 'type', 'fields', 'resend_autoresponders'] unknown_keys = [ d for d in data.keys() if d not in optional_keys if d not in ['groups', 'segments'] ] if unknown_keys: raise ValueError( "The following keys are unknown: {}".format(unknown_keys)) url = client.build_url('subscribers', path) res_code, res_json = client.put(url, body=data, headers=self.headers) if not res_json: return False res_json['fields'] = [Field(**res) for res in res_json['fields']] return Subscriber(**res_json)
def groups(self, as_json=False, **identifier): """Get groups subscriber belongs to. More informations: https://developers.mailerlite.com/v2/reference#groups-subscriber-belongs-to Parameters ---------- identifier : str should be subscriber id or email. e.g: id=1343965485 or email='*****@*****.**' as_json : bool return result as json format Returns ------- groups: list all groups that a subscriber belongs to. More informations : https://developers.mailerlite.com/v2/reference#groups """ path = get_id_or_email_identifier(**identifier) if path is None: raise IOError('An identifier must be define') url = client.build_url('subscribers', path, 'groups') res_code, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json all_groups = [Group(**res) for res in res_json] return all_groups
def batch(self, batch_requests): """Execute a list of command. Dedicated for experts. https://developers.mailerlite.com/v2/reference#batch-api-requests Parameters ---------- batch_requests : list of dict all you command. E.g: batch_requests = {"requests": [{"method":"GET", "path": "/api/v2/groups" }, {"method":"POST", "path": "/api/v2/groups", "body": {"name": "New group"} } ] } Returns ------- results : list list of all desired object Notes ----- * There is a limit of maximum 50 requests per single batch. * The order of response objects are the same as sent requests. * requests parameter should not be empty """ url = client.build_url('batch') return client.post(url, body=batch_requests, headers=self.headers)
def cancel(self, campaign_id, as_json=False): """Cancel a campaign which is in outbox. https://developers.mailerlite.com/reference#campaign-actions-and-triggers Parameters ---------- campaign_id : int campaign id as_json : bool return result as json format Returns ------- content : dict The JSON output from the API """ # TODO: Check if campaign is in Outbox otherwise raise an issue url = client.build_url('campaigns', campaign_id, "actions/cancel") code, res_json = client.post(url, headers=self.headers) # TODO: Check new attribute to campaign object. # if as_json or not res_json or code != 200: # return res_json # res_json['opened'] = Stats(**res_json.pop('opened')) # res_json['clicked'] = Stats(**res_json.pop('clicked')) # return Campaign(**res_json) return code, res_json
def update(self, field_id, title, as_json=False): """Update custom field in account. https://developers.mailerlite.com/v2/reference#update-field Parameters ---------- field_id : int field id title : str Title of field Returns ------- field : :class:Field field object updated """ url = client.build_url('fields', field_id) body = {"title": title} res_code, res_json = client.put(url, body=body, headers=self.headers) if as_json or not res_json: return res_json return Field(**res_json)
def get(self, id, as_json=False): """Get single field by ID from your account. look at https://developers.mailerlite.com/v2/reference#all-fields Parameters ---------- id : int should be group id. e.g: id=1343965485 as_json : bool return result as json format Returns ------- Field: :class:Field a single field """ url = client.build_url('fields', id) res_code, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json return Field(**res_json)
def get(self, as_json=False, **identifier): """Get a single subscriber from your account. https://developers.mailerlite.com/v2/reference#single-subscriber Parameters ---------- identifier : str should be subscriber id or email. e.g: id=1343965485 or email='*****@*****.**' as_json : bool return result as json format Returns ------- subscriber: :class:Subscriber a single subscriber """ path = get_id_or_email_identifier(**identifier) if path is None: raise IOError('An identifier must be define') url = client.build_url('subscribers', path) res_code, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json res_json['fields'] = [Field(**res) for res in res_json['fields']] return Subscriber(**res_json)
def subscriber(self, group_id, subscriber_id, as_json=False): """Get one subscriber in a specified group. https://developers.mailerlite.com/v2/reference#a-subscriber-of-a-group Parameters ---------- group_id : int group id subscriber_id : int subscriber id as_json : bool return result as json format Returns ------- subscriber: :class:Subscriber a single subscriber """ url = client.build_url('groups', group_id, 'subscribers', subscriber_id) _, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json res_json['fields'] = [Field(**res) for res in res_json['fields']] return Subscriber(**res_json)
def all(self, limit=100, offset=0, gfilters='', as_json=False): """Get list of groups from your account. look at https://developers.mailerlite.com/v2/reference#groups Parameters ---------- limit : int How many groups you want offset : int page index gfilters : str group filters as_json : bool return result as json format Returns ------- groups: list all desired Groups. More informations : https://developers.mailerlite.com/v2/reference#groups """ params = {'limit': limit, 'offset': offset, 'filters': gfilters} url = client.build_url('groups', **params) _, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json all_groups = [Group(**res) for res in res_json] return all_groups
def add_subscribers(self, group_id, subscribers_data, resubscribe=False, autoresponders=False, as_json=False): """Add one or many new subscribers to specified group at once. https://developers.mailerlite.com/v2/reference#add-single-subscriber https://developers.mailerlite.com/v2/reference#add-many-subscribers Parameters ---------- group_id : int group id subscribers_data : dict, list of dict subscribers element that contains email and name resubscribe : bool reactivate subscriber if value is true (default False) autoresponders : bool autoresponders will be sent if value is true (default False) as_json : bool return result as json format Returns ------- group: :class:Group group object """ url = client.build_url('groups', group_id, 'subscribers', 'import') body = {'resubscribe': resubscribe, 'autoresponders': autoresponders} if isinstance(subscribers_data, dict): body['subscribers'] = [ subscribers_data, ] elif isinstance(subscribers_data, list): body['subscribers'] = subscribers_data else: raise ValueError('subscribers_data should be a dict or a list of' ' dict that contains the following keys: email,' ' name') errors = [ d for d in body['subscribers'] if not {'email', 'name'}.issubset(d.keys()) ] if errors: raise ValueError('All subscribers_data should contain the' ' following keys: email, name') _, res_json = client.post(url, body=body, headers=self.headers) if as_json or not res_json: return res_json return [Subscriber(**subs) for subs in res_json['imported']]
def activity(self, as_json=False, atype=None, **identifier): """Get activities (clicks, opens, etc) of selected subscriber. More informations: https://developers.mailerlite.com/v2/reference#activity-of-single-subscriber Parameters ---------- identifier : str should be subscriber id or email. e.g: id=1343965485 or email='*****@*****.**' as_json : bool return result as json format atype : str Define activity type: Here are the possible values: * None - All activities (default) * opens * clicks * bounces * junks * unsubscribes * forwards * sendings Returns ------- activities: list all subscriber activities. More informations : https://developers.mailerlite.com/v2/reference#activity-of-single-subscriber """ path = get_id_or_email_identifier(**identifier) if path is None: raise IOError('An identifier must be define') args = ['subscribers', path, 'activity'] if atype: possible_atype = [ 'opens', 'clicks', 'junks', 'bounces', 'unsubscribes', 'forwards', 'sendings' ] if atype not in possible_atype: raise ValueError('Incorrect value atype. Activity type should' ' be {0}'.format(possible_atype)) args.append(atype) url = client.build_url(*args) res_code, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json all_activities = [Activity(**res) for res in res_json] return all_activities
def update(self, campaign_id, html, plain, auto_inline=True): r"""Upload your HTML template to created campaign. https://developers.mailerlite.com/v2/reference#put-custom-content-to-campaign Parameters ---------- campaign_id : int the campaign id that you want to update html : str HTML template source plain : str Plain text of email auto_inline : bool, optional Defines if it is needed to convert available CSS to inline CSS (excluding media queries) Returns ------- success : bool Examples -------- >>> from mailerlite import MailerLiteApi >>> api = MailerLiteApi('my_keys') >>> html = '<head></head><body><h1>Title</h1><p>Content</p><p><small>' >>> html += '<a href=\"{$unsubscribe}\">Unsubscribe</a></small></p>' >>> html += '</body>' >>> plain = "Your email client does not support HTML emails. " >>> plain += "Open newsletter here: {$url}. If you do not want" >>> plain += " to receive emails from us, click here: {$unsubscribe}" >>> api.campaigns.update(campaign_id, html=html, plain=plain) True Notes ----- * HTML template must contain body and head tag. * HTML template must contain a link for unsubscribe. It may look like this: <a href="{$unsubscribe}">Unsubscribe</a> * Some email clients do not support HTML emails so you need to set plain text email and it must contain these variables: * {$unsubscribe} - unsubscribe link * {$url} - URL to your HTML newsletter """ url = client.build_url('campaigns', campaign_id, 'content') # Todo, Check html syntax body = {"html": html, "plain": plain} _, res_json = client.put(url, body=body, headers=self.headers) if not res_json: return False return res_json['success']
def subscribers(self, group_id, limit=100, offset=0, stype=None, as_json=False): """Get all subscribers in a specified group. https://developers.mailerlite.com/v2/reference#subscribers-in-a-group Parameters ---------- group_id : int group id limit : int How many subscribers you want offset : int page index stype : str Define subscriber type: Here are the possible values: * None - All subscribers (default) * active * unsubscribed * bounced * junk * unconfirmed as_json : bool return result as json format Returns ------- subscribers: list all desired Subscribers. More informations : https://developers.mailerlite.com/v2/reference#subscribers """ params = {'limit': limit, 'offset': offset} if stype and stype.lower() in [ 'active', 'unsubscribed', 'bounced', 'junk', 'unconfirmed' ]: params.update({'type': stype}) url = client.build_url('groups', group_id, 'subscribers', **params) _, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json for res in res_json: res['fields'] = [Field(**field) for field in res['fields']] all_subscribers = [Subscriber(**res) for res in res_json] return all_subscribers
def create(self, data, as_json=False): """Add new single subscriber. https://developers.mailerlite.com/v2/reference#create-a-subscriber Parameters ---------- data : dict subscriber object. only the email is required. you can use the following example: data = {'name' : 'John', 'email' : '*****@*****.**', 'fields' : {'company': 'MailerLite'} } as_json : bool return result as json format Returns ------- subscriber: :class:Subscriber a single subscriber """ if not isinstance(data, dict): raise ValueError('In data should be a dictionary.') required_keys = [ 'email', ] optional_keys = [ 'name', 'fields', 'resubscribe', 'type', 'signup_ip', 'signup_timestamp', 'confirmation_ip', 'confirmation_timestamp' ] available_keys = required_keys + optional_keys errors = [rk for rk in required_keys if rk not in data.keys()] if errors: raise ValueError("The following keys are missing and they" " are required : {}".format(errors)) unknown_keys = [ d for d in data.keys() if d not in available_keys if d not in ['groups', 'segments'] ] if unknown_keys: raise ValueError( "The following keys are unknown: {}".format(unknown_keys)) url = client.build_url('subscribers') res_code, res_json = client.post(url, body=data, headers=self.headers) if as_json or not res_json: return res_json return Subscriber(**res_json)
def double_optin(self): """Retrieve the status double opt-in. https://developers.mailerlite.com/v2/reference#get-double-optin-status Returns ------- success: bool deletion status """ url = client.build_url('settings', 'double_optin') _, res_json = client.get(url, headers=self.headers) return res_json
def all(self): """Get list of Webhooks. https://developers.mailerlite.com/v2/reference#get-webhooks-list Returns ------- webhooks: list of dict all webhooks. """ url = client.build_url('webhooks') _, res_json = client.get(url, headers=self.headers) return res_json
def info(self): """Get account info. https://developers.mailerlite.com/v2/reference#account Returns ------- info: dict all account information. """ url = client.build_url('me') res_code, res_json = client.get(url, headers=self.headers) return res_json
def count(self): """Return the number of segments. More informations: https://developers.mailerlite.com/reference#section-segments-count Returns ------- count: int number of segments """ url = client.build_url('segments', 'count') _, res_json = client.get(url, headers=self.headers) return res_json['count']
def delete(self, subscriber_id): """Remove a subscribers. Parameters ---------- subscriber_id : int subscribers id Returns ------- success: bool deletion status """ url = client.build_url('subscribers', subscriber_id) return client.delete(url, headers=self.headers)
def all(self, status='sent', limit=100, offset=0, order='asc', as_json=False): """Get paginated details of all campaigns from your account. look at https://developers.mailerlite.com/reference#campaigns-by-type Parameters ---------- status : str Define campaigns type: Here are the possible values: * sent - campaigns which are sent already (default) * draft - campaigns which aren't completed or sent to subscribers * outbox - campaigns which are being sent right now or scheduled limit : int How many campaigns you want offset : int page index order : str pick the order. Here are the possible values: ASC (default) or DESC as_json : bool return result as json format Returns ------- campaigns: list all desired campaign. More informations concerning campaign : https://developers.mailerlite.com/reference#section-response-body-parameters """ if order.upper() not in ['ASC', 'DESC']: raise IOError("Incorrect order, please choose between ASC or DESC") params = {'limit': limit, 'offset': offset, 'order': order} url = client.build_url('campaigns', status, **params) _, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json for res in res_json: res['opened'] = Stats(**res.pop('opened')) res['clicked'] = Stats(**res.pop('clicked')) all_campaigns = [Campaign(**res) for res in res_json] return all_campaigns
def stats(self): """Get basic stats for of account, such as subscribers, open/click rates and so on. https://developers.mailerlite.com/v2/reference#stats Returns ------- stats: dict account stats """ url = client.build_url('stats') res_code, res_json = client.get(url, headers=self.headers) return res_json
def add_single_subscriber(self, group_id, subscribers_data: dict, resubscribe=False, autoresponders=False, as_json=False): """Add single new subscriber to specified group. https://developers.mailerlite.com/v2/reference#add-single-subscriber Parameters ---------- group_id : int group id subscribers_data : dict, subscribers data resubscribe : bool reactivate subscriber if value is true (default False) autoresponders : bool autoresponders will be sent if value is true (default False) as_json : bool return result as json format Returns ------- subscriber: :class:Subscriber subscriber object """ url = client.build_url('groups', group_id, 'subscribers') body = { 'resubscribe': resubscribe, 'autoresponders': autoresponders, **subscribers_data } if not {'email', 'name'}.issubset(subscribers_data.keys()): raise ValueError('Subscribers_data should contain the' ' following keys: email, name') _, res_json = client.post(url, body=body, headers=self.headers) if as_json or not res_json: return res_json return Subscriber(**res_json)
def delete(self, webhook_id): """Remove a webhook. https://developers.mailerlite.com/v2/reference#delete-a-webhook Parameters ---------- webhook_id : int ID of a webhook Returns ------- success: bool deletion status """ url = client.build_url('webhooks', webhook_id) return client.delete(url, headers=self.headers)
def delete(self, campaign_id): """Remove a campaign. look at https://developers.mailerlite.com/reference#delete-campaign Parameters ---------- campaign_id : int campaign id Returns ------- success: bool deletion status """ url = client.build_url('campaigns', campaign_id) return client.delete(url, headers=self.headers)
def search(self, search=None, limit=100, offset=0, minimized=True, as_json=False): """Get paginated details of all Subscribers from your account. look at https://developers.mailerlite.com/v2/reference#subscribers Parameters ---------- search : str query parameter to search limit : int How many subscribers you want offset : int page index minimized : bool return minimized response with: id, email, type default: True as_json : bool return result as json format Returns ------- subscribers: list all desired Subscribers. More informations : https://developers.mailerlite.com/v2/reference#subscribers """ params = {'limit': limit, 'offset': offset, 'minimized': minimized} if search is not None: params.update({'query': search}) url = client.build_url('subscribers', 'search', **params) res_code, res_json = client.get(url, headers=self.headers) if as_json or not res_json: return res_json if not minimized: for res in res_json: res['fields'] = [Field(**field) for field in res['fields']] all_subscribers = [Subscriber(**res) for res in res_json] return all_subscribers