about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/test
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/test
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/test')
-rw-r--r--.venv/lib/python3.12/site-packages/test/integ/__init__.py0
-rw-r--r--.venv/lib/python3.12/site-packages/test/integ/test_sendgrid.py2309
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/__init__.py0
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_app.py22
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_config.py60
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_email.py68
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_eventwebhook.py50
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_inbound_send.py49
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_mail_helpers.py1766
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_parse.py16
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_project.py52
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_sendgrid.py27
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_spam_check.py38
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_stats.py86
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_twilio_email.py37
-rw-r--r--.venv/lib/python3.12/site-packages/test/unit/test_unassigned.py93
16 files changed, 4673 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/test/integ/__init__.py b/.venv/lib/python3.12/site-packages/test/integ/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/integ/__init__.py
diff --git a/.venv/lib/python3.12/site-packages/test/integ/test_sendgrid.py b/.venv/lib/python3.12/site-packages/test/integ/test_sendgrid.py
new file mode 100644
index 00000000..0c63851e
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/integ/test_sendgrid.py
@@ -0,0 +1,2309 @@
+import datetime
+import os
+import unittest
+
+import sendgrid
+from sendgrid.helpers.endpoints.ip.unassigned import unassigned
+
+
+class UnitTests(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.path = '{}{}'.format(
+            os.path.abspath(
+                os.path.dirname(__file__)), '/..')
+        cls.sg = sendgrid.SendGridAPIClient()
+        cls.devnull = open(os.devnull, 'w')
+
+    def test_api_key_init(self):
+        self.assertEqual(self.sg.api_key, os.environ.get('SENDGRID_API_KEY'))
+        my_sendgrid = sendgrid.SendGridAPIClient(api_key="THISISMYKEY")
+        self.assertEqual(my_sendgrid.api_key, "THISISMYKEY")
+
+    def test_api_key_setter(self):
+        sg_api_key_setter = sendgrid.SendGridAPIClient(api_key="THISISMYKEY")
+        self.assertEqual(sg_api_key_setter.api_key, "THISISMYKEY")
+        # Use api_key setter to change api key
+        sg_api_key_setter.api_key = "THISISMYNEWAPIKEY"
+        self.assertEqual(sg_api_key_setter.api_key, "THISISMYNEWAPIKEY")
+
+    def test_impersonate_subuser_init(self):
+        temp_subuser = 'abcxyz@this.is.a.test.subuser'
+        sg_impersonate = sendgrid.SendGridAPIClient(
+            impersonate_subuser=temp_subuser)
+        self.assertEqual(sg_impersonate.impersonate_subuser, temp_subuser)
+
+    def test_useragent(self):
+        useragent = '{}{}{}'.format('sendgrid/', sendgrid.__version__, ';python')
+        self.assertEqual(self.sg.useragent, useragent)
+
+    def test_host(self):
+        self.assertEqual(self.sg.host, 'https://api.sendgrid.com')
+
+    def test_get_default_headers(self):
+        headers = self.sg._default_headers
+        self.assertIn('Authorization', headers)
+        self.assertIn('User-Agent', headers)
+        self.assertIn('Accept', headers)
+        self.assertNotIn('On-Behalf-Of', headers)
+
+        self.sg.impersonate_subuser = 'ladida@testsubuser.sendgrid'
+        headers = self.sg._default_headers
+        self.assertIn('Authorization', headers)
+        self.assertIn('User-Agent', headers)
+        self.assertIn('Accept', headers)
+        self.assertIn('On-Behalf-Of', headers)
+
+    def test_reset_request_headers(self):
+        addl_headers = {
+            'blah': 'test value',
+            'blah2x': 'another test value',
+        }
+        self.sg.client.request_headers.update(addl_headers)
+        self.assertIn('blah', self.sg.client.request_headers)
+        self.assertIn('blah2x', self.sg.client.request_headers)
+
+        self.sg.reset_request_headers()
+        self.assertNotIn('blah', self.sg.client.request_headers)
+        self.assertNotIn('blah2x', self.sg.client.request_headers)
+
+        for k, v in self.sg._default_headers.items():
+            self.assertEqual(v, self.sg.client.request_headers[k])
+
+    def test_access_settings_activity_get(self):
+        params = {'limit': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.access_settings.activity.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_access_settings_whitelist_post(self):
+        data = {
+            "ips": [
+                {
+                    "ip": "192.168.1.1"
+                },
+                {
+                    "ip": "192.*.*.*"
+                },
+                {
+                    "ip": "192.168.1.3/32"
+                }
+            ]
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.access_settings.whitelist.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_access_settings_whitelist_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.access_settings.whitelist.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_access_settings_whitelist_delete(self):
+        data = {
+            "ids": [
+                1,
+                2,
+                3
+            ]
+        }
+        headers = {'X-Mock': 204}
+        response = self.sg.client.access_settings.whitelist.delete(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_access_settings_whitelist__rule_id__get(self):
+        rule_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.access_settings.whitelist._(rule_id).get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_access_settings_whitelist__rule_id__delete(self):
+        rule_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.access_settings.whitelist._(rule_id).delete(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_alerts_post(self):
+        data = {
+            "email_to": "example@example.com",
+            "frequency": "daily",
+            "type": "stats_notification"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.alerts.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_alerts_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.alerts.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_alerts__alert_id__patch(self):
+        data = {
+            "email_to": "example@example.com"
+        }
+        alert_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.alerts._(alert_id).patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_alerts__alert_id__get(self):
+        alert_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.alerts._(alert_id).get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_alerts__alert_id__delete(self):
+        alert_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.alerts._(alert_id).delete(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_api_keys_post(self):
+        data = {
+            "name": "My API Key",
+            "sample": "data",
+            "scopes": [
+                "mail.send",
+                "alerts.create",
+                "alerts.read"
+            ]
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.api_keys.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_api_keys_get(self):
+        params = {'limit': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.api_keys.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_api_keys__api_key_id__put(self):
+        data = {
+            "name": "A New Hope",
+            "scopes": [
+                "user.profile.read",
+                "user.profile.update"
+            ]
+        }
+        api_key_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.api_keys._(api_key_id).put(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_api_keys__api_key_id__patch(self):
+        data = {
+            "name": "A New Hope"
+        }
+        api_key_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.api_keys._(api_key_id).patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_api_keys__api_key_id__get(self):
+        api_key_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.api_keys._(api_key_id).get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_api_keys__api_key_id__delete(self):
+        api_key_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.api_keys._(api_key_id).delete(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_asm_groups_post(self):
+        data = {
+            "description": "Suggestions for products our users might like.",
+            "is_default": True,
+            "name": "Product Suggestions"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.asm.groups.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_asm_groups_get(self):
+        params = {'id': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.asm.groups.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_asm_groups__group_id__patch(self):
+        data = {
+            "description": "Suggestions for items our users might like.",
+            "id": 103,
+            "name": "Item Suggestions"
+        }
+        group_id = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.asm.groups._(group_id).patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_asm_groups__group_id__get(self):
+        group_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.asm.groups._(group_id).get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_asm_groups__group_id__delete(self):
+        group_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.asm.groups._(group_id).delete(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_asm_groups__group_id__suppressions_post(self):
+        data = {
+            "recipient_emails": [
+                "test1@example.com",
+                "test2@example.com"
+            ]
+        }
+        group_id = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.asm.groups._(group_id).suppressions.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_asm_groups__group_id__suppressions_get(self):
+        group_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.asm.groups._(group_id).suppressions.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_asm_groups__group_id__suppressions_search_post(self):
+        data = {
+            "recipient_emails": [
+                "exists1@example.com",
+                "exists2@example.com",
+                "doesnotexists@example.com"
+            ]
+        }
+        group_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.asm.groups._(
+            group_id).suppressions.search.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_asm_groups__group_id__suppressions__email__delete(self):
+        group_id = "test_url_param"
+        email = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.asm.groups._(group_id).suppressions._(
+            email).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_asm_suppressions_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.asm.suppressions.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_asm_suppressions_global_post(self):
+        data = {
+            "recipient_emails": [
+                "test1@example.com",
+                "test2@example.com"
+            ]
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.asm.suppressions._("global").post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_asm_suppressions_global__email__get(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.asm.suppressions._("global")._(
+            email).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_asm_suppressions_global__email__delete(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.asm.suppressions._("global")._(
+            email).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_asm_suppressions__email__get(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.asm.suppressions._(email).get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_browsers_stats_get(self):
+        params = {'end_date': '2016-04-01', 'aggregated_by': 'day',
+                  'browsers': 'test_string', 'limit': 'test_string',
+                  'offset': 'test_string', 'start_date': '2016-01-01'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.browsers.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_campaigns_post(self):
+        data = {
+            "categories": [
+                "spring line"
+            ],
+            "custom_unsubscribe_url": "",
+            "html_content": "<html><head><title></title></head><body>"
+                            "<p>Check out our spring line!</p></body></html>",
+            "ip_pool": "marketing",
+            "list_ids": [
+                110,
+                124
+            ],
+            "plain_content": "Check out our spring line!",
+            "segment_ids": [
+                110
+            ],
+            "sender_id": 124451,
+            "subject": "New Products for Spring!",
+            "suppression_group_id": 42,
+            "title": "March Newsletter"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.campaigns.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_campaigns_get(self):
+        params = {'limit': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.campaigns.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_campaigns__campaign_id__patch(self):
+        data = {
+            "categories": [
+                "summer line"
+            ],
+            "html_content": "<html><head><title></title></head><body><p>"
+                            "Check out our summer line!</p></body></html>",
+            "plain_content": "Check out our summer line!",
+            "subject": "New Products for Summer!",
+            "title": "May Newsletter"
+        }
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.campaigns._(campaign_id).patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_campaigns__campaign_id__get(self):
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.campaigns._(campaign_id).get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_campaigns__campaign_id__delete(self):
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.campaigns._(campaign_id).delete(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_campaigns__campaign_id__schedules_patch(self):
+        data = {
+            "send_at": 1489451436
+        }
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.campaigns._(campaign_id).schedules.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_campaigns__campaign_id__schedules_post(self):
+        data = {
+            "send_at": 1489771528
+        }
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.campaigns._(campaign_id).schedules.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_campaigns__campaign_id__schedules_get(self):
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.campaigns._(campaign_id).schedules.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_campaigns__campaign_id__schedules_delete(self):
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.campaigns._(campaign_id).schedules.delete(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_campaigns__campaign_id__schedules_now_post(self):
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.campaigns._(campaign_id).schedules.now.post(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_campaigns__campaign_id__schedules_test_post(self):
+        data = {
+            "to": "your.email@example.com"
+        }
+        campaign_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.campaigns._(campaign_id).schedules.test.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_categories_get(self):
+        params = {'category': 'test_string', 'limit': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.categories.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_categories_stats_get(self):
+        params = {'end_date': '2016-04-01', 'aggregated_by': 'day',
+                  'limit': 1, 'offset': 1, 'start_date': '2016-01-01',
+                  'categories': 'test_string'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.categories.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_categories_stats_sums_get(self):
+        params = {'end_date': '2016-04-01', 'aggregated_by': 'day',
+                  'limit': 1, 'sort_by_metric': 'test_string', 'offset': 1,
+                  'start_date': '2016-01-01', 'sort_by_direction': 'asc'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.categories.stats.sums.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_clients_stats_get(self):
+        params = {'aggregated_by': 'day', 'start_date': '2016-01-01',
+                  'end_date': '2016-04-01'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.clients.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_clients__client_type__stats_get(self):
+        params = {'aggregated_by': 'day', 'start_date': '2016-01-01',
+                  'end_date': '2016-04-01'}
+        client_type = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.clients._(client_type).stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_custom_fields_post(self):
+        data = {
+            "name": "pet",
+            "type": "text"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.contactdb.custom_fields.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_contactdb_custom_fields_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.custom_fields.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_custom_fields__custom_field_id__get(self):
+        custom_field_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.custom_fields._(
+            custom_field_id).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_custom_fields__custom_field_id__delete(self):
+        custom_field_id = "test_url_param"
+        headers = {'X-Mock': 202}
+        response = self.sg.client.contactdb.custom_fields._(
+            custom_field_id).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 202)
+
+    def test_contactdb_lists_post(self):
+        data = {
+            "name": "your list name"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.contactdb.lists.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_contactdb_lists_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.lists.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_lists_delete(self):
+        data = [
+            1,
+            2,
+            3,
+            4
+        ]
+        headers = {'X-Mock': 204}
+        response = self.sg.client.contactdb.lists.delete(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_contactdb_lists__list_id__patch(self):
+        data = {
+            "name": "newlistname"
+        }
+        params = {'list_id': 1}
+        list_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.lists._(list_id).patch(
+            request_body=data, query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_lists__list_id__get(self):
+        params = {'list_id': 1}
+        list_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.lists._(list_id).get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_lists__list_id__delete(self):
+        params = {'delete_contacts': 'true'}
+        list_id = "test_url_param"
+        headers = {'X-Mock': 202}
+        response = self.sg.client.contactdb.lists._(list_id).delete(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 202)
+
+    def test_contactdb_lists__list_id__recipients_post(self):
+        data = [
+            "recipient_id1",
+            "recipient_id2"
+        ]
+        list_id = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.contactdb.lists._(list_id).recipients.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_contactdb_lists__list_id__recipients_get(self):
+        params = {'page': 1, 'page_size': 1}
+        list_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.lists._(list_id).recipients.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_lists__list_id__recipients__recipient_id__post(self):
+        list_id = "test_url_param"
+        recipient_id = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.contactdb.lists._(list_id).recipients._(
+            recipient_id).post(request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_contactdb_lists__list_id__recipients__recipient_id__delete(self):
+        params = {'recipient_id': 1, 'list_id': 1}
+        list_id = "test_url_param"
+        recipient_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.contactdb.lists._(list_id).recipients._(
+            recipient_id).delete(query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_contactdb_recipients_patch(self):
+        data = [
+            {
+                "email": "jones@example.com",
+                "first_name": "Guy",
+                "last_name": "Jones"
+            }
+        ]
+        headers = {'X-Mock': 201}
+        response = self.sg.client.contactdb.recipients.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_contactdb_recipients_post(self):
+        data = [
+            {
+                "age": 25,
+                "email": "example@example.com",
+                "first_name": "",
+                "last_name": "User"
+            },
+            {
+                "age": 25,
+                "email": "example2@example.com",
+                "first_name": "Example",
+                "last_name": "User"
+            }
+        ]
+        headers = {'X-Mock': 201}
+        response = self.sg.client.contactdb.recipients.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_contactdb_recipients_get(self):
+        params = {'page': 1, 'page_size': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.recipients.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_recipients_delete(self):
+        data = [
+            "recipient_id1",
+            "recipient_id2"
+        ]
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.recipients.delete(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_recipients_billable_count_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.recipients.billable_count.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_recipients_count_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.recipients.count.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_recipients_search_get(self):
+        params = {'{field_name}': 'test_string'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.recipients.search.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_recipients__recipient_id__get(self):
+        recipient_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.recipients._(
+            recipient_id).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_recipients__recipient_id__delete(self):
+        recipient_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.contactdb.recipients._(
+            recipient_id).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_contactdb_recipients__recipient_id__lists_get(self):
+        recipient_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.recipients._(
+            recipient_id).lists.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_reserved_fields_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.reserved_fields.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_segments_post(self):
+        data = {
+            "conditions": [
+                {
+                    "and_or": "",
+                    "field": "last_name",
+                    "operator": "eq",
+                    "value": "Miller"
+                },
+                {
+                    "and_or": "and",
+                    "field": "last_clicked",
+                    "operator": "gt",
+                    "value": "01/02/2015"
+                },
+                {
+                    "and_or": "or",
+                    "field": "clicks.campaign_identifier",
+                    "operator": "eq",
+                    "value": "513"
+                }
+            ],
+            "list_id": 4,
+            "name": "Last Name Miller"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.segments.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_segments_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.segments.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_segments__segment_id__patch(self):
+        data = {
+            "conditions": [
+                {
+                    "and_or": "",
+                    "field": "last_name",
+                    "operator": "eq",
+                    "value": "Miller"
+                }
+            ],
+            "list_id": 5,
+            "name": "The Millers"
+        }
+        params = {'segment_id': 'test_string'}
+        segment_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.segments._(segment_id).patch(
+            request_body=data, query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_segments__segment_id__get(self):
+        params = {'segment_id': 1}
+        segment_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.segments._(segment_id).get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_contactdb_segments__segment_id__delete(self):
+        params = {'delete_contacts': 'true'}
+        segment_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.contactdb.segments._(segment_id).delete(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_contactdb_segments__segment_id__recipients_get(self):
+        params = {'page': 1, 'page_size': 1}
+        segment_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.contactdb.segments._(
+            segment_id).recipients.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_devices_stats_get(self):
+        params = {
+            'aggregated_by': 'day',
+            'limit': 1,
+            'start_date': '2016-01-01',
+            'end_date': '2016-04-01',
+            'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.devices.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_geo_stats_get(self):
+        params = {
+            'end_date': '2016-04-01',
+            'country': 'US',
+            'aggregated_by': 'day',
+            'limit': 1,
+            'offset': 1,
+            'start_date': '2016-01-01'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.geo.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_get(self):
+        params = {
+            'subuser': 'test_string',
+            'ip': 'test_string',
+            'limit': 1,
+            'exclude_whitelabels': 'true',
+            'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.get(
+            query_params=params, request_headers=headers)
+        data = response.body
+        unused = unassigned(data)
+        self.assertEqual(type(unused), list)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_assigned_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.assigned.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_pools_post(self):
+        data = {
+            "name": "marketing"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.pools.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_pools_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.pools.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_pools__pool_name__put(self):
+        data = {
+            "name": "new_pool_name"
+        }
+        pool_name = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.pools._(pool_name).put(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_pools__pool_name__get(self):
+        pool_name = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.pools._(
+            pool_name).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_pools__pool_name__delete(self):
+        pool_name = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.ips.pools._(
+            pool_name).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_ips_pools__pool_name__ips_post(self):
+        data = {
+            "ip": "0.0.0.0"
+        }
+        pool_name = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.ips.pools._(pool_name).ips.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_ips_pools__pool_name__ips__ip__delete(self):
+        pool_name = "test_url_param"
+        ip = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.ips.pools._(pool_name).ips._(
+            ip).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_ips_warmup_post(self):
+        data = {
+            "ip": "0.0.0.0"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.warmup.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_warmup_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.warmup.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_warmup__ip_address__get(self):
+        ip_address = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips.warmup._(
+            ip_address).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_ips_warmup__ip_address__delete(self):
+        ip_address = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.ips.warmup._(
+            ip_address).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_ips__ip_address__get(self):
+        ip_address = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.ips._(
+            ip_address).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_batch_post(self):
+        headers = {'X-Mock': 201}
+        response = self.sg.client.mail.batch.post(request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_mail_batch__batch_id__get(self):
+        batch_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail.batch._(
+            batch_id).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_send_post(self):
+        data = {
+            "asm": {
+                "group_id": 1,
+                "groups_to_display": [
+                    1,
+                    2,
+                    3
+                ]
+            },
+            "attachments": [
+                {
+                    "content": "[BASE64 encoded content block here]",
+                    "content_id": "ii_139db99fdb5c3704",
+                    "disposition": "inline",
+                    "filename": "file1.jpg",
+                    "name": "file1",
+                    "type": "jpg"
+                }
+            ],
+            "batch_id": "[YOUR BATCH ID GOES HERE]",
+            "categories": [
+                "category1",
+                "category2"
+            ],
+            "content": [
+                {
+                    "type": "text/html",
+                    "value": "<html><p>Hello, world!</p><img "
+                             "src=[CID GOES HERE]></img></html>"
+                }
+            ],
+            "custom_args": {
+                "New Argument 1": "New Value 1",
+                "activationAttempt": "1",
+                "customerAccountNumber": "[CUSTOMER ACCOUNT NUMBER GOES HERE]"
+            },
+            "from": {
+                "email": "sam.smith@example.com",
+                "name": "Sam Smith"
+            },
+            "headers": {},
+            "ip_pool_name": "[YOUR POOL NAME GOES HERE]",
+            "mail_settings": {
+                "bcc": {
+                    "email": "ben.doe@example.com",
+                    "enable": True
+                },
+                "bypass_list_management": {
+                    "enable": True
+                },
+                "footer": {
+                    "enable": True,
+                    "html": "<p>Thanks</br>The SendGrid Team</p>",
+                    "text": "Thanks,/n The SendGrid Team"
+                },
+                "sandbox_mode": {
+                    "enable": False
+                },
+                "spam_check": {
+                    "enable": True,
+                    "post_to_url": "http://example.com/compliance",
+                    "threshold": 3
+                }
+            },
+            "personalizations": [
+                {
+                    "bcc": [
+                        {
+                            "email": "sam.doe@example.com",
+                            "name": "Sam Doe"
+                        }
+                    ],
+                    "cc": [
+                        {
+                            "email": "jane.doe@example.com",
+                            "name": "Jane Doe"
+                        }
+                    ],
+                    "custom_args": {
+                        "New Argument 1": "New Value 1",
+                        "activationAttempt": "1",
+                        "customerAccountNumber":
+                            "[CUSTOMER ACCOUNT NUMBER GOES HERE]"
+                    },
+                    "headers": {
+                        "X-Accept-Language": "en",
+                        "X-Mailer": "MyApp"
+                    },
+                    "send_at": 1409348513,
+                    "subject": "Hello, World!",
+                    "substitutions": {
+                        "id": "substitutions",
+                        "type": "object"
+                    },
+                    "to": [
+                        {
+                            "email": "john.doe@example.com",
+                            "name": "John Doe"
+                        }
+                    ]
+                }
+            ],
+            "reply_to": {
+                "email": "sam.smith@example.com",
+                "name": "Sam Smith"
+            },
+            "sections": {
+                "section": {
+                    ":sectionName1": "section 1 text",
+                    ":sectionName2": "section 2 text"
+                }
+            },
+            "send_at": 1409348513,
+            "subject": "Hello, World!",
+            "template_id": "[YOUR TEMPLATE ID GOES HERE]",
+            "tracking_settings": {
+                "click_tracking": {
+                    "enable": True,
+                    "enable_text": True
+                },
+                "ganalytics": {
+                    "enable": True,
+                    "utm_campaign": "[NAME OF YOUR REFERRER SOURCE]",
+                    "utm_content": "[USE THIS SPACE TO DIFFERENTIATE "
+                                   "YOUR EMAIL FROM ADS]",
+                    "utm_medium": "[NAME OF YOUR MARKETING MEDIUM e.g. email]",
+                    "utm_name": "[NAME OF YOUR CAMPAIGN]",
+                    "utm_term": "[IDENTIFY PAID KEYWORDS HERE]"
+                },
+                "open_tracking": {
+                    "enable": True,
+                    "substitution_tag": "%opentrack"
+                },
+                "subscription_tracking": {
+                    "enable": True,
+                    "html": "If you would like to unsubscribe and stop "
+                            "receiving these emails <% clickhere %>.",
+                    "substitution_tag": "<%click here%>",
+                    "text": "If you would like to unsubscribe and stop "
+                            "receiving these emails <% click here %>."
+                }
+            }
+        }
+        headers = {'X-Mock': 202}
+        response = self.sg.client.mail.send.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 202)
+
+    def test_mail_settings_get(self):
+        params = {'limit': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_address_whitelist_patch(self):
+        data = {
+            "enabled": True,
+            "list": [
+                "email1@example.com",
+                "example.com"
+            ]
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.address_whitelist.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_address_whitelist_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.address_whitelist.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_bcc_patch(self):
+        data = {
+            "email": "email@example.com",
+            "enabled": False
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.bcc.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_bcc_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.bcc.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_bounce_purge_patch(self):
+        data = {
+            "enabled": True,
+            "hard_bounces": 5,
+            "soft_bounces": 5
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.bounce_purge.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_bounce_purge_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.bounce_purge.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_footer_patch(self):
+        data = {
+            "enabled": True,
+            "html_content": "...",
+            "plain_content": "..."
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.footer.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_footer_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.footer.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_forward_bounce_patch(self):
+        data = {
+            "email": "example@example.com",
+            "enabled": True
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.forward_bounce.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_forward_bounce_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.forward_bounce.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_forward_spam_patch(self):
+        data = {
+            "email": "",
+            "enabled": False
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.forward_spam.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_forward_spam_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.forward_spam.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_plain_content_patch(self):
+        data = {
+            "enabled": False
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.plain_content.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_plain_content_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.plain_content.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_spam_check_patch(self):
+        data = {
+            "enabled": True,
+            "max_score": 5,
+            "url": "url"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.spam_check.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_spam_check_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.spam_check.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_template_patch(self):
+        data = {
+            "enabled": True,
+            "html_content": "<% body %>"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.template.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mail_settings_template_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mail_settings.template.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_mailbox_providers_stats_get(self):
+        params = {
+            'end_date': '2016-04-01',
+            'mailbox_providers': 'test_string',
+            'aggregated_by': 'day',
+            'limit': 1,
+            'offset': 1,
+            'start_date': '2016-01-01'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.mailbox_providers.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_partner_settings_get(self):
+        params = {'limit': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.partner_settings.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_partner_settings_new_relic_patch(self):
+        data = {
+            "enable_subuser_statistics": True,
+            "enabled": True,
+            "license_key": ""
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.partner_settings.new_relic.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_partner_settings_new_relic_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.partner_settings.new_relic.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_scopes_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.scopes.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_senders_post(self):
+        data = {
+            "address": "123 Elm St.",
+            "address_2": "Apt. 456",
+            "city": "Denver",
+            "country": "United States",
+            "from": {
+                "email": "from@example.com",
+                "name": "Example INC"
+            },
+            "nickname": "My Sender ID",
+            "reply_to": {
+                "email": "replyto@example.com",
+                "name": "Example INC"
+            },
+            "state": "Colorado",
+            "zip": "80202"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.senders.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_senders_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.senders.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_senders__sender_id__patch(self):
+        data = {
+            "address": "123 Elm St.",
+            "address_2": "Apt. 456",
+            "city": "Denver",
+            "country": "United States",
+            "from": {
+                "email": "from@example.com",
+                "name": "Example INC"
+            },
+            "nickname": "My Sender ID",
+            "reply_to": {
+                "email": "replyto@example.com",
+                "name": "Example INC"
+            },
+            "state": "Colorado",
+            "zip": "80202"
+        }
+        sender_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.senders._(sender_id).patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_senders__sender_id__get(self):
+        sender_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.senders._(
+            sender_id).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_senders__sender_id__delete(self):
+        sender_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.senders._(
+            sender_id).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_senders__sender_id__resend_verification_post(self):
+        sender_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.senders._(
+            sender_id).resend_verification.post(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_stats_get(self):
+        params = {
+            'aggregated_by': 'day',
+            'limit': 1,
+            'start_date': '2016-01-01',
+            'end_date': '2016-04-01',
+            'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers_post(self):
+        data = {
+            "email": "John@example.com",
+            "ips": [
+                "1.1.1.1",
+                "2.2.2.2"
+            ],
+            "password": "johns_password",
+            "username": "John@example.com"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers_get(self):
+        params = {'username': 'test_string', 'limit': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers_reputations_get(self):
+        params = {'usernames': 'test_string'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers.reputations.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers_stats_get(self):
+        params = {
+            'end_date': '2016-04-01',
+            'aggregated_by': 'day',
+            'limit': 1,
+            'offset': 1,
+            'start_date': '2016-01-01',
+            'subusers': 'test_string'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers_stats_monthly_get(self):
+        params = {
+            'subuser': 'test_string',
+            'limit': 1,
+            'sort_by_metric': 'test_string',
+            'offset': 1,
+            'date': 'test_string',
+            'sort_by_direction': 'asc'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers.stats.monthly.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers_stats_sums_get(self):
+        params = {
+            'end_date': '2016-04-01',
+            'aggregated_by': 'day',
+            'limit': 1,
+            'sort_by_metric': 'test_string',
+            'offset': 1,
+            'start_date': '2016-01-01',
+            'sort_by_direction': 'asc'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers.stats.sums.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers__subuser_name__patch(self):
+        data = {
+            "disabled": False
+        }
+        subuser_name = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.subusers._(subuser_name).patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_subusers__subuser_name__delete(self):
+        subuser_name = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.subusers._(
+            subuser_name).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_subusers__subuser_name__ips_put(self):
+        data = [
+            "127.0.0.1"
+        ]
+        subuser_name = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers._(subuser_name).ips.put(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers__subuser_name__monitor_put(self):
+        data = {
+            "email": "example@example.com",
+            "frequency": 500
+        }
+        subuser_name = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers._(subuser_name).monitor.put(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers__subuser_name__monitor_post(self):
+        data = {
+            "email": "example@example.com",
+            "frequency": 50000
+        }
+        subuser_name = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers._(subuser_name).monitor.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers__subuser_name__monitor_get(self):
+        subuser_name = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers._(
+            subuser_name).monitor.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_subusers__subuser_name__monitor_delete(self):
+        subuser_name = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.subusers._(
+            subuser_name).monitor.delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_subusers__subuser_name__stats_monthly_get(self):
+        params = {
+            'date': 'test_string',
+            'sort_by_direction': 'asc',
+            'limit': 1,
+            'sort_by_metric': 'test_string',
+            'offset': 1}
+        subuser_name = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.subusers._(subuser_name).stats.monthly.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_blocks_get(self):
+        params = {'start_time': 1, 'limit': 1, 'end_time': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.blocks.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_blocks_delete(self):
+        data = {
+            "delete_all": False,
+            "emails": [
+                "example1@example.com",
+                "example2@example.com"
+            ]
+        }
+        headers = {'X-Mock': 204}
+        response = self.sg.client.suppression.blocks.delete(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_suppression_blocks__email__get(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.blocks._(
+            email).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_blocks__email__delete(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.suppression.blocks._(
+            email).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_suppression_bounces_get(self):
+        params = {'start_time': 1, 'end_time': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.bounces.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_bounces_delete(self):
+        data = {
+            "delete_all": True,
+            "emails": [
+                "example@example.com",
+                "example2@example.com"
+            ]
+        }
+        headers = {'X-Mock': 204}
+        response = self.sg.client.suppression.bounces.delete(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_suppression_bounces__email__get(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.bounces._(
+            email).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_bounces__email__delete(self):
+        params = {'email_address': 'example@example.com'}
+        email = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.suppression.bounces._(email).delete(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_suppression_invalid_emails_get(self):
+        params = {'start_time': 1, 'limit': 1, 'end_time': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.invalid_emails.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_invalid_emails_delete(self):
+        data = {
+            "delete_all": False,
+            "emails": [
+                "example1@example.com",
+                "example2@example.com"
+            ]
+        }
+        headers = {'X-Mock': 204}
+        response = self.sg.client.suppression.invalid_emails.delete(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_suppression_invalid_emails__email__get(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.invalid_emails._(
+            email).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_invalid_emails__email__delete(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.suppression.invalid_emails._(
+            email).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_suppression_spam_report__email__get(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.spam_reports._(
+            email).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_spam_report__email__delete(self):
+        email = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.suppression.spam_reports._(
+            email).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_suppression_spam_reports_get(self):
+        params = {'start_time': 1, 'limit': 1, 'end_time': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.spam_reports.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_suppression_spam_reports_delete(self):
+        data = {
+            "delete_all": False,
+            "emails": [
+                "example1@example.com",
+                "example2@example.com"
+            ]
+        }
+        headers = {'X-Mock': 204}
+        response = self.sg.client.suppression.spam_reports.delete(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_suppression_unsubscribes_get(self):
+        params = {'start_time': 1, 'limit': 1, 'end_time': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.suppression.unsubscribes.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_templates_post(self):
+        data = {
+            "name": "example_name"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.templates.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_templates_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.templates.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_templates__template_id__patch(self):
+        data = {
+            "name": "new_example_name"
+        }
+        template_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.templates._(template_id).patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_templates__template_id__get(self):
+        template_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.templates._(
+            template_id).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_templates__template_id__delete(self):
+        template_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.templates._(
+            template_id).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_templates__template_id__versions_post(self):
+        data = {
+            "active": 1,
+            "html_content": "<%body%>",
+            "name": "example_version_name",
+            "plain_content": "<%body%>",
+            "subject": "<%subject%>",
+            "template_id": "ddb96bbc-9b92-425e-8979-99464621b543"
+        }
+        template_id = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.templates._(template_id).versions.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_templates__template_id__versions__version_id__patch(self):
+        data = {
+            "active": 1,
+            "html_content": "<%body%>",
+            "name": "updated_example_name",
+            "plain_content": "<%body%>",
+            "subject": "<%subject%>"
+        }
+        template_id = "test_url_param"
+        version_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.templates._(template_id).versions._(
+            version_id).patch(request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_templates__template_id__versions__version_id__get(self):
+        template_id = "test_url_param"
+        version_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.templates._(template_id).versions._(
+            version_id).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_templates__template_id__versions__version_id__delete(self):
+        template_id = "test_url_param"
+        version_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.templates._(template_id).versions._(
+            version_id).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_templates__template_id__versions__version_id__activate_post(self):
+        template_id = "test_url_param"
+        version_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.templates._(template_id).versions._(
+            version_id).activate.post(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_get(self):
+        params = {'limit': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_click_patch(self):
+        data = {
+            "enabled": True
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.click.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_click_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.click.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_google_analytics_patch(self):
+        data = {
+            "enabled": True,
+            "utm_campaign": "website",
+            "utm_content": "",
+            "utm_medium": "email",
+            "utm_source": "sendgrid.com",
+            "utm_term": ""
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.google_analytics.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_google_analytics_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.google_analytics.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_open_patch(self):
+        data = {
+            "enabled": True
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.open.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_open_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.open.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_subscription_patch(self):
+        data = {
+            "enabled": True,
+            "html_content": "html content",
+            "landing": "landing page html",
+            "plain_content": "text content",
+            "replace": "replacement tag",
+            "url": "url"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.subscription.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_tracking_settings_subscription_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.tracking_settings.subscription.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_account_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.account.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_credits_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.credits.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_email_put(self):
+        data = {
+            "email": "example@example.com"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.email.put(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_email_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.email.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_password_put(self):
+        data = {
+            "new_password": "new_password",
+            "old_password": "old_password"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.password.put(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_profile_patch(self):
+        data = {
+            "city": "Orange",
+            "first_name": "Example",
+            "last_name": "User"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.profile.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_profile_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.profile.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_scheduled_sends_post(self):
+        data = {
+            "batch_id": "YOUR_BATCH_ID",
+            "status": "pause"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.user.scheduled_sends.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_user_scheduled_sends_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.scheduled_sends.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_scheduled_sends__batch_id__patch(self):
+        data = {
+            "status": "pause"
+        }
+        batch_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.user.scheduled_sends._(
+            batch_id).patch(request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_user_scheduled_sends__batch_id__get(self):
+        batch_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.scheduled_sends._(
+            batch_id).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_scheduled_sends__batch_id__delete(self):
+        batch_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.user.scheduled_sends._(
+            batch_id).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_user_settings_enforced_tls_patch(self):
+        data = {
+            "require_tls": True,
+            "require_valid_cert": False
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.settings.enforced_tls.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_settings_enforced_tls_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.settings.enforced_tls.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_username_put(self):
+        data = {
+            "username": "test_username"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.username.put(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_username_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.username.get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_webhooks_event_settings_patch(self):
+        data = {
+            "bounce": True,
+            "click": True,
+            "deferred": True,
+            "delivered": True,
+            "dropped": True,
+            "enabled": True,
+            "group_resubscribe": True,
+            "group_unsubscribe": True,
+            "open": True,
+            "processed": True,
+            "spam_report": True,
+            "unsubscribe": True,
+            "url": "url"
+        }
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.webhooks.event.settings.patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_webhooks_event_settings_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.webhooks.event.settings.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_webhooks_event_test_post(self):
+        data = {
+            "url": "url"
+        }
+        headers = {'X-Mock': 204}
+        response = self.sg.client.user.webhooks.event.test.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_user_webhooks_parse_settings_post(self):
+        data = {
+            "hostname": "myhostname.com",
+            "send_raw": False,
+            "spam_check": True,
+            "url": "http://email.myhosthame.com"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.user.webhooks.parse.settings.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_user_webhooks_parse_settings_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.webhooks.parse.settings.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_webhooks_parse_settings__hostname__patch(self):
+        data = {
+            "send_raw": True,
+            "spam_check": False,
+            "url": "http://newdomain.com/parse"
+        }
+        hostname = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.webhooks.parse.settings._(
+            hostname).patch(request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_webhooks_parse_settings__hostname__get(self):
+        hostname = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.webhooks.parse.settings._(
+            hostname).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_user_webhooks_parse_settings__hostname__delete(self):
+        hostname = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.user.webhooks.parse.settings._(
+            hostname).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_user_webhooks_parse_stats_get(self):
+        params = {
+            'aggregated_by': 'day',
+            'limit': 'test_string',
+            'start_date': '2016-01-01',
+            'end_date': '2016-04-01',
+            'offset': 'test_string'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.user.webhooks.parse.stats.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_domains_post(self):
+        data = {
+            "automatic_security": False,
+            "custom_spf": True,
+            "default": True,
+            "domain": "example.com",
+            "ips": [
+                "192.168.1.1",
+                "192.168.1.2"
+            ],
+            "subdomain": "news",
+            "username": "john@example.com"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.whitelabel.domains.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_whitelabel_domains_get(self):
+        params = {
+            'username': 'test_string',
+            'domain': 'test_string',
+            'exclude_subusers': 'true',
+            'limit': 1,
+            'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.domains.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_domains_default_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.domains.default.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_domains_subuser_get(self):
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.domains.subuser.get(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_domains_subuser_delete(self):
+        headers = {'X-Mock': 204}
+        response = self.sg.client.whitelabel.domains.subuser.delete(
+            request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_whitelabel_domains__domain_id__patch(self):
+        data = {
+            "custom_spf": True,
+            "default": False
+        }
+        domain_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.domains._(
+            domain_id).patch(request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_domains__domain_id__get(self):
+        domain_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.domains._(
+            domain_id).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_domains__domain_id__delete(self):
+        domain_id = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.whitelabel.domains._(
+            domain_id).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_whitelabel_domains__domain_id__subuser_post(self):
+        data = {
+            "username": "jane@example.com"
+        }
+        domain_id = "test_url_param"
+        headers = {'X-Mock': 201}
+        response = self.sg.client.whitelabel.domains._(
+            domain_id).subuser.post(request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_whitelabel_domains__id__ips_post(self):
+        data = {
+            "ip": "192.168.0.1"
+        }
+        id_ = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.domains._(
+            id_).ips.post(request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_domains__id__ips__ip__delete(self):
+        id_ = "test_url_param"
+        ip = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.domains._(
+            id_).ips._(ip).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_domains__id__validate_post(self):
+        id_ = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.domains._(
+            id_).validate.post(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_ips_post(self):
+        data = {
+            "domain": "example.com",
+            "ip": "192.168.1.1",
+            "subdomain": "email"
+        }
+        headers = {'X-Mock': 201}
+        response = self.sg.client.whitelabel.ips.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_whitelabel_ips_get(self):
+        params = {'ip': 'test_string', 'limit': 1, 'offset': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.ips.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_ips__id__get(self):
+        id_ = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.ips._(
+            id_).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_ips__id__delete(self):
+        id_ = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.whitelabel.ips._(
+            id_).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_whitelabel_ips__id__validate_post(self):
+        id_ = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.ips._(
+            id_).validate.post(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_links_post(self):
+        data = {
+            "default": True,
+            "domain": "example.com",
+            "subdomain": "mail"
+        }
+        params = {'limit': 1, 'offset': 1}
+        headers = {'X-Mock': 201}
+        response = self.sg.client.whitelabel.links.post(
+            request_body=data, query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 201)
+
+    def test_whitelabel_links_get(self):
+        params = {'limit': 1}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.links.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_links_default_get(self):
+        params = {'domain': 'test_string'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.links.default.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_links_subuser_get(self):
+        params = {'username': 'test_string'}
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.links.subuser.get(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_links_subuser_delete(self):
+        params = {'username': 'test_string'}
+        headers = {'X-Mock': 204}
+        response = self.sg.client.whitelabel.links.subuser.delete(
+            query_params=params, request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_whitelabel_links__id__patch(self):
+        data = {
+            "default": True
+        }
+        id_ = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.links._(id_).patch(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_links__id__get(self):
+        id_ = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.links._(
+            id_).get(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_links__id__delete(self):
+        id_ = "test_url_param"
+        headers = {'X-Mock': 204}
+        response = self.sg.client.whitelabel.links._(
+            id_).delete(request_headers=headers)
+        self.assertEqual(response.status_code, 204)
+
+    def test_whitelabel_links__id__validate_post(self):
+        id_ = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.links._(
+            id_).validate.post(request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_whitelabel_links__link_id__subuser_post(self):
+        data = {
+            "username": "jane@example.com"
+        }
+        link_id = "test_url_param"
+        headers = {'X-Mock': 200}
+        response = self.sg.client.whitelabel.links._(link_id).subuser.post(
+            request_body=data, request_headers=headers)
+        self.assertEqual(response.status_code, 200)
+
+    def test_license_year(self):
+        LICENSE_FILE = 'LICENSE'
+        copyright_line = ''
+        with open(LICENSE_FILE, 'r') as f:
+            for line in f:
+                if line.startswith('Copyright'):
+                    copyright_line = line.strip()
+                    break
+        self.assertEqual(
+            'Copyright (C) %s, Twilio SendGrid, Inc. <help@twilio.com>' % datetime.datetime.now().year,
+            copyright_line)
diff --git a/.venv/lib/python3.12/site-packages/test/unit/__init__.py b/.venv/lib/python3.12/site-packages/test/unit/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/__init__.py
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_app.py b/.venv/lib/python3.12/site-packages/test/unit/test_app.py
new file mode 100644
index 00000000..56027d57
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_app.py
@@ -0,0 +1,22 @@
+import os
+import unittest
+
+from sendgrid.helpers.inbound.config import Config
+from sendgrid.helpers.inbound.app import app
+
+
+class UnitTests(unittest.TestCase):
+
+    def setUp(self):
+        self.config = Config()
+        app.testing = True
+        self.tester = app.test_client(self)
+
+    def test_up_and_running(self):
+        response = self.tester.get('/')
+        self.assertEqual(response.status_code, 200)
+
+    def test_used_port_true(self):
+        if self.config.debug_mode:
+            port = int(os.environ.get("PORT", self.config.port))
+            self.assertEqual(port, self.config.port)
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_config.py b/.venv/lib/python3.12/site-packages/test/unit/test_config.py
new file mode 100644
index 00000000..f60306a5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_config.py
@@ -0,0 +1,60 @@
+import os
+import unittest
+
+import sendgrid.helpers.inbound.config
+from sendgrid.helpers.inbound.config import Config
+
+
+class UnitTests(unittest.TestCase):
+
+    def setUp(self):
+        self.config = Config()
+
+    def test_initialization(self):
+        endpoint = '/inbound'
+        port = 5000
+        keys = [
+            'from',
+            'attachments',
+            'headers',
+            'text',
+            'envelope',
+            'to',
+            'html',
+            'sender_ip',
+            'attachment-info',
+            'subject',
+            'dkim',
+            'SPF',
+            'charsets',
+            'content-ids',
+            'spam_report',
+            'spam_score',
+            'email',
+        ]
+        host = 'http://127.0.0.1:5000/inbound'
+
+        self.assertTrue(self.config.debug_mode)
+        self.assertEqual(self.config.endpoint, endpoint)
+        self.assertEqual(self.config.host, host)
+        self.assertEqual(self.config.port, port)
+        for key in keys:
+            self.assertIn(key, self.config.keys)
+
+    def test_init_environment_should_set_env_from_dotenv(self):
+        config_file = sendgrid.helpers.inbound.config.__file__
+        env_file_path = '{0}/.env'.format(os.path.abspath(os.path.dirname(config_file)))
+        with open(env_file_path, 'w') as f:
+            f.write('RANDOM_VARIABLE=RANDOM_VALUE')
+        Config()
+        os.remove(env_file_path)
+        self.assertEqual(os.environ['RANDOM_VARIABLE'], 'RANDOM_VALUE')
+
+    def test_init_environment_should_not_set_env_if_format_is_invalid(self):
+        config_file = sendgrid.helpers.inbound.config.__file__
+        env_file_path = os.path.abspath(os.path.dirname(config_file)) + '/.env'
+        with open(env_file_path, 'w') as f:
+            f.write('RANDOM_VARIABLE=RANDOM_VALUE=ANOTHER_RANDOM_VALUE')
+        Config()
+        os.remove(env_file_path)
+        self.assertIsNone(os.environ.get('RANDOM_VARIABLE'))
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_email.py b/.venv/lib/python3.12/site-packages/test/unit/test_email.py
new file mode 100644
index 00000000..9db06070
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_email.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+import unittest
+
+from sendgrid.helpers.mail import (Email)
+
+
+class TestEmailObject(unittest.TestCase):
+
+    def test_add_email_address(self):
+        address = "test@example.com"
+        email = Email(address)
+
+        self.assertEqual(email.email, "test@example.com")
+
+    def test_add_name(self):
+        name = "SomeName"
+        email = Email(name=name)
+
+        self.assertEqual(email.name, name)
+
+    def test_add_unicode_name(self):
+        name = u"SomeName"
+        email = Email(name=name)
+
+        self.assertEqual(email.name, name)
+
+    def test_add_name_email(self):
+        name = "SomeName"
+        address = "test@example.com"
+        email = Email(email=address, name=name)
+        self.assertEqual(email.name, name)
+        self.assertEqual(email.email, "test@example.com")
+
+    def test_add_unicode_name_email(self):
+        name = u"SomeName"
+        address = u"test@example.com"
+        email = Email(email=address, name=name)
+        self.assertEqual(email.name, name)
+        self.assertEqual(email.email, u"test@example.com")
+
+    def test_add_rfc_function_finds_name_not_email(self):
+        name = "SomeName"
+        email = Email(name)
+
+        self.assertEqual(email.name, name)
+        self.assertIsNone(email.email)
+
+    def test_add_rfc_email(self):
+        name = "SomeName"
+        address = "test@example.com"
+        name_address = "{} <{}>".format(name, address)
+        email = Email(name_address)
+        self.assertEqual(email.name, name)
+        self.assertEqual(email.email, "test@example.com")
+
+    def test_empty_obj_add_name(self):
+        email = Email()
+        name = "SomeName"
+        email.name = name
+
+        self.assertEqual(email.name, name)
+
+    def test_empty_obj_add_email(self):
+        email = Email()
+        address = "test@example.com"
+        email.email = address
+
+        self.assertEqual(email.email, address)
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_eventwebhook.py b/.venv/lib/python3.12/site-packages/test/unit/test_eventwebhook.py
new file mode 100644
index 00000000..eee1eabf
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_eventwebhook.py
@@ -0,0 +1,50 @@
+import json
+import unittest
+
+from sendgrid import EventWebhook
+
+
+class UnitTests(unittest.TestCase):
+    @classmethod
+    def setUpClass(cls):
+        cls.PUBLIC_KEY = 'MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE83T4O/n84iotIvIW4mdBgQ/7dAfSmpqIM8kF9mN1flpVKS3GRqe62gw+2fNNRaINXvVpiglSI8eNEc6wEA3F+g=='
+        cls.SIGNATURE = 'MEUCIGHQVtGj+Y3LkG9fLcxf3qfI10QysgDWmMOVmxG0u6ZUAiEAyBiXDWzM+uOe5W0JuG+luQAbPIqHh89M15TluLtEZtM='
+        cls.TIMESTAMP = '1600112502'
+        cls.PAYLOAD = json.dumps(
+            [
+                {
+                    'email': 'hello@world.com',
+                    'event': 'dropped',
+                    'reason': 'Bounced Address',
+                    'sg_event_id': 'ZHJvcC0xMDk5NDkxOS1MUnpYbF9OSFN0T0doUTRrb2ZTbV9BLTA',
+                    'sg_message_id': 'LRzXl_NHStOGhQ4kofSm_A.filterdrecv-p3mdw1-756b745b58-kmzbl-18-5F5FC76C-9.0',
+                    'smtp-id': '<LRzXl_NHStOGhQ4kofSm_A@ismtpd0039p1iad1.sendgrid.net>',
+                    'timestamp': 1600112492,
+                }
+            ], sort_keys=True, separators=(',', ':')
+        ) + '\r\n'  # Be sure to include the trailing carriage return and newline!
+
+    def test_verify_valid_signature(self):
+        ew = EventWebhook()
+        key = ew.convert_public_key_to_ecdsa(self.PUBLIC_KEY)
+        self.assertTrue(ew.verify_signature(self.PAYLOAD, self.SIGNATURE, self.TIMESTAMP, key))
+
+    def test_verify_bad_key(self):
+        ew = EventWebhook('MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqTxd43gyp8IOEto2LdIfjRQrIbsd4SXZkLW6jDutdhXSJCWHw8REntlo7aNDthvj+y7GjUuFDb/R1NGe1OPzpA==')
+        self.assertFalse(ew.verify_signature(self.PAYLOAD, self.SIGNATURE, self.TIMESTAMP))
+
+    def test_verify_bad_payload(self):
+        ew = EventWebhook(self.PUBLIC_KEY)
+        self.assertFalse(ew.verify_signature('payload', self.SIGNATURE, self.TIMESTAMP))
+
+    def test_verify_bad_signature(self):
+        ew = EventWebhook(self.PUBLIC_KEY)
+        self.assertFalse(ew.verify_signature(
+            self.PAYLOAD,
+            'MEUCIQCtIHJeH93Y+qpYeWrySphQgpNGNr/U+UyUlBkU6n7RAwIgJTz2C+8a8xonZGi6BpSzoQsbVRamr2nlxFDWYNH3j/0=',
+            self.TIMESTAMP
+        ))
+
+    def test_verify_bad_timestamp(self):
+        ew = EventWebhook(self.PUBLIC_KEY)
+        self.assertFalse(ew.verify_signature(self.PAYLOAD, self.SIGNATURE, 'timestamp'))
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_inbound_send.py b/.venv/lib/python3.12/site-packages/test/unit/test_inbound_send.py
new file mode 100644
index 00000000..19ee5de1
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_inbound_send.py
@@ -0,0 +1,49 @@
+import argparse
+import unittest
+
+from sendgrid.helpers.inbound import send
+
+try:
+    import unittest.mock as mock
+except ImportError:
+    import mock
+
+
+class UnitTests(unittest.TestCase):
+    def setUp(self):
+        self.client_mock = mock.patch('sendgrid.helpers.inbound.send.Client')
+        self.open_mock = mock.patch('sendgrid.helpers.inbound.send.open',
+                                    mock.mock_open(), create=True)
+        self.client_mock.start()
+        self.open_mock.start()
+
+    def tearDown(self):
+        self.client_mock.stop()
+        self.open_mock.stop()
+
+    def test_send(self):
+
+        fake_url = 'https://fake_url'
+        x = send.Send(fake_url)
+        x.test_payload(fake_url)
+
+        send.Client.assert_called_once_with(
+            host=fake_url,
+            request_headers={
+                'User-Agent': 'SendGrid-Test',
+                'Content-Type': 'multipart/form-data; boundary=xYzZY'
+            })
+
+    def test_main_call(self):
+        fake_url = 'https://fake_url'
+
+        with mock.patch(
+            'argparse.ArgumentParser.parse_args',
+            return_value=argparse.Namespace(
+                host=fake_url, data='test_file.txt')):
+            send.main()
+            send.Client.assert_called_once_with(
+                host=fake_url,
+                request_headers={
+                    'User-Agent': 'SendGrid-Test',
+                    'Content-Type': 'multipart/form-data; boundary=xYzZY'})
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_mail_helpers.py b/.venv/lib/python3.12/site-packages/test/unit/test_mail_helpers.py
new file mode 100644
index 00000000..c00307d4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_mail_helpers.py
@@ -0,0 +1,1766 @@
+# -*- coding: utf-8 -*-
+import json
+import unittest
+
+try:
+    from email.message import EmailMessage
+except ImportError:
+    # Python2
+    from email import message
+    EmailMessage = message.Message
+
+from sendgrid.helpers.mail import (
+    Asm, Attachment,
+    ClickTracking, Content,
+    DynamicTemplateData, Email, From,
+    Mail, Personalization,
+    Subject, Substitution, To, Cc, Bcc, TrackingSettings
+)
+
+# The below amp html email content is taken from [Google AMP Hello World Email](https://amp.dev/documentation/examples/introduction/hello_world_email/)
+amp_html_content = '''<!doctype html><html amp4email><head><meta charset="utf-8"><script async src="https://cdn.ampproject.org/v0.js"></script><style amp4email-boilerplate>body{visibility:hidden}</style><script async custom-element="amp-carousel" src="https://cdn.ampproject.org/v0/amp-carousel-0.1.js"></script><style amp-custom>.emailbody {padding: 16px;}.helloworld {font-family: Helvetica;color: red;font-size: 24px;padding-bottom: 8px;}.images {max-width: 100%;}</style></head><body><div class="emailbody"><h1 class="helloworld">Hello!</h1><amp-img src="https://amp.dev/static/samples/img/amp.jpg" width="800" height="600" layout="responsive"></amp-img></div></body></html>'''
+
+response_content_with_all_three_mime_contents = json.dumps({
+    "content": [
+        {
+            "type": "text/plain",
+            "value": "and easy to do anywhere, even with Python"
+        },
+        {
+            "type": "text/x-amp-html",
+            "value": amp_html_content
+        },
+        {
+            "type": "text/html",
+            "value": "<strong>and easy to do anywhere, even with Python</strong>"
+        }
+    ],
+    "from": {
+        "email": "test+from@example.com",
+        "name": "Example From Name"
+    },
+    "personalizations": [
+        {
+            "to": [
+                {
+                    "email": "test+to@example.com",
+                    "name": "Example To Name"
+                }
+            ]
+        }
+    ],
+    "subject": "Sending with SendGrid is Fun"
+})
+
+class UnitTests(unittest.TestCase):
+
+    def test_asm(self):
+        from sendgrid.helpers.mail import (GroupId, GroupsToDisplay)
+        asm1 = Asm(GroupId(1), GroupsToDisplay([1, 2, 3]))
+        asm2 = Asm(1, [1, 2, 3])
+        self.assertEqual(
+            asm1.group_id.get(), asm2.group_id.get())
+        self.assertEqual(
+            asm1.groups_to_display.get(), asm2.groups_to_display.get())
+
+    def test_attachment(self):
+        from sendgrid.helpers.mail import (FileContent, FileType, FileName,
+                                           Disposition, ContentId)
+        a1 = Attachment(
+            FileContent('Base64EncodedString'),
+            FileName('example.pdf'),
+            FileType('application/pdf'),
+            Disposition('attachment'),
+            ContentId('123')
+        )
+        a2 = Attachment(
+            'Base64EncodedString',
+            'example.pdf',
+            'application/pdf',
+            'attachment',
+            '123'
+        )
+        self.assertEqual(a1.file_content.get(), a2.file_content.get())
+        self.assertEqual(a1.file_name.get(), a2.file_name.get())
+        self.assertEqual(a1.file_type.get(), a2.file_type.get())
+        self.assertEqual(a1.disposition.get(), a2.disposition.get())
+        self.assertEqual(a1.content_id.get(), a2.content_id.get())
+
+    def test_batch_id(self):
+        from sendgrid.helpers.mail import BatchId
+
+        b1 = BatchId('1')
+        self.assertEqual('1', b1.get())
+
+    # Send a Single Email to a Single Recipient
+    def test_single_email_to_a_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "and easy to do anywhere, even with Python"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>and easy to do anywhere, even with Python</strong>"
+                    }
+                ],
+                "from": {
+                    "email": "test+from@example.com",
+                    "name": "Example From Name"
+                },
+                "personalizations": [
+                    {
+                        "to": [
+                            {
+                                "email": "test+to@example.com",
+                                "name": "Example To Name"
+                            }
+                        ]
+                    }
+                ],
+                "subject": "Sending with SendGrid is Fun"
+            }''')
+        )
+
+    def test_single_email_to_a_single_recipient_content_reversed(self):
+        """Tests bug found in Issue-451 with Content ordering causing a crash
+        """
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        message = Mail()
+        message.from_email = From('test+from@example.com', 'Example From Name')
+        message.to = To('test+to@example.com', 'Example To Name')
+        message.subject = Subject('Sending with SendGrid is Fun')
+        message.content = HtmlContent(
+            '<strong>and easy to do anywhere, even with Python</strong>')
+        message.content = PlainTextContent(
+            'and easy to do anywhere, even with Python')
+
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "and easy to do anywhere, even with Python"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>and easy to do anywhere, even with Python</strong>"
+                    }
+                ],
+                "from": {
+                    "email": "test+from@example.com",
+                    "name": "Example From Name"
+                },
+                "personalizations": [
+                    {
+                        "to": [
+                            {
+                                "email": "test+to@example.com",
+                                "name": "Example To Name"
+                            }
+                        ]
+                    }
+                ],
+                "subject": "Sending with SendGrid is Fun"
+            }''')
+        )
+
+    def test_send_a_single_email_to_multiple_recipients(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = [
+            To('test+to0@example.com', 'Example To Name 0'),
+            To('test+to1@example.com', 'Example To Name 1')
+        ]
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "and easy to do anywhere, even with Python"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>and easy to do anywhere, even with Python</strong>"
+                    }
+                ],
+                "from": {
+                    "email": "test+from@example.com",
+                    "name": "Example From Name"
+                },
+                "personalizations": [
+                    {
+                        "to": [
+                            {
+                                "email": "test+to0@example.com",
+                                "name": "Example To Name 0"
+                            },
+                            {
+                                "email": "test+to1@example.com",
+                                "name": "Example To Name 1"
+                            }
+                        ]
+                    }
+                ],
+                "subject": "Sending with SendGrid is Fun"
+            }''')
+        )
+
+    def test_send_a_single_email_with_multiple_reply_to_addresses(self):
+        from sendgrid.helpers.mail import (Mail, From, ReplyTo, To, Subject,
+                                           PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to0@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent('and easy to do anywhere, even with Python'),
+            html_content=HtmlContent('<strong>and easy to do anywhere, even with Python</strong>'))
+
+        message.reply_to_list = [ReplyTo(email = 'test+reply_to_1@example.com'), ReplyTo(email = 'test+reply_to_2@example.com')]
+
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "and easy to do anywhere, even with Python"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>and easy to do anywhere, even with Python</strong>"
+                    }
+                ],
+                "from": {
+                    "email": "test+from@example.com",
+                    "name": "Example From Name"
+                },
+                "personalizations": [
+                    {
+                        "to": [
+                            {
+                                "email": "test+to0@example.com",
+                                "name": "Example To Name"
+                            }
+                        ]
+                    }
+                ],
+                "reply_to_list": [
+                    {
+                        "email": "test+reply_to_1@example.com"
+                    },
+                    {
+                        "email": "test+reply_to_2@example.com"
+                    }
+                ],
+                "subject": "Sending with SendGrid is Fun"
+            }''')
+        )
+
+    def test_multiple_emails_to_multiple_recipients(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent,
+                                           Substitution)
+        self.maxDiff = None
+
+        to_emails = [
+            To(email='test+to0@example.com',
+               name='Example Name 0',
+               substitutions=[
+                   Substitution('-name-', 'Example Name Substitution 0'),
+                   Substitution('-github-', 'https://example.com/test0'),
+               ],
+               subject=Subject('Override Global Subject')),
+            To(email='test+to1@example.com',
+               name='Example Name 1',
+               substitutions=[
+                   Substitution('-name-', 'Example Name Substitution 1'),
+                   Substitution('-github-', 'https://example.com/test1'),
+               ])
+        ]
+        global_substitutions = Substitution('-time-', '2019-01-01 00:00:00')
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Hi -name-'),
+            plain_text_content=PlainTextContent(
+                'Hello -name-, your URL is -github-, email sent at -time-'),
+            html_content=HtmlContent(
+                '<strong>Hello -name-, your URL is <a href=\"-github-\">here</a></strong> email sent at -time-'),
+            global_substitutions=global_substitutions,
+            is_multiple=True)
+
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "Hello -name-, your URL is -github-, email sent at -time-"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>Hello -name-, your URL is <a href=\"-github-\">here</a></strong> email sent at -time-"
+                    }
+                ],
+                "from": {
+                    "email": "test+from@example.com",
+                    "name": "Example From Name"
+                },
+                "personalizations": [
+                    {
+                        "substitutions": {
+                            "-github-": "https://example.com/test1",
+                            "-name-": "Example Name Substitution 1",
+                            "-time-": "2019-01-01 00:00:00"
+                        },
+                        "to": [
+                            {
+                                "email": "test+to1@example.com",
+                                "name": "Example Name 1"
+                            }
+                        ]
+                    },
+                    {
+                        "subject": "Override Global Subject",
+                        "substitutions": {
+                            "-github-": "https://example.com/test0",
+                            "-name-": "Example Name Substitution 0",
+                            "-time-": "2019-01-01 00:00:00"
+                        },
+                        "to": [
+                            {
+                                "email": "test+to0@example.com",
+                                "name": "Example Name 0"
+                            }
+                        ]
+                    }
+                ],
+                "subject": "Hi -name-"
+            }''')
+        )
+
+    def test_single_email_with_all_three_email_contents_to_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            amp_html_content=AmpHtmlContent(amp_html_content),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>')
+        )
+
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content_with_all_three_mime_contents)
+        )
+
+    def test_single_email_with_amp_and_html_contents_to_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun'),
+            amp_html_content=AmpHtmlContent(amp_html_content),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>')
+        )
+
+        response_content = json.dumps({
+            "content": [
+                {
+                    "type": "text/x-amp-html",
+                    "value": amp_html_content
+                },
+                {
+                    "type": "text/html",
+                    "value": "<strong>and easy to do anywhere, even with Python</strong>"
+                }
+            ],
+            "from": {
+                "email": "test+from@example.com",
+                "name": "Example From Name"
+            },
+            "personalizations": [
+                {
+                    "to": [
+                        {
+                            "email": "test+to@example.com",
+                            "name": "Example To Name"
+                        }
+                    ]
+                }
+            ],
+            "subject": "Sending with SendGrid is Fun"
+        })
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content)
+        )
+
+    def test_single_email_with_amp_and_plain_contents_to_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            amp_html_content=AmpHtmlContent(amp_html_content)
+        )
+
+        response_content = json.dumps({
+            "content": [
+                {
+                    "type": "text/plain",
+                    "value": "and easy to do anywhere, even with Python"
+                },
+                {
+                    "type": "text/x-amp-html",
+                    "value": amp_html_content
+                }
+            ],
+            "from": {
+                "email": "test+from@example.com",
+                "name": "Example From Name"
+            },
+            "personalizations": [
+                {
+                    "to": [
+                        {
+                            "email": "test+to@example.com",
+                            "name": "Example To Name"
+                        }
+                    ]
+                }
+            ],
+            "subject": "Sending with SendGrid is Fun"
+        })
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content)
+        )
+
+    ## Check ordering of MIME types in different variants - start
+    def test_single_email_with_all_three_contents_in_collapsed_order_of_plain_amp_html_content_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun')
+        )
+        message.content = PlainTextContent(
+            'and easy to do anywhere, even with Python')
+        message.content = AmpHtmlContent(amp_html_content)
+        message.content = HtmlContent(
+            '<strong>and easy to do anywhere, even with Python</strong>')
+
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content_with_all_three_mime_contents)
+        )
+
+    def test_single_email_with_all_three_contents_in_collapsed_order_of_plain_html_amp_content_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun')
+        )
+        message.content = PlainTextContent(
+            'and easy to do anywhere, even with Python')
+        message.content = HtmlContent(
+            '<strong>and easy to do anywhere, even with Python</strong>')
+        message.content = AmpHtmlContent(amp_html_content)
+
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content_with_all_three_mime_contents)
+        )
+
+    def test_single_email_with_all_three_contents_in_collapsed_order_of_html_plain_amp_content_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun')
+        )
+        message.content = HtmlContent(
+            '<strong>and easy to do anywhere, even with Python</strong>')
+        message.content = PlainTextContent(
+            'and easy to do anywhere, even with Python')
+        message.content = AmpHtmlContent(amp_html_content)
+
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content_with_all_three_mime_contents)
+        )
+
+    def test_single_email_with_all_three_contents_in_collapsed_order_of_html_amp_plain_content_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun')
+        )
+        message.content = HtmlContent(
+            '<strong>and easy to do anywhere, even with Python</strong>')
+        message.content = AmpHtmlContent(amp_html_content)
+        message.content = PlainTextContent(
+            'and easy to do anywhere, even with Python')
+
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content_with_all_three_mime_contents)
+        )
+
+    def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_html_plain_content_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun')
+        )
+        message.content = AmpHtmlContent(amp_html_content)
+        message.content = HtmlContent(
+            '<strong>and easy to do anywhere, even with Python</strong>')
+        message.content = PlainTextContent(
+            'and easy to do anywhere, even with Python')
+
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content_with_all_three_mime_contents)
+        )
+
+    def test_single_email_with_all_three_contents_in_collapsed_order_of_amp_plain_html_content_single_recipient(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent, AmpHtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun')
+        )
+        message.content = AmpHtmlContent(amp_html_content)
+        message.content = PlainTextContent(
+            'and easy to do anywhere, even with Python')
+        message.content = HtmlContent(
+            '<strong>and easy to do anywhere, even with Python</strong>')
+
+        self.assertEqual(
+            message.get(),
+            json.loads(response_content_with_all_three_mime_contents)
+        )
+
+    ## end
+
+    def test_value_error_is_raised_on_to_emails_set_to_list_of_lists(self):
+        from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = [
+            ['test+to0@example.com', 'Example To Name 0'],
+            ['test+to1@example.com', 'Example To Name 1']
+        ]
+
+        with self.assertRaises(ValueError):
+            Mail(
+                from_email=From('test+from@example.com', 'Example From Name'),
+                to_emails=to_emails,
+                subject=Subject('Sending with SendGrid is Fun'),
+                plain_text_content=PlainTextContent(
+                    'and easy to do anywhere, even with Python'),
+                html_content=HtmlContent(
+                    '<strong>and easy to do anywhere, even with Python</strong>'))
+    
+    def test_value_error_is_raised_on_to_emails_set_to_reply_to_list_of_strs(self):
+        from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = [
+            ('test+to0@example.com', 'Example To Name 0'),
+            ('test+to1@example.com', 'Example To Name 1')
+        ]
+    
+        mail = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+        with self.assertRaises(ValueError):
+            mail.reply_to_list = ['test+reply_to0@example.com', 'test+reply_to1@example.com']
+    
+    def test_value_error_is_raised_on_to_emails_set_to_reply_to_list_of_tuples(self):
+        from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = [
+            ('test+to0@example.com', 'Example To Name 0'),
+            ('test+to1@example.com', 'Example To Name 1')
+        ]
+    
+        mail = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+        with self.assertRaises(ValueError):
+            mail.reply_to_list = [('test+reply_to@example.com', 'Test Name')]
+
+    def test_error_is_not_raised_on_to_emails_set_to_list_of_tuples(self):
+        from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = [
+            ('test+to0@example.com', 'Example To Name 0'),
+            ('test+to1@example.com', 'Example To Name 1')
+        ]
+
+        Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+
+    def test_error_is_not_raised_on_to_emails_set_to_list_of_strs(self):
+        from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = ['test+to0@example.com', 'test+to1@example.com']
+
+        Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+
+    def test_error_is_not_raised_on_to_emails_set_to_a_str(self):
+        from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = 'test+to0@example.com'
+
+        Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+
+    def test_error_is_not_raised_on_to_emails_set_to_a_tuple(self):
+        from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = ('test+to0@example.com', 'Example To Name 0')
+
+        Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+
+    def test_error_is_not_raised_on_to_emails_includes_bcc_cc(self):
+        from sendgrid.helpers.mail import (PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        to_emails = [
+            To('test+to0@example.com', 'Example To Name 0'),
+            Bcc('test+bcc@example.com', 'Example Bcc Name 1'),
+            Cc('test+cc@example.com', 'Example Cc Name 2')
+        ]
+
+        Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+
+    def test_personalization_add_email_filters_out_duplicate_to_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        to_email = To('test+to0@example.com', 'Example To Name 0')
+        p.add_email(to_email)
+        p.add_email(to_email)
+
+        self.assertEqual([to_email.get()], p.tos)
+
+    def test_personalization_add_email_filters_out_duplicate_to_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        to_email = To('test+to0@example.com', 'Example To Name 0')
+        to_email_with_caps = To('test+TO0@example.com', 'Example To Name 0')
+        p.add_email(to_email)
+        p.add_email(to_email_with_caps)
+
+        self.assertEqual([to_email.get()], p.tos)
+
+    def test_personalization_set_from_email(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        from_email = From('test+from@example.com', 'Example From')
+        p.set_from(from_email)
+
+        self.assertEqual(from_email.get(), p.from_email)
+
+    def test_personalization_filters_out_duplicate_cc_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        cc_email = Cc('test+cc0@example.com', 'Example Cc Name 0')
+        p.add_email(cc_email)
+        p.add_email(cc_email)
+
+        self.assertEqual([cc_email.get()], p.ccs)
+
+    def test_personalization_filters_out_duplicate_cc_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        cc_email = Cc('test+cc0@example.com', 'Example Cc Name 0')
+        cc_email_with_caps = Cc('test+CC0@example.com', 'Example Cc Name 0')
+        p.add_email(cc_email)
+        p.add_email(cc_email_with_caps)
+
+        self.assertEqual([cc_email.get()], p.ccs)
+
+    def test_personalization_filters_out_duplicate_bcc_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        bcc_email = Bcc('test+bcc0@example.com', 'Example Bcc Name 0')
+        p.add_email(bcc_email)
+        p.add_email(bcc_email)
+
+        self.assertEqual([bcc_email.get()], p.bccs)
+
+    def test_personalization_filters_out_duplicate_bcc_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        bcc_email = Bcc('test+bcc0@example.com', 'Example Bcc Name 0')
+        bcc_email_with_caps = Bcc('test+BCC0@example.com', 'Example Bcc Name 0')
+        p.add_email(bcc_email)
+        p.add_email(bcc_email_with_caps)
+
+        self.assertEqual([bcc_email.get()], p.bccs)
+
+    def test_personalization_tos_setter_filters_out_duplicate_dict_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        to_emails = [{ 'email': 'test+to0@example.com', 'name': 'Example To Name 0' }] * 2
+        p.tos = to_emails
+
+        self.assertEqual([to_emails[0]], p.tos)
+
+    def test_personalization_tos_setter_filters_out_duplicate_dict_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        to_email = { 'email': 'test+to0@example.com', 'name': 'Example To Name 0' }
+        to_email_with_caps = { 'email': 'test+TO0@example.com', 'name': 'Example To Name 0' }
+        to_emails = [to_email, to_email_with_caps]
+        p.tos = to_emails
+
+        self.assertEqual([to_email], p.tos)
+
+    def test_personalization_tos_setter_filters_out_duplicate_to_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        to_emails = [To('test+to0@example.com', 'Example To Name 0')] * 2
+        p.tos = to_emails
+
+        self.assertEqual([to_emails[0].get()], p.tos)
+
+
+    def test_personalization_tos_setter_filters_out_duplicate_to_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        to_email = To('test+to0@example.com', 'Example To Name 0')
+        to_email_with_caps = To('test+TO0@example.com', 'Example To Name 0')
+        to_emails = [to_email, to_email_with_caps]
+        p.tos = to_emails
+
+        self.assertEqual([to_email.get()], p.tos)
+
+    def test_personalization_ccs_setter_filters_out_duplicate_dict_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        cc_emails = [{ 'email': 'test+cc0@example.com', 'name': 'Example Cc Name 0' }] * 2
+        p.ccs = cc_emails
+
+        self.assertEqual([cc_emails[0]], p.ccs)
+
+    def test_personalization_ccs_setter_filters_out_duplicate_dict_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        cc_email = { 'email': 'test+cc0@example.com', 'name': 'Example Cc Name 0' }
+        cc_email_with_caps = { 'email': 'test+CC0@example.com', 'name': 'Example Cc Name 0' }
+        cc_emails = [cc_email, cc_email_with_caps]
+        p.ccs = cc_emails
+
+        self.assertEqual([cc_email], p.ccs)
+
+    def test_personalization_ccs_setter_filters_out_duplicate_cc_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        cc_emails = [Cc('test+cc0@example.com', 'Example Cc Name 0')] * 2
+        p.ccs = cc_emails
+
+        self.assertEqual([cc_emails[0].get()], p.ccs)
+
+    def test_personalization_ccs_setter_filters_out_duplicate_cc_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        cc_email = Cc('test+cc0@example.com', 'Example Cc Name 0')
+        cc_email_with_caps = Cc('test+CC0@example.com', 'Example Cc Name 0')
+        p.ccs = [cc_email, cc_email_with_caps]
+
+        self.assertEqual([cc_email.get()], p.ccs)
+
+    def test_personalization_bccs_setter_filters_out_duplicate_dict_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        bcc_emails = [{ 'email': 'test+bcc0@example.com', 'name': 'Example Bcc Name 0' }] * 2
+        p.bccs = bcc_emails
+
+        self.assertEqual([bcc_emails[0]], p.bccs)
+
+    def test_personalization_bccs_setter_filters_out_duplicate_dict_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        bcc_email = { 'email': 'test+bcc0@example.com', 'name': 'Example Bcc Name 0' }
+        bcc_email_with_caps = { 'email': 'test+BCC0@example.com', 'name': 'Example Bcc Name 0' }
+        bcc_emails = [bcc_email, bcc_email_with_caps]
+        p.bccs = bcc_emails
+
+        self.assertEqual([bcc_email], p.bccs)
+
+    def test_personalization_bccs_setter_filters_out_duplicate_bcc_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        bcc_emails = [Bcc('test+bcc0@example.com', 'Example Bcc Name 0')] * 2
+        p.bccs = bcc_emails
+
+        self.assertEqual([bcc_emails[0].get()], p.bccs)
+
+    def test_personalization_bccs_setter_filters_out_duplicate_bcc_emails_ignoring_case(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        bcc_email = Bcc('test+bcc0@example.com', 'Example Bcc Name 0')
+        bcc_email_with_caps = Bcc('test+BCC0@example.com', 'Example Bcc Name 0')
+        p.bccs = [bcc_email, bcc_email_with_caps]
+
+        self.assertEqual([bcc_email.get()], p.bccs)
+
+    def test_personalization_add_to_filters_out_duplicate_to_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        to_email = To('test+to0@example.com', 'Example To Name 0')
+        p.add_to(to_email)
+        p.add_to(to_email)
+
+        expected = [to_email.get()]
+
+        self.assertEqual(expected, p.tos)
+
+    def test_personalization_add_bcc_filters_out_duplicate_bcc_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        bcc_email = Bcc('test+to0@example.com', 'Example To Name 0')
+        p.add_bcc(bcc_email)
+        p.add_bcc(bcc_email)
+
+        expected = [bcc_email.get()]
+
+        self.assertEqual(expected, p.bccs)
+
+    def test_personalization_add_cc_filters_out_duplicate_cc_emails(self):
+        self.maxDiff = None
+
+        p = Personalization()
+        cc_email = Cc('test+to0@example.com', 'Example To Name 0')
+        p.add_cc(cc_email)
+        p.add_cc(cc_email)
+
+        expected = [cc_email.get()]
+
+        self.assertEqual(expected, p.ccs)
+
+    def test_dynamic_template_data(self):
+        self.maxDiff = None
+
+        to_emails = [
+            To(email='test+to+0@example.com',
+               name='Example To 0 Name',
+               dynamic_template_data=DynamicTemplateData({'name': 'Example 0 Name'})),
+            To(email='test+to+1@example.com',
+               name='Example To 1 Name',
+               dynamic_template_data={'name': 'Example 1 Name'})
+        ]
+        message = Mail(
+            from_email=From('test@example.com', 'Example From Name'),
+            to_emails=to_emails,
+            subject=Subject('Hi!'),
+            plain_text_content='Hello!',
+            html_content='<strong>Hello!</strong>',
+            is_multiple=True)
+
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "Hello!"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>Hello!</strong>"
+                    }
+                ],
+                "from": {
+                    "email": "test@example.com",
+                    "name": "Example From Name"
+                },
+                "personalizations": [
+                    {
+                        "dynamic_template_data": {
+                            "name": "Example 1 Name"
+                        },
+                        "to": [
+                            {
+                                "email": "test+to+1@example.com",
+                                "name": "Example To 1 Name"
+                            }
+                        ]
+                    },
+                    {
+                        "dynamic_template_data": {
+                            "name": "Example 0 Name"
+                        },
+                        "to": [
+                            {
+                                "email": "test+to+0@example.com",
+                                "name": "Example To 0 Name"
+                            }
+                        ]
+                    }
+                ],
+                "subject": "Hi!"
+            }''')
+        )
+
+    def test_kitchen_sink(self):
+        from sendgrid.helpers.mail import (
+            Mail, From, To, Cc, Bcc, Subject, Substitution, Header,
+            CustomArg, SendAt, Content, MimeType, Attachment, FileName,
+            FileContent, FileType, Disposition, ContentId, TemplateId,
+            Section, ReplyTo, Category, BatchId, Asm, GroupId, GroupsToDisplay,
+            IpPoolName, MailSettings, BccSettings, BccSettingsEmail,
+            BypassBounceManagement, BypassListManagement, BypassSpamManagement,
+            BypassUnsubscribeManagement, FooterSettings, FooterText,
+            FooterHtml, SandBoxMode, SpamCheck, SpamThreshold, SpamUrl,
+            TrackingSettings, ClickTracking, SubscriptionTracking,
+            SubscriptionText, SubscriptionHtml, SubscriptionSubstitutionTag,
+            OpenTracking, OpenTrackingSubstitutionTag, Ganalytics,
+            UtmSource, UtmMedium, UtmTerm, UtmContent, UtmCampaign)
+
+        self.maxDiff = None
+
+        message = Mail()
+
+        # Define Personalizations
+
+        message.to = To('test1@example.com', 'Example User1', p=0)
+        message.to = [
+            To('test2@example.com', 'Example User2', p=0),
+            To('test3@example.com', 'Example User3', p=0)
+        ]
+
+        message.cc = Cc('test4@example.com', 'Example User4', p=0)
+        message.cc = [
+            Cc('test5@example.com', 'Example User5', p=0),
+            Cc('test6@example.com', 'Example User6', p=0)
+        ]
+
+        message.bcc = Bcc('test7@example.com', 'Example User7', p=0)
+        message.bcc = [
+            Bcc('test8@example.com', 'Example User8', p=0),
+            Bcc('test9@example.com', 'Example User9', p=0)
+        ]
+
+        message.subject = Subject('Sending with SendGrid is Fun 0', p=0)
+
+        message.header = Header('X-Test1', 'Test1', p=0)
+        message.header = Header('X-Test2', 'Test2', p=0)
+        message.header = [
+            Header('X-Test3', 'Test3', p=0),
+            Header('X-Test4', 'Test4', p=0)
+        ]
+
+        message.substitution = Substitution('%name1%', 'Example Name 1', p=0)
+        message.substitution = Substitution('%city1%', 'Example City 1', p=0)
+        message.substitution = [
+            Substitution('%name2%', 'Example Name 2', p=0),
+            Substitution('%city2%', 'Example City 2', p=0)
+        ]
+
+        message.custom_arg = CustomArg('marketing1', 'true', p=0)
+        message.custom_arg = CustomArg('transactional1', 'false', p=0)
+        message.custom_arg = [
+            CustomArg('marketing2', 'false', p=0),
+            CustomArg('transactional2', 'true', p=0)
+        ]
+
+        message.send_at = SendAt(1461775051, p=0)
+
+        message.to = To('test10@example.com', 'Example User10', p=1)
+        message.to = [
+            To('test11@example.com', 'Example User11', p=1),
+            To('test12@example.com', 'Example User12', p=1)
+        ]
+
+        message.cc = Cc('test13@example.com', 'Example User13', p=1)
+        message.cc = [
+            Cc('test14@example.com', 'Example User14', p=1),
+            Cc('test15@example.com', 'Example User15', p=1)
+        ]
+
+        message.bcc = Bcc('test16@example.com', 'Example User16', p=1)
+        message.bcc = [
+            Bcc('test17@example.com', 'Example User17', p=1),
+            Bcc('test18@example.com', 'Example User18', p=1)
+        ]
+
+        message.header = Header('X-Test5', 'Test5', p=1)
+        message.header = Header('X-Test6', 'Test6', p=1)
+        message.header = [
+            Header('X-Test7', 'Test7', p=1),
+            Header('X-Test8', 'Test8', p=1)
+        ]
+
+        message.substitution = Substitution('%name3%', 'Example Name 3', p=1)
+        message.substitution = Substitution('%city3%', 'Example City 3', p=1)
+        message.substitution = [
+            Substitution('%name4%', 'Example Name 4', p=1),
+            Substitution('%city4%', 'Example City 4', p=1)
+        ]
+
+        message.custom_arg = CustomArg('marketing3', 'true', p=1)
+        message.custom_arg = CustomArg('transactional3', 'false', p=1)
+        message.custom_arg = [
+            CustomArg('marketing4', 'false', p=1),
+            CustomArg('transactional4', 'true', p=1)
+        ]
+
+        message.send_at = SendAt(1461775052, p=1)
+
+        message.subject = Subject('Sending with SendGrid is Fun 1', p=1)
+
+        # The values below this comment are global to entire message
+
+        message.from_email = From('help@twilio.com', 'Twilio SendGrid')
+
+        message.reply_to = ReplyTo('help_reply@twilio.com', 'Twilio SendGrid Reply')
+
+        message.subject = Subject('Sending with SendGrid is Fun 2')
+
+        message.content = Content(
+            MimeType.text,
+            'and easy to do anywhere, even with Python')
+        message.content = Content(
+            MimeType.html,
+            '<strong>and easy to do anywhere, even with Python</strong>')
+        message.content = [
+            Content('text/calendar', 'Party Time!!'),
+            Content('text/custom', 'Party Time 2!!')
+        ]
+
+        message.attachment = Attachment(
+            FileContent('base64 encoded content 1'),
+            FileName('balance_001.pdf'),
+            FileType('application/pdf'),
+            Disposition('attachment'),
+            ContentId('Content ID 1'))
+        message.attachment = [
+            Attachment(
+                FileContent('base64 encoded content 2'),
+                FileName('banner.png'),
+                FileType('image/png'),
+                Disposition('inline'),
+                ContentId('Content ID 2')),
+            Attachment(
+                FileContent('base64 encoded content 3'),
+                FileName('banner2.png'),
+                FileType('image/png'),
+                Disposition('inline'),
+                ContentId('Content ID 3'))
+        ]
+
+        message.template_id = TemplateId(
+            '13b8f94f-bcae-4ec6-b752-70d6cb59f932')
+
+        message.section = Section(
+            '%section1%', 'Substitution for Section 1 Tag')
+        message.section = [
+            Section('%section2%', 'Substitution for Section 2 Tag'),
+            Section('%section3%', 'Substitution for Section 3 Tag')
+        ]
+
+        message.header = Header('X-Test9', 'Test9')
+        message.header = Header('X-Test10', 'Test10')
+        message.header = [
+            Header('X-Test11', 'Test11'),
+            Header('X-Test12', 'Test12')
+        ]
+
+        message.category = Category('Category 1')
+        message.category = Category('Category 2')
+        message.category = [
+            Category('Category 1'),
+            Category('Category 2')
+        ]
+
+        message.custom_arg = CustomArg('marketing5', 'false')
+        message.custom_arg = CustomArg('transactional5', 'true')
+        message.custom_arg = [
+            CustomArg('marketing6', 'true'),
+            CustomArg('transactional6', 'false')
+        ]
+
+        message.send_at = SendAt(1461775053)
+
+        message.batch_id = BatchId("HkJ5yLYULb7Rj8GKSx7u025ouWVlMgAi")
+
+        message.asm = Asm(GroupId(1), GroupsToDisplay([1, 2, 3, 4]))
+
+        message.ip_pool_name = IpPoolName("IP Pool Name")
+
+        mail_settings = MailSettings()
+        mail_settings.bcc_settings = BccSettings(
+            False, BccSettingsEmail("bcc@twilio.com"))
+        mail_settings.bypass_bounce_management = BypassBounceManagement(False)
+        mail_settings.bypass_list_management = BypassListManagement(False)
+        mail_settings.bypass_spam_management = BypassSpamManagement(False)
+        mail_settings.bypass_unsubscribe_management = BypassUnsubscribeManagement(False)
+        mail_settings.footer_settings = FooterSettings(
+            True, FooterText("w00t"), FooterHtml("<string>w00t!<strong>"))
+        mail_settings.sandbox_mode = SandBoxMode(True)
+        mail_settings.spam_check = SpamCheck(
+            True, SpamThreshold(5), SpamUrl("https://example.com"))
+        message.mail_settings = mail_settings
+
+        tracking_settings = TrackingSettings()
+        tracking_settings.click_tracking = ClickTracking(True, False)
+        tracking_settings.open_tracking = OpenTracking(
+            True, OpenTrackingSubstitutionTag("open_tracking"))
+        tracking_settings.subscription_tracking = SubscriptionTracking(
+            True,
+            SubscriptionText("Goodbye"),
+            SubscriptionHtml("<strong>Goodbye!</strong>"),
+            SubscriptionSubstitutionTag("unsubscribe"))
+        tracking_settings.ganalytics = Ganalytics(
+            True,
+            UtmSource("utm_source"),
+            UtmMedium("utm_medium"),
+            UtmTerm("utm_term"),
+            UtmContent("utm_content"),
+            UtmCampaign("utm_campaign"))
+        message.tracking_settings = tracking_settings
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "asm": {
+                    "group_id": 1,
+                    "groups_to_display": [
+                        1,
+                        2,
+                        3,
+                        4
+                    ]
+                },
+                "attachments": [
+                    {
+                        "content": "base64 encoded content 3",
+                        "content_id": "Content ID 3",
+                        "disposition": "inline",
+                        "filename": "banner2.png",
+                        "type": "image/png"
+                    },
+                    {
+                        "content": "base64 encoded content 2",
+                        "content_id": "Content ID 2",
+                        "disposition": "inline",
+                        "filename": "banner.png",
+                        "type": "image/png"
+                    },
+                    {
+                        "content": "base64 encoded content 1",
+                        "content_id": "Content ID 1",
+                        "disposition": "attachment",
+                        "filename": "balance_001.pdf",
+                        "type": "application/pdf"
+                    }
+                ],
+                "batch_id": "HkJ5yLYULb7Rj8GKSx7u025ouWVlMgAi",
+                "categories": [
+                    "Category 2",
+                    "Category 1",
+                    "Category 2",
+                    "Category 1"
+                ],
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "and easy to do anywhere, even with Python"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>and easy to do anywhere, even with Python</strong>"
+                    },
+                    {
+                        "type": "text/calendar",
+                        "value": "Party Time!!"
+                    },
+                    {
+                        "type": "text/custom",
+                        "value": "Party Time 2!!"
+                    }
+                ],
+                "custom_args": {
+                    "marketing5": "false",
+                    "marketing6": "true",
+                    "transactional5": "true",
+                    "transactional6": "false"
+                },
+                "from": {
+                    "email": "help@twilio.com",
+                    "name": "Twilio SendGrid"
+                },
+                "headers": {
+                    "X-Test10": "Test10",
+                    "X-Test11": "Test11",
+                    "X-Test12": "Test12",
+                    "X-Test9": "Test9"
+                },
+                "ip_pool_name": "IP Pool Name",
+                "mail_settings": {
+                    "bcc": {
+                        "email": "bcc@twilio.com",
+                        "enable": false
+                    },
+                    "bypass_bounce_management": {
+                        "enable": false
+                    },
+                    "bypass_list_management": {
+                        "enable": false
+                    },
+                    "bypass_spam_management": {
+                        "enable": false
+                    },
+                    "bypass_unsubscribe_management": {
+                        "enable": false
+                    },
+                    "footer": {
+                        "enable": true,
+                        "html": "<string>w00t!<strong>",
+                        "text": "w00t"
+                    },
+                    "sandbox_mode": {
+                        "enable": true
+                    },
+                    "spam_check": {
+                        "enable": true,
+                        "post_to_url": "https://example.com",
+                        "threshold": 5
+                    }
+                },
+                "personalizations": [
+                    {
+                        "bcc": [
+                            {
+                                "email": "test7@example.com",
+                                "name": "Example User7"
+                            },
+                            {
+                                "email": "test8@example.com",
+                                "name": "Example User8"
+                            },
+                            {
+                                "email": "test9@example.com",
+                                "name": "Example User9"
+                            }
+                        ],
+                        "cc": [
+                            {
+                                "email": "test4@example.com",
+                                "name": "Example User4"
+                            },
+                            {
+                                "email": "test5@example.com",
+                                "name": "Example User5"
+                            },
+                            {
+                                "email": "test6@example.com",
+                                "name": "Example User6"
+                            }
+                        ],
+                        "custom_args": {
+                            "marketing1": "true",
+                            "marketing2": "false",
+                            "transactional1": "false",
+                            "transactional2": "true"
+                        },
+                        "headers": {
+                            "X-Test1": "Test1",
+                            "X-Test2": "Test2",
+                            "X-Test3": "Test3",
+                            "X-Test4": "Test4"
+                        },
+                        "send_at": 1461775051,
+                        "subject": "Sending with SendGrid is Fun 0",
+                        "substitutions": {
+                            "%city1%": "Example City 1",
+                            "%city2%": "Example City 2",
+                            "%name1%": "Example Name 1",
+                            "%name2%": "Example Name 2"
+                        },
+                        "to": [
+                            {
+                                "email": "test1@example.com",
+                                "name": "Example User1"
+                            },
+                            {
+                                "email": "test2@example.com",
+                                "name": "Example User2"
+                            },
+                            {
+                                "email": "test3@example.com",
+                                "name": "Example User3"
+                            }
+                        ]
+                    },
+                    {
+                        "bcc": [
+                            {
+                                "email": "test16@example.com",
+                                "name": "Example User16"
+                            },
+                            {
+                                "email": "test17@example.com",
+                                "name": "Example User17"
+                            },
+                            {
+                                "email": "test18@example.com",
+                                "name": "Example User18"
+                            }
+                        ],
+                        "cc": [
+                            {
+                                "email": "test13@example.com",
+                                "name": "Example User13"
+                            },
+                            {
+                                "email": "test14@example.com",
+                                "name": "Example User14"
+                            },
+                            {
+                                "email": "test15@example.com",
+                                "name": "Example User15"
+                            }
+                        ],
+                        "custom_args": {
+                            "marketing3": "true",
+                            "marketing4": "false",
+                            "transactional3": "false",
+                            "transactional4": "true"
+                        },
+                        "headers": {
+                            "X-Test5": "Test5",
+                            "X-Test6": "Test6",
+                            "X-Test7": "Test7",
+                            "X-Test8": "Test8"
+                        },
+                        "send_at": 1461775052,
+                        "subject": "Sending with SendGrid is Fun 1",
+                        "substitutions": {
+                            "%city3%": "Example City 3",
+                            "%city4%": "Example City 4",
+                            "%name3%": "Example Name 3",
+                            "%name4%": "Example Name 4"
+                        },
+                        "to": [
+                            {
+                                "email": "test10@example.com",
+                                "name": "Example User10"
+                            },
+                            {
+                                "email": "test11@example.com",
+                                "name": "Example User11"
+                            },
+                            {
+                                "email": "test12@example.com",
+                                "name": "Example User12"
+                            }
+                        ]
+                    }
+                ],
+                "reply_to": {
+                    "email": "help_reply@twilio.com",
+                    "name": "Twilio SendGrid Reply"
+                },
+                "sections": {
+                    "%section1%": "Substitution for Section 1 Tag",
+                    "%section2%": "Substitution for Section 2 Tag",
+                    "%section3%": "Substitution for Section 3 Tag"
+                },
+                "send_at": 1461775053,
+                "subject": "Sending with SendGrid is Fun 2",
+                "template_id": "13b8f94f-bcae-4ec6-b752-70d6cb59f932",
+                "tracking_settings": {
+                    "click_tracking": {
+                        "enable": true,
+                        "enable_text": false
+                    },
+                    "ganalytics": {
+                        "enable": true,
+                        "utm_campaign": "utm_campaign",
+                        "utm_content": "utm_content",
+                        "utm_medium": "utm_medium",
+                        "utm_source": "utm_source",
+                        "utm_term": "utm_term"
+                    },
+                    "open_tracking": {
+                        "enable": true,
+                        "substitution_tag": "open_tracking"
+                    },
+                    "subscription_tracking": {
+                        "enable": true,
+                        "html": "<strong>Goodbye!</strong>",
+                        "substitution_tag": "unsubscribe",
+                        "text": "Goodbye"
+                    }
+                }
+            }''')
+        )
+
+    # Send a Single Email to a Single Recipient with a Dynamic Template
+    def test_single_email_to_a_single_recipient_with_dynamic_templates(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+        message.dynamic_template_data = DynamicTemplateData({
+            "total": "$ 239.85",
+            "items": [
+                {
+                    "text": "New Line Sneakers",
+                    "image": "https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png",
+                    "price": "$ 79.95"
+                },
+                {
+                    "text": "Old Line Sneakers",
+                    "image": "https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png",
+                    "price": "$ 79.95"
+                },
+                {
+                    "text": "Blue Line Sneakers",
+                    "image": "https://marketing-image-production.s3.amazonaws.com/uploads/00731ed18eff0ad5da890d876c456c3124a4e44cb48196533e9b95fb2b959b7194c2dc7637b788341d1ff4f88d1dc88e23f7e3704726d313c57f350911dd2bd0.png",
+                    "price": "$ 79.95"
+                }
+            ],
+            "receipt": True,
+            "name": "Sample Name",
+            "address01": "1234 Fake St.",
+            "address02": "Apt. 123",
+            "city": "Place",
+            "state": "CO",
+            "zip": "80202"
+        })
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "and easy to do anywhere, even with Python"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>and easy to do anywhere, even with Python</strong>"
+                    }
+                ],
+                "from": {
+                    "email": "test+from@example.com",
+                    "name": "Example From Name"
+                },
+                "personalizations": [
+                    {
+                        "dynamic_template_data": {
+                            "address01": "1234 Fake St.",
+                            "address02": "Apt. 123",
+                            "city": "Place",
+                            "items": [
+                                {
+                                    "image": "https://marketing-image-production.s3.amazonaws.com/uploads/8dda1131320a6d978b515cc04ed479df259a458d5d45d58b6b381cae0bf9588113e80ef912f69e8c4cc1ef1a0297e8eefdb7b270064cc046b79a44e21b811802.png",
+                                    "price": "$ 79.95",
+                                    "text": "New Line Sneakers"
+                                },
+                                {
+                                    "image": "https://marketing-image-production.s3.amazonaws.com/uploads/3629f54390ead663d4eb7c53702e492de63299d7c5f7239efdc693b09b9b28c82c924225dcd8dcb65732d5ca7b7b753c5f17e056405bbd4596e4e63a96ae5018.png",
+                                    "price": "$ 79.95",
+                                    "text": "Old Line Sneakers"
+                                },
+                                {
+                                    "image": "https://marketing-image-production.s3.amazonaws.com/uploads/00731ed18eff0ad5da890d876c456c3124a4e44cb48196533e9b95fb2b959b7194c2dc7637b788341d1ff4f88d1dc88e23f7e3704726d313c57f350911dd2bd0.png",
+                                    "price": "$ 79.95",
+                                    "text": "Blue Line Sneakers"
+                                }
+                            ],
+                            "name": "Sample Name",
+                            "receipt": true,
+                            "state": "CO",
+                            "total": "$ 239.85",
+                            "zip": "80202"
+                        },
+                        "to": [
+                            {
+                                "email": "test+to@example.com",
+                                "name": "Example To Name"
+                            }
+                        ]
+                    }
+                ],
+                "subject": "Sending with SendGrid is Fun"
+            }''')
+        )
+
+    def test_sendgrid_api_key(self):
+        """Tests if including SendGrid API will throw an Exception"""
+
+        # Minimum required to send an email
+        self.max_diff = None
+        mail = Mail()
+
+        mail.from_email = Email("test@example.com")
+
+        mail.subject = "Hello World from the SendGrid Python Library"
+
+        personalization = Personalization()
+        personalization.add_to(Email("test@example.com"))
+        mail.add_personalization(personalization)
+
+        # Try to include SendGrid API key
+        try:
+            mail.add_content(
+                Content(
+                    "text/plain",
+                    "some SG.2123b1B.1212lBaC here"))
+            mail.add_content(
+                Content(
+                    "text/html",
+                    "<html><body>some SG.Ba2BlJSDba.232Ln2 here</body></html>"))
+
+            self.assertEqual(
+                json.dumps(
+                    mail.get(),
+                    sort_keys=True),
+                '{"content": [{"type": "text/plain", "value": "some text here"}, '
+                '{"type": "text/html", '
+                '"value": "<html><body>some text here</body></html>"}], '
+                '"from": {"email": "test@example.com"}, "personalizations": '
+                '[{"to": [{"email": "test@example.com"}]}], '
+                '"subject": "Hello World from the SendGrid Python Library"}'
+            )
+
+        # Exception should be thrown
+        except Exception:
+            pass
+
+        # Exception not thrown
+        else:
+            self.fail("Should have failed as SendGrid API key included")
+
+    def test_unicode_values_in_substitutions_helper(self):
+        from sendgrid.helpers.mail import (Mail, From, To, Subject,
+                                           PlainTextContent, HtmlContent)
+        self.maxDiff = None
+        message = Mail(
+            from_email=From('test+from@example.com', 'Example From Name'),
+            to_emails=To('test+to@example.com', 'Example To Name'),
+            subject=Subject('Sending with SendGrid is Fun'),
+            plain_text_content=PlainTextContent(
+                'and easy to do anywhere, even with Python'),
+            html_content=HtmlContent(
+                '<strong>and easy to do anywhere, even with Python</strong>'))
+        message.substitution = Substitution('%city%', u'Αθήνα', p=1)
+        self.assertEqual(
+            message.get(),
+            json.loads(r'''{
+                "content": [
+                    {
+                        "type": "text/plain",
+                        "value": "and easy to do anywhere, even with Python"
+                    },
+                    {
+                        "type": "text/html",
+                        "value": "<strong>and easy to do anywhere, even with Python</strong>"
+                    }
+                ],
+                "from": {
+                    "email": "test+from@example.com",
+                    "name": "Example From Name"
+                },
+                "personalizations": [
+                    {
+                        "to": [
+                            {
+                                "email": "test+to@example.com",
+                                "name": "Example To Name"
+                            }
+                        ]
+                    },
+                    {
+                        "substitutions": {
+                            "%city%": "Αθήνα"
+                        }
+                    }
+                ],
+                "subject": "Sending with SendGrid is Fun"
+            }''')
+        )
+
+    def test_asm_display_group_limit(self):
+        self.assertRaises(ValueError, Asm, 1, list(range(26)))
+
+    def test_disable_tracking(self):
+        tracking_settings = TrackingSettings()
+        tracking_settings.click_tracking = ClickTracking(False, False)
+
+        self.assertEqual(
+            tracking_settings.get(),
+            {'click_tracking': {'enable': False, 'enable_text': False}}
+        )
+
+    def test_bypass_list_management(self):
+        from sendgrid.helpers.mail import (MailSettings, BypassListManagement)
+        mail_settings = MailSettings()
+        mail_settings.bypass_list_management = BypassListManagement(True)
+
+        self.assertEqual(
+            mail_settings.get(),
+            {
+                "bypass_list_management": {
+                    "enable": True
+                },
+            },
+        )
+
+    def test_v3_bypass_filters(self):
+        from sendgrid.helpers.mail import (
+            MailSettings, BypassBounceManagement,
+            BypassSpamManagement, BypassUnsubscribeManagement
+        )
+        mail_settings = MailSettings()
+        mail_settings.bypass_bounce_management = BypassBounceManagement(True)
+        mail_settings.bypass_spam_management = BypassSpamManagement(True)
+        mail_settings.bypass_unsubscribe_management = BypassUnsubscribeManagement(True)
+
+        self.assertEqual(
+            mail_settings.get(),
+            {
+                "bypass_bounce_management": {
+                    "enable": True
+                },
+                "bypass_spam_management": {
+                    "enable": True
+                },
+                "bypass_unsubscribe_management": {
+                    "enable": True
+                },
+            },
+        )
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_parse.py b/.venv/lib/python3.12/site-packages/test/unit/test_parse.py
new file mode 100644
index 00000000..1c899bbb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_parse.py
@@ -0,0 +1,16 @@
+import unittest
+
+from sendgrid.helpers.inbound.config import Config
+from sendgrid.helpers.inbound.app import app
+
+
+class UnitTests(unittest.TestCase):
+
+    def setUp(self):
+        self.config = Config()
+        self.tester = app.test_client(self)
+
+    def test_parse(self):
+        response = self.tester.post(self.config.endpoint,
+                                    data='{"Message:", "Success"}')
+        self.assertEqual(response.status_code, 200)
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_project.py b/.venv/lib/python3.12/site-packages/test/unit/test_project.py
new file mode 100644
index 00000000..40282bdb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_project.py
@@ -0,0 +1,52 @@
+import os
+import unittest
+
+
+class ProjectTests(unittest.TestCase):
+    # ./.env_sample
+    def test_env(self):
+        self.assertTrue(os.path.isfile('./.env_sample'))
+
+    # ./.gitignore
+    def test_gitignore(self):
+        self.assertTrue(os.path.isfile('./.gitignore'))
+
+    # ./CHANGELOG.md
+    def test_changelog(self):
+        self.assertTrue(os.path.isfile('./CHANGELOG.md'))
+
+    # ./CODE_OF_CONDUCT.md
+    def test_code_of_conduct(self):
+        self.assertTrue(os.path.isfile('./CODE_OF_CONDUCT.md'))
+
+    # ./CONTRIBUTING.md
+    def test_contributing(self):
+        self.assertTrue(os.path.isfile('./CONTRIBUTING.md'))
+
+    # ./LICENSE
+    def test_license(self):
+        self.assertTrue(os.path.isfile('./LICENSE'))
+
+    # ./PULL_REQUEST_TEMPLATE.md
+    def test_pr_template(self):
+        self.assertTrue(os.path.isfile('./PULL_REQUEST_TEMPLATE.md'))
+
+    # ./README.rst
+    def test_readme(self):
+        self.assertTrue(os.path.isfile('./README.rst'))
+
+    # ./TROUBLESHOOTING.md
+    def test_troubleshooting(self):
+        self.assertTrue(os.path.isfile('./TROUBLESHOOTING.md'))
+
+    # ./USAGE.md
+    def test_usage(self):
+        self.assertTrue(os.path.isfile('./USAGE.md'))
+
+    # ./use-cases/README.md
+    def test_use_cases(self):
+        self.assertTrue(os.path.isfile('./use_cases/README.md'))
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_sendgrid.py b/.venv/lib/python3.12/site-packages/test/unit/test_sendgrid.py
new file mode 100644
index 00000000..328d978a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_sendgrid.py
@@ -0,0 +1,27 @@
+import unittest
+import sendgrid
+
+class UnitTests(unittest.TestCase):
+    def test_host_with_no_region(self):
+        sg = sendgrid.SendGridAPIClient(api_key='MY_API_KEY')
+        self.assertEqual("https://api.sendgrid.com",sg.client.host)
+
+    def test_host_with_eu_region(self):
+        sg = sendgrid.SendGridAPIClient(api_key='MY_API_KEY')
+        sg.set_sendgrid_data_residency("eu")
+        self.assertEqual("https://api.eu.sendgrid.com",sg.client.host)
+
+    def test_host_with_global_region(self):
+        sg = sendgrid.SendGridAPIClient(api_key='MY_API_KEY')
+        sg.set_sendgrid_data_residency("global")
+        self.assertEqual("https://api.sendgrid.com",sg.client.host)
+
+    def test_with_region_is_none(self):
+        sg = sendgrid.SendGridAPIClient(api_key='MY_API_KEY')
+        with self.assertRaises(ValueError):
+            sg.set_sendgrid_data_residency(None)
+
+    def test_with_region_is_invalid(self):
+        sg = sendgrid.SendGridAPIClient(api_key='MY_API_KEY')
+        with self.assertRaises(ValueError):
+            sg.set_sendgrid_data_residency("abc")
\ No newline at end of file
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_spam_check.py b/.venv/lib/python3.12/site-packages/test/unit/test_spam_check.py
new file mode 100644
index 00000000..e532573b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_spam_check.py
@@ -0,0 +1,38 @@
+from sendgrid.helpers.mail.spam_check import SpamCheck
+
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
+
+class UnitTests(unittest.TestCase):
+
+    def test_spam_all_values(self):
+        expected = {'enable': True, 'threshold': 5, 'post_to_url': 'https://www.test.com'}
+        spam_check = SpamCheck(enable=True, threshold=5, post_to_url='https://www.test.com')
+        self.assertEqual(spam_check.get(), expected)
+
+    def test_spam_no_url(self):
+        expected = {'enable': True, 'threshold': 10}
+        spam_check = SpamCheck(enable=True, threshold=10)
+        self.assertEqual(spam_check.get(), expected)
+
+    def test_spam_no_threshold(self):
+        expected = {'enable': True}
+        spam_check = SpamCheck(enable=True)
+        self.assertEqual(spam_check.get(), expected)
+
+    def test_has_values_but_not_enabled(self):
+        expected = {'enable': False, 'threshold': 1, 'post_to_url': 'https://www.test.com'}
+        spam_check = SpamCheck(enable=False, threshold=1, post_to_url='https://www.test.com')
+        self.assertEqual(spam_check.get(), expected)
+
+    def test_spam_change_properties(self):
+        """Tests changing the properties of the spam check class"""
+        expected = {'enable': False, 'threshold': 10, 'post_to_url': 'https://www.testing.com'}
+        spam_check = SpamCheck(enable=True, threshold=5, post_to_url='https://www.test.com')
+        spam_check.enable = False
+        spam_check.threshold = 10
+        spam_check.post_to_url = 'https://www.testing.com'
+        self.assertEqual(spam_check.get(), expected)
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_stats.py b/.venv/lib/python3.12/site-packages/test/unit/test_stats.py
new file mode 100644
index 00000000..c7111739
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_stats.py
@@ -0,0 +1,86 @@
+# -*- coding: utf-8 -*-
+import json
+from sendgrid.helpers.stats import *
+
+try:
+    import unittest2 as unittest
+except ImportError:
+    import unittest
+
+
+class UnitTests(unittest.TestCase):
+
+    def test_basicStats(self):
+
+        """Minimum required for stats"""
+        global_stats = Stats(start_date='12-09-2017')
+
+        self.assertEqual(
+            json.dumps(
+                global_stats.get(),
+                sort_keys=True),
+            '{"start_date": "12-09-2017"}'
+        )
+
+        self.assertTrue(isinstance(str(global_stats), str))
+
+    def test_Stats(self):
+
+        all_stats = Stats(start_date='12-09-2017')
+        all_stats.end_date = '12-10-2017'
+        all_stats.aggregated_by = 'day'
+        all_stats._sort_by_direction = 'asc'
+        all_stats.sort_by_metric = 'clicks'
+        all_stats._limit = 100
+        all_stats._offset = 2
+
+        self.assertEqual(
+            json.dumps(
+                all_stats.get(),
+                sort_keys=True),
+            '{"aggregated_by": "day", "end_date": "12-10-2017", '
+            '"limit": 100, "offset": 2, "sort_by_direction": "asc", '
+            '"sort_by_metric": "clicks", "start_date": "12-09-2017"}'
+        )
+
+    def test_categoryStats(self):
+
+        category_stats = CategoryStats(start_date='12-09-2017', categories=['foo', 'bar'])
+        category_stats.add_category(Category('woo'))
+        category_stats.end_date = '12-10-2017'
+        category_stats.aggregated_by = 'day'
+        category_stats._sort_by_direction = 'asc'
+        category_stats.sort_by_metric = 'clicks'
+        category_stats._limit = 100
+        category_stats._offset = 2
+
+        self.assertEqual(
+            json.dumps(
+                category_stats.get(),
+                sort_keys=True),
+            '{"aggregated_by": "day", "categories": ["foo", "bar", "woo"], '
+            '"end_date": "12-10-2017", "limit": 100, "offset": 2, '
+            '"sort_by_direction": "asc", "sort_by_metric": "clicks", '
+            '"start_date": "12-09-2017"}'
+        )
+
+    def test_subuserStats(self):
+
+        subuser_stats = SubuserStats(start_date = '12-09-2017', subusers=['foo', 'bar'])
+        subuser_stats.add_subuser(Subuser('blah'))
+        subuser_stats.end_date = '12-10-2017'
+        subuser_stats.aggregated_by = 'day'
+        subuser_stats._sort_by_direction = 'asc'
+        subuser_stats.sort_by_metric = 'clicks'
+        subuser_stats._limit = 100
+        subuser_stats._offset = 2
+
+        self.assertEqual(
+            json.dumps(
+                subuser_stats.get(),
+                sort_keys=True),
+            '{"aggregated_by": "day", "end_date": "12-10-2017", '
+            '"limit": 100, "offset": 2, "sort_by_direction": "asc", '
+            '"sort_by_metric": "clicks", "start_date": "12-09-2017", '
+            '"subusers": ["foo", "bar", "blah"]}'
+        )
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_twilio_email.py b/.venv/lib/python3.12/site-packages/test/unit/test_twilio_email.py
new file mode 100644
index 00000000..92269acf
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_twilio_email.py
@@ -0,0 +1,37 @@
+import os
+import unittest
+
+from sendgrid import TwilioEmailAPIClient
+
+
+class UnitTests(unittest.TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        os.environ['TWILIO_API_KEY'] = 'api-key'
+        os.environ['TWILIO_API_SECRET'] = 'api-secret'
+        os.environ['TWILIO_ACCOUNT_SID'] = 'account-sid'
+        os.environ['TWILIO_AUTH_TOKEN'] = 'auth-token'
+
+    def test_init_key_over_token(self):
+        mail_client = TwilioEmailAPIClient()
+
+        self.assertEqual(mail_client.username, 'api-key')
+        self.assertEqual(mail_client.password, 'api-secret')
+        self.assertEqual(mail_client.host, 'https://email.twilio.com')
+
+    def test_init_token(self):
+        del os.environ['TWILIO_API_KEY']
+        del os.environ['TWILIO_API_SECRET']
+
+        mail_client = TwilioEmailAPIClient()
+
+        self.assertEqual(mail_client.username, 'account-sid')
+        self.assertEqual(mail_client.password, 'auth-token')
+
+    def test_init_args(self):
+        mail_client = TwilioEmailAPIClient('username', 'password')
+
+        self.assertEqual(mail_client.username, 'username')
+        self.assertEqual(mail_client.password, 'password')
+        self.assertEqual(mail_client.auth, 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=')
diff --git a/.venv/lib/python3.12/site-packages/test/unit/test_unassigned.py b/.venv/lib/python3.12/site-packages/test/unit/test_unassigned.py
new file mode 100644
index 00000000..08ab943b
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/test/unit/test_unassigned.py
@@ -0,0 +1,93 @@
+import json
+
+from sendgrid.helpers.endpoints.ip.unassigned import unassigned
+
+ret_json = '''[ {
+	"ip": "167.89.21.3",
+        "pools": [
+		"pool1",
+	"pool2"
+	],
+        "whitelabeled": false,
+        "start_date": 1409616000,
+        "subusers": [
+          "tim@sendgrid.net"
+        ],
+        "warmup": false,
+        "assigned_at": 1482883200
+      },
+      {
+        "ip": "192.168.1.1",
+        "pools": [
+          "pool1",
+          "pool2"
+        ],
+        "whitelabeled": false,
+        "start_date": 1409616000,
+        "subusers": [
+          "tim@sendgrid.net"
+        ],
+        "warmup": false,
+        "assigned_at": 1482883200
+      },
+      {
+        "ip": "208.115.214.22",
+        "pools": [],
+        "whitelabeled": true,
+        "rdns": "o1.email.burgermail.com",
+        "start_date": 1409616000,
+        "subusers": [],
+        "warmup": false,
+        "assigned_at": 1482883200
+      },
+      {
+        "ip": "208.115.214.23",
+        "pools": [],
+        "whitelabeled": true,
+        "rdns": "o1.email.burgermail.com",
+        "start_date": 1409616000,
+        "subusers": [],
+        "warmup": false,
+        "assigned_at": 1482883200
+
+      } ]
+      '''
+
+
+def get_all_ip():
+    ret_val = json.loads(ret_json)
+    return ret_val
+
+
+def make_data():
+    data = set()
+    data.add("208.115.214.23")
+    data.add("208.115.214.22")
+    return data
+
+
+def test_unassigned_ip_json():
+    data = make_data()
+
+    as_json = True
+    calculated = unassigned(get_all_ip(), as_json=as_json)
+    calculated = json.loads(calculated)
+
+    for item in calculated:
+        assert item["ip"] in data
+
+
+def test_unassigned_ip_obj():
+    data = make_data()
+
+    as_json = False
+    calculated = unassigned(get_all_ip(), as_json=as_json)
+
+    for item in calculated:
+        assert item["ip"] in data
+
+
+def test_unassigned_baddata():
+    as_json = False
+    calculated = unassigned(dict(), as_json=as_json)
+    assert calculated == []