chub-dev 0.1.0 → 0.1.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (139) hide show
  1. package/README.md +55 -0
  2. package/bin/chub-mcp +2 -0
  3. package/dist/airtable/docs/database/javascript/DOC.md +1437 -0
  4. package/dist/airtable/docs/database/python/DOC.md +1735 -0
  5. package/dist/amplitude/docs/analytics/javascript/DOC.md +1282 -0
  6. package/dist/amplitude/docs/analytics/python/DOC.md +1199 -0
  7. package/dist/anthropic/docs/claude-api/javascript/DOC.md +503 -0
  8. package/dist/anthropic/docs/claude-api/python/DOC.md +389 -0
  9. package/dist/asana/docs/tasks/DOC.md +1396 -0
  10. package/dist/assemblyai/docs/transcription/DOC.md +1043 -0
  11. package/dist/atlassian/docs/confluence/javascript/DOC.md +1347 -0
  12. package/dist/atlassian/docs/confluence/python/DOC.md +1604 -0
  13. package/dist/auth0/docs/identity/javascript/DOC.md +968 -0
  14. package/dist/auth0/docs/identity/python/DOC.md +1199 -0
  15. package/dist/aws/docs/s3/javascript/DOC.md +1773 -0
  16. package/dist/aws/docs/s3/python/DOC.md +1807 -0
  17. package/dist/binance/docs/trading/javascript/DOC.md +1315 -0
  18. package/dist/binance/docs/trading/python/DOC.md +1454 -0
  19. package/dist/braintree/docs/gateway/javascript/DOC.md +1278 -0
  20. package/dist/braintree/docs/gateway/python/DOC.md +1179 -0
  21. package/dist/chromadb/docs/embeddings-db/javascript/DOC.md +1263 -0
  22. package/dist/chromadb/docs/embeddings-db/python/DOC.md +1707 -0
  23. package/dist/clerk/docs/auth/javascript/DOC.md +1220 -0
  24. package/dist/clerk/docs/auth/python/DOC.md +274 -0
  25. package/dist/cloudflare/docs/workers/javascript/DOC.md +918 -0
  26. package/dist/cloudflare/docs/workers/python/DOC.md +994 -0
  27. package/dist/cockroachdb/docs/distributed-db/DOC.md +1500 -0
  28. package/dist/cohere/docs/llm/DOC.md +1335 -0
  29. package/dist/datadog/docs/monitoring/javascript/DOC.md +1740 -0
  30. package/dist/datadog/docs/monitoring/python/DOC.md +1815 -0
  31. package/dist/deepgram/docs/speech/javascript/DOC.md +885 -0
  32. package/dist/deepgram/docs/speech/python/DOC.md +685 -0
  33. package/dist/deepl/docs/translation/javascript/DOC.md +887 -0
  34. package/dist/deepl/docs/translation/python/DOC.md +944 -0
  35. package/dist/deepseek/docs/llm/DOC.md +1220 -0
  36. package/dist/directus/docs/headless-cms/javascript/DOC.md +1128 -0
  37. package/dist/directus/docs/headless-cms/python/DOC.md +1276 -0
  38. package/dist/discord/docs/bot/javascript/DOC.md +1090 -0
  39. package/dist/discord/docs/bot/python/DOC.md +1130 -0
  40. package/dist/elasticsearch/docs/search/DOC.md +1634 -0
  41. package/dist/elevenlabs/docs/text-to-speech/javascript/DOC.md +336 -0
  42. package/dist/elevenlabs/docs/text-to-speech/python/DOC.md +552 -0
  43. package/dist/firebase/docs/auth/DOC.md +1015 -0
  44. package/dist/gemini/docs/genai/javascript/DOC.md +691 -0
  45. package/dist/gemini/docs/genai/python/DOC.md +555 -0
  46. package/dist/github/docs/octokit/DOC.md +1560 -0
  47. package/dist/google/docs/bigquery/javascript/DOC.md +1688 -0
  48. package/dist/google/docs/bigquery/python/DOC.md +1503 -0
  49. package/dist/hubspot/docs/crm/javascript/DOC.md +1805 -0
  50. package/dist/hubspot/docs/crm/python/DOC.md +2033 -0
  51. package/dist/huggingface/docs/transformers/DOC.md +948 -0
  52. package/dist/intercom/docs/messaging/javascript/DOC.md +1844 -0
  53. package/dist/intercom/docs/messaging/python/DOC.md +1797 -0
  54. package/dist/jira/docs/issues/javascript/DOC.md +1420 -0
  55. package/dist/jira/docs/issues/python/DOC.md +1492 -0
  56. package/dist/kafka/docs/streaming/javascript/DOC.md +1671 -0
  57. package/dist/kafka/docs/streaming/python/DOC.md +1464 -0
  58. package/dist/landingai-ade/docs/api/DOC.md +620 -0
  59. package/dist/landingai-ade/docs/sdk/python/DOC.md +489 -0
  60. package/dist/landingai-ade/docs/sdk/typescript/DOC.md +542 -0
  61. package/dist/landingai-ade/skills/SKILL.md +489 -0
  62. package/dist/launchdarkly/docs/feature-flags/javascript/DOC.md +1191 -0
  63. package/dist/launchdarkly/docs/feature-flags/python/DOC.md +1671 -0
  64. package/dist/linear/docs/tracker/DOC.md +1554 -0
  65. package/dist/livekit/docs/realtime/javascript/DOC.md +303 -0
  66. package/dist/livekit/docs/realtime/python/DOC.md +163 -0
  67. package/dist/mailchimp/docs/marketing/DOC.md +1420 -0
  68. package/dist/meilisearch/docs/search/DOC.md +1241 -0
  69. package/dist/microsoft/docs/onedrive/javascript/DOC.md +1421 -0
  70. package/dist/microsoft/docs/onedrive/python/DOC.md +1549 -0
  71. package/dist/mongodb/docs/atlas/DOC.md +2041 -0
  72. package/dist/notion/docs/workspace-api/javascript/DOC.md +1435 -0
  73. package/dist/notion/docs/workspace-api/python/DOC.md +1400 -0
  74. package/dist/okta/docs/identity/javascript/DOC.md +1171 -0
  75. package/dist/okta/docs/identity/python/DOC.md +1401 -0
  76. package/dist/openai/docs/chat/javascript/DOC.md +407 -0
  77. package/dist/openai/docs/chat/python/DOC.md +568 -0
  78. package/dist/paypal/docs/checkout/DOC.md +278 -0
  79. package/dist/pinecone/docs/sdk/javascript/DOC.md +984 -0
  80. package/dist/pinecone/docs/sdk/python/DOC.md +1395 -0
  81. package/dist/plaid/docs/banking/javascript/DOC.md +1163 -0
  82. package/dist/plaid/docs/banking/python/DOC.md +1203 -0
  83. package/dist/playwright-community/skills/login-flows/SKILL.md +108 -0
  84. package/dist/postmark/docs/transactional-email/DOC.md +1168 -0
  85. package/dist/prisma/docs/orm/javascript/DOC.md +1419 -0
  86. package/dist/prisma/docs/orm/python/DOC.md +1317 -0
  87. package/dist/qdrant/docs/vector-search/javascript/DOC.md +1221 -0
  88. package/dist/qdrant/docs/vector-search/python/DOC.md +1653 -0
  89. package/dist/rabbitmq/docs/message-queue/javascript/DOC.md +1193 -0
  90. package/dist/rabbitmq/docs/message-queue/python/DOC.md +1243 -0
  91. package/dist/razorpay/docs/payments/javascript/DOC.md +1219 -0
  92. package/dist/razorpay/docs/payments/python/DOC.md +1330 -0
  93. package/dist/redis/docs/key-value/javascript/DOC.md +1851 -0
  94. package/dist/redis/docs/key-value/python/DOC.md +2054 -0
  95. package/dist/registry.json +2817 -0
  96. package/dist/replicate/docs/model-hosting/DOC.md +1318 -0
  97. package/dist/resend/docs/email/DOC.md +1271 -0
  98. package/dist/salesforce/docs/crm/javascript/DOC.md +1241 -0
  99. package/dist/salesforce/docs/crm/python/DOC.md +1183 -0
  100. package/dist/search-index.json +1 -0
  101. package/dist/sendgrid/docs/email-api/javascript/DOC.md +371 -0
  102. package/dist/sendgrid/docs/email-api/python/DOC.md +656 -0
  103. package/dist/sentry/docs/error-tracking/javascript/DOC.md +1073 -0
  104. package/dist/sentry/docs/error-tracking/python/DOC.md +1309 -0
  105. package/dist/shopify/docs/storefront/DOC.md +457 -0
  106. package/dist/slack/docs/workspace/javascript/DOC.md +933 -0
  107. package/dist/slack/docs/workspace/python/DOC.md +271 -0
  108. package/dist/square/docs/payments/javascript/DOC.md +1855 -0
  109. package/dist/square/docs/payments/python/DOC.md +1728 -0
  110. package/dist/stripe/docs/api/DOC.md +1727 -0
  111. package/dist/stripe/docs/payments/DOC.md +1726 -0
  112. package/dist/stytch/docs/auth/javascript/DOC.md +1813 -0
  113. package/dist/stytch/docs/auth/python/DOC.md +1962 -0
  114. package/dist/supabase/docs/client/DOC.md +1606 -0
  115. package/dist/twilio/docs/messaging/python/DOC.md +469 -0
  116. package/dist/twilio/docs/messaging/typescript/DOC.md +946 -0
  117. package/dist/vercel/docs/platform/DOC.md +1940 -0
  118. package/dist/weaviate/docs/vector-db/javascript/DOC.md +1268 -0
  119. package/dist/weaviate/docs/vector-db/python/DOC.md +1388 -0
  120. package/dist/zendesk/docs/support/javascript/DOC.md +2150 -0
  121. package/dist/zendesk/docs/support/python/DOC.md +2297 -0
  122. package/package.json +22 -6
  123. package/skills/get-api-docs/SKILL.md +84 -0
  124. package/src/commands/annotate.js +83 -0
  125. package/src/commands/build.js +12 -1
  126. package/src/commands/feedback.js +150 -0
  127. package/src/commands/get.js +83 -42
  128. package/src/commands/search.js +7 -0
  129. package/src/index.js +43 -17
  130. package/src/lib/analytics.js +90 -0
  131. package/src/lib/annotations.js +57 -0
  132. package/src/lib/bm25.js +170 -0
  133. package/src/lib/cache.js +69 -6
  134. package/src/lib/config.js +8 -3
  135. package/src/lib/identity.js +99 -0
  136. package/src/lib/registry.js +103 -20
  137. package/src/lib/telemetry.js +86 -0
  138. package/src/mcp/server.js +177 -0
  139. package/src/mcp/tools.js +251 -0
@@ -0,0 +1,656 @@
1
+ ---
2
+ name: email-api
3
+ description: "SendGrid Python SDK for sending emails and managing email communications via the SendGrid API."
4
+ metadata:
5
+ languages: "python"
6
+ versions: "6.12.5"
7
+ updated-on: "2026-03-01"
8
+ source: maintainer
9
+ tags: "sendgrid,email,transactional,templates,delivery"
10
+ ---
11
+
12
+ # SendGrid API Coding Guidelines (Python)
13
+
14
+ You are a SendGrid API coding expert. Help me with writing code using the SendGrid Python SDK for sending emails and managing email communications.
15
+
16
+ Please follow the following guidelines when generating code.
17
+
18
+ You can find the official SDK documentation and code samples here:
19
+ https://sendgrid.com/docs/
20
+
21
+ ## Golden Rule: Use the Correct and Current SDK
22
+
23
+ Always use the official SendGrid Python SDK to send emails and interact with SendGrid's Web API v3.
24
+
25
+ - **Library Name:** SendGrid Python SDK
26
+ - **Python Package:** `sendgrid`
27
+ - **GitHub Repository:** sendgrid/sendgrid-python
28
+
29
+ **Installation:**
30
+
31
+ - **Correct:** `pip install sendgrid`
32
+
33
+ **APIs and Usage:**
34
+
35
+ - **Correct:** `from sendgrid import SendGridAPIClient`
36
+ - **Correct:** `from sendgrid.helpers.mail import Mail`
37
+ - **Correct:** `sg = SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY'))`
38
+
39
+ ## Initialization and API Key
40
+
41
+ The SendGrid Python library requires creating a client object for all API calls.
42
+
43
+ - Always use `SendGridAPIClient()` to create a client object.
44
+ - Set `SENDGRID_API_KEY` environment variable, which will be picked up automatically.
45
+ - API key can also be passed directly to the constructor.
46
+
47
+ ## Environment Setup
48
+
49
+ ### Setting API Key Environment Variable
50
+
51
+ **Mac/Linux:**
52
+ ```bash
53
+ export SENDGRID_API_KEY='YOUR_API_KEY'
54
+ # Or create a .env file
55
+ echo "SENDGRID_API_KEY='YOUR_API_KEY'" > .env
56
+ ```
57
+
58
+ **Windows:**
59
+ ```bash
60
+ set SENDGRID_API_KEY=YOUR_API_KEY
61
+ # Or permanently:
62
+ setx SENDGRID_API_KEY "YOUR_API_KEY"
63
+ ```
64
+
65
+ ## Basic Email Sending
66
+
67
+ ### Simple Email with Mail Helper Class
68
+
69
+ Here's how to send a basic email using the Mail helper class:
70
+
71
+ ```python
72
+ import os
73
+ from sendgrid import SendGridAPIClient
74
+ from sendgrid.helpers.mail import Mail
75
+
76
+ # Create the email message
77
+ message = Mail(
78
+ from_email='from@example.com',
79
+ to_emails='to@example.com',
80
+ subject='Sending with SendGrid is Fun',
81
+ html_content='<strong>and easy to do anywhere, even with Python</strong>'
82
+ )
83
+
84
+ # Send the email
85
+ try:
86
+ sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
87
+ response = sg.send(message)
88
+ print(response.status_code)
89
+ print(response.body)
90
+ print(response.headers)
91
+ except Exception as e:
92
+ print(e)
93
+ ```
94
+
95
+ ### Email with Both HTML and Plain Text Content
96
+
97
+ ```python
98
+ from sendgrid.helpers.mail import Mail, Content
99
+ from sendgrid import SendGridAPIClient
100
+ import os
101
+
102
+ message = Mail(
103
+ from_email='from@example.com',
104
+ to_emails='to@example.com',
105
+ subject='Multi-format Email'
106
+ )
107
+
108
+ # Add plain text content
109
+ message.add_content(Content("text/plain", "Hello, this is plain text!"))
110
+
111
+ # Add HTML content
112
+ message.add_content(Content("text/html", "<strong>Hello, this is HTML!</strong>"))
113
+
114
+ sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
115
+ response = sg.send(message)
116
+ ```
117
+
118
+ ## Advanced Email Features
119
+
120
+ ### Using Dynamic Templates
121
+
122
+ For emails with dynamic content using SendGrid templates:
123
+
124
+ ```python
125
+ import os
126
+ from sendgrid import SendGridAPIClient
127
+ from sendgrid.helpers.mail import Mail
128
+
129
+ message = Mail(
130
+ from_email='from@example.com',
131
+ to_emails='to@example.com'
132
+ )
133
+
134
+ # Set template ID and dynamic data
135
+ message.template_id = 'd-your-template-id-here'
136
+ message.dynamic_template_data = {
137
+ 'subject': 'Testing Templates',
138
+ 'name': 'John Doe',
139
+ 'city': 'San Francisco'
140
+ }
141
+
142
+ sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
143
+ response = sg.send(message)
144
+ ```
145
+
146
+ ### Multiple Recipients
147
+
148
+ ```python
149
+ from sendgrid.helpers.mail import Mail, To
150
+
151
+ # Multiple recipients in to_emails list
152
+ message = Mail(
153
+ from_email='from@example.com',
154
+ to_emails=['user1@example.com', 'user2@example.com', 'user3@example.com'],
155
+ subject='Email to Multiple Recipients',
156
+ html_content='<strong>Hello everyone!</strong>'
157
+ )
158
+ ```
159
+
160
+ ### Adding Attachments
161
+
162
+ ```python
163
+ from sendgrid.helpers.mail import Mail, Attachment
164
+ import base64
165
+
166
+ message = Mail(
167
+ from_email='from@example.com',
168
+ to_emails='to@example.com',
169
+ subject='Email with Attachment',
170
+ html_content='<strong>Please see attached file</strong>'
171
+ )
172
+
173
+ # Add attachment
174
+ with open('path/to/file.pdf', 'rb') as f:
175
+ data = f.read()
176
+ f.close()
177
+
178
+ encoded_file = base64.b64encode(data).decode()
179
+ attachment = Attachment(
180
+ file_content=encoded_file,
181
+ file_name='attachment.pdf',
182
+ file_type='application/pdf',
183
+ disposition='attachment'
184
+ )
185
+
186
+ message.add_attachment(attachment)
187
+ ```
188
+
189
+ ### Personalizations for Individual Recipients
190
+
191
+ ```python
192
+ from sendgrid.helpers.mail import Mail, Personalization, To, Subject
193
+
194
+ message = Mail()
195
+ message.from_email = 'from@example.com'
196
+
197
+ # Create separate personalization for each recipient
198
+ personalization1 = Personalization()
199
+ personalization1.add_to(To('user1@example.com', 'User One'))
200
+ personalization1.subject = 'Personal message for User One'
201
+
202
+ personalization2 = Personalization()
203
+ personalization2.add_to(To('user2@example.com', 'User Two'))
204
+ personalization2.subject = 'Personal message for User Two'
205
+
206
+ message.add_personalization(personalization1)
207
+ message.add_personalization(personalization2)
208
+ ```
209
+
210
+ ## API Client Usage
211
+
212
+ ### General Web API Usage (Fluent Interface)
213
+
214
+ For accessing other SendGrid APIs beyond mail sending:
215
+
216
+ ```python
217
+ import os
218
+ from sendgrid import SendGridAPIClient
219
+
220
+ sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
221
+
222
+ # Get bounce suppressions
223
+ response = sg.client.suppression.bounces.get()
224
+ print(response.status_code)
225
+ print(response.body)
226
+
227
+ # Get API keys
228
+ response = sg.client.api_keys.get()
229
+ print(response.status_code)
230
+ ```
231
+
232
+ ### Alternative API Usage (Non-Fluent Interface)
233
+
234
+ ```python
235
+ import os
236
+ from sendgrid import SendGridAPIClient
237
+
238
+ sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
239
+
240
+ # Using string path instead of fluent interface
241
+ response = sg.client._("suppression/bounces").get()
242
+ print(response.status_code)
243
+ ```
244
+
245
+ ## Configuration Options
246
+
247
+ ### Data Residency
248
+
249
+ For EU data residency compliance:
250
+
251
+ ```python
252
+ from sendgrid import SendGridAPIClient
253
+
254
+ sg = SendGridAPIClient(api_key='your-api-key')
255
+ sg.set_sendgrid_data_residency('eu') # 'eu' or 'global'
256
+ ```
257
+
258
+ ### Subuser Impersonation
259
+
260
+ To send emails on behalf of a subuser:
261
+
262
+ ```python
263
+ from sendgrid import SendGridAPIClient
264
+
265
+ sg = SendGridAPIClient(
266
+ api_key='your-api-key',
267
+ impersonate_subuser='subuser@example.com'
268
+ )
269
+ ```
270
+
271
+ ## Error Handling
272
+
273
+ Always wrap SendGrid API calls in try-catch blocks:
274
+
275
+ ```python
276
+ import os
277
+ from sendgrid import SendGridAPIClient
278
+ from sendgrid.helpers.mail import Mail
279
+
280
+ message = Mail(
281
+ from_email='from@example.com',
282
+ to_emails='to@example.com',
283
+ subject='Test Email',
284
+ html_content='<strong>Test</strong>'
285
+ )
286
+
287
+ try:
288
+ sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
289
+ response = sg.send(message)
290
+
291
+ # Check response status
292
+ if response.status_code >= 200 and response.status_code < 300:
293
+ print("Email sent successfully!")
294
+ else:
295
+ print(f"Failed to send email. Status: {response.status_code}")
296
+ print(f"Response: {response.body}")
297
+
298
+ except Exception as e:
299
+ print(f"Error occurred: {e}")
300
+ ```
301
+
302
+ ## Best Practices
303
+
304
+ ### Mail Helper Class vs Raw JSON
305
+
306
+ - **Recommended:** Use the Mail helper class for building emails as it provides validation and easier syntax
307
+ - **Alternative:** Raw JSON can be used but requires manual construction of the payload
308
+
309
+ ### Content Ordering
310
+
311
+ When adding multiple content types, follow this order:
312
+ 1. Plain text (`text/plain`)
313
+ 2. AMP HTML (`text/x-amp-html`)
314
+ 3. HTML (`text/html`)
315
+
316
+ ### Environment Variables
317
+
318
+ - Always use environment variables for API keys, never hardcode them
319
+ - Use `.env` files for local development and add them to `.gitignore`
320
+
321
+ ## Common Mail Helper Classes
322
+
323
+ Key classes from `sendgrid.helpers.mail`:
324
+
325
+ - `Mail` - Main email builder class
326
+ - `From` - Sender email address
327
+ - `To`, `Cc`, `Bcc` - Recipient email addresses
328
+ - `Content` - Email content (HTML/plain text)
329
+ - `Attachment` - File attachments
330
+ - `Personalization` - Individual recipient customization
331
+ - `TemplateId` - Dynamic template reference
332
+
333
+ ## Useful Links
334
+
335
+ - **Documentation:** https://sendgrid.com/docs/
336
+ - **API Reference:** https://sendgrid.com/docs/API_Reference/index.html
337
+ - **Library Documentation:** https://github.com/sendgrid/sendgrid-python
338
+ - **Use Cases:** https://github.com/sendgrid/sendgrid-python/tree/main/use_cases
339
+ - **Troubleshooting:** https://github.com/sendgrid/sendgrid-python/blob/main/TROUBLESHOOTING.md
340
+
341
+ ## Notes
342
+
343
+ This SendGrid Python SDK provides full support for SendGrid Web API v3 endpoints. The library uses the Mail helper class as the primary interface for building and sending emails, with the SendGridAPIClient handling the actual API communication. Always ensure proper error handling and use environment variables for sensitive data like API keys.
344
+
345
+ ## Official Documentation
346
+
347
+ **This library allows you to quickly and easily use the SendGrid Web API v3 via Python.**
348
+
349
+ Version 3.X.X+ of this library provides full support for all SendGrid [Web API v3](https://sendgrid.com/docs/API_Reference/Web_API_v3/index.html) endpoints, including the new [v3 /mail/send](https://sendgrid.com/blog/introducing-v3mailsend-sendgrids-new-mail-endpoint).
350
+
351
+ ### Alternative Environment Setup Methods
352
+
353
+ #### Mac
354
+
355
+ Update the development environment with your [SENDGRID_API_KEY](https://app.sendgrid.com/settings/api_keys) (more info [here](https://sendgrid.com/docs/User_Guide/Settings/api_keys.html)), for example:
356
+
357
+ ```bash
358
+ echo "export SENDGRID_API_KEY='YOUR_API_KEY'" > sendgrid.env
359
+ echo "sendgrid.env" >> .gitignore
360
+ source ./sendgrid.env
361
+ ```
362
+ SendGrid also supports local environment file `.env`. Copy or rename `.env_sample` into `.env` and update [SENDGRID_API_KEY](https://app.sendgrid.com/settings/api_keys) with your key.
363
+
364
+ #### Windows
365
+ Temporarily set the environment variable(accessible only during the current cli session):
366
+ ```bash
367
+ set SENDGRID_API_KEY=YOUR_API_KEY
368
+ ```
369
+ Permanently set the environment variable(accessible in all subsequent cli sessions):
370
+ ```bash
371
+ setx SENDGRID_API_KEY "YOUR_API_KEY"
372
+ ```
373
+ ## Code Examples
374
+
375
+ ### With Mail Helper Class
376
+
377
+ ```python
378
+ import sendgrid
379
+ import os
380
+ from sendgrid.helpers.mail import *
381
+
382
+ sg = sendgrid.SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY'))
383
+ from_email = Email("test@example.com")
384
+ to_email = To("test@example.com")
385
+ subject = "Sending with SendGrid is Fun"
386
+ content = Content("text/plain", "and easy to do anywhere, even with Python")
387
+ mail = Mail(from_email, to_email, subject, content)
388
+ response = sg.client.mail.send.post(request_body=mail.get())
389
+ print(response.status_code)
390
+ print(response.body)
391
+ print(response.headers)
392
+ ```
393
+
394
+ ### Fluent API Usage
395
+
396
+ ```python
397
+ import sendgrid
398
+ import os
399
+
400
+ sg = sendgrid.SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY'))
401
+ response = sg.client.suppression.bounces.get()
402
+ print(response.status_code)
403
+ print(response.body)
404
+ print(response.headers)
405
+ ```
406
+
407
+ ### Non-Fluent API Usage
408
+
409
+ ```python
410
+ import sendgrid
411
+ import os
412
+
413
+ sg = sendgrid.SendGridAPIClient(api_key=os.environ.get('SENDGRID_API_KEY'))
414
+ response = sg.client._("suppression/bounces").get()
415
+ print(response.status_code)
416
+ print(response.body)
417
+ print(response.headers)
418
+ ```
419
+ ## SendGridAPIClient Constructor
420
+
421
+ ```python
422
+ def __init__(
423
+ self,
424
+ api_key=None,
425
+ host='https://api.sendgrid.com',
426
+ impersonate_subuser=None):
427
+ """
428
+ Construct the Twilio SendGrid v3 API object.
429
+ Note that the underlying client is being set up during initialization,
430
+ therefore changing attributes in runtime will not affect HTTP client
431
+ behaviour.
432
+
433
+ :param api_key: Twilio SendGrid API key to use. If not provided, value
434
+ will be read from environment variable "SENDGRID_API_KEY"
435
+ :type api_key: string
436
+ :param impersonate_subuser: the subuser to impersonate. Will be passed
437
+ by "On-Behalf-Of" header by underlying
438
+ client. See
439
+ https://sendgrid.com/docs/User_Guide/Settings/subusers.html
440
+ for more details
441
+ :type impersonate_subuser: string
442
+ :param host: base URL for API calls
443
+ :type host: string
444
+ """
445
+ self.api_key = api_key or os.environ.get('SENDGRID_API_KEY')
446
+ auth = 'Bearer {}'.format(self.api_key)
447
+
448
+ super(SendGridAPIClient, self).__init__(auth, host, impersonate_subuser)
449
+ ```
450
+
451
+ ## Helper Class Imports
452
+
453
+ ```python
454
+ from .bcc_email import Bcc
455
+ from .cc_email import Cc
456
+ from .content import Content
457
+ from .custom_arg import CustomArg
458
+ from .dynamic_template_data import DynamicTemplateData
459
+ from .email import Email
460
+ from .from_email import From
461
+ from .header import Header
462
+ from .mime_type import MimeType
463
+ from .personalization import Personalization
464
+ from .reply_to import ReplyTo
465
+ from .send_at import SendAt
466
+ from .subject import Subject
467
+ from .substitution import Substitution
468
+ from .template_id import TemplateId
469
+ from .to_email import To
470
+ ```
471
+
472
+ ## Mail Methods
473
+
474
+ ### Add Personalization
475
+
476
+ ```python
477
+ def add_personalization(self, personalization, index=0):
478
+ """Add a Personalization object
479
+
480
+ :param personalization: Add a Personalization object
481
+ :type personalization: Personalization
482
+ :param index: The index where to add the Personalization
483
+ :type index: int
484
+ """
485
+ self._personalizations = self._ensure_append(
486
+ personalization, self._personalizations, index)
487
+ ```
488
+
489
+ ### Add To Recipients
490
+
491
+ ```python
492
+ def add_to(
493
+ self, to_email, global_substitutions=None, is_multiple=False, p=0):
494
+ """Adds a To object to the Personalization object
495
+
496
+ :param to_email: A To object
497
+ :type to_email: To, str, tuple, list(str), list(tuple), list(To)
498
+ :param global_substitutions: A dict of substitutions for all recipients
499
+ :type global_substitutions: dict
500
+ :param is_multiple: Create a new personalization for each recipient
501
+ :type is_multiple: bool
502
+ :param p: p is the Personalization object or Personalization object
503
+ index
504
+ :type p: Personalization, integer, optional
505
+ """
506
+
507
+ if isinstance(to_email, list):
508
+ for email in to_email:
509
+ if isinstance(email, str):
510
+ email = To(email, None)
511
+ elif isinstance(email, tuple):
512
+ email = To(email[0], email[1])
513
+ elif not isinstance(email, Email):
514
+ raise ValueError(
515
+ 'Please use a To/Cc/Bcc, tuple, or a str for a to_email list.'
516
+ )
517
+ self._set_emails(email, global_substitutions, is_multiple, p)
518
+ else:
519
+ if isinstance(to_email, str):
520
+ to_email = To(to_email, None)
521
+ if isinstance(to_email, tuple):
522
+ to_email = To(to_email[0], to_email[1])
523
+ if isinstance(to_email, Email):
524
+ p = to_email.personalization
525
+ self._set_emails(to_email, global_substitutions, is_multiple, p)
526
+ ```
527
+
528
+ ### Add Content
529
+
530
+ ```python
531
+ def add_content(self, content, mime_type=None):
532
+ """Add content to the email
533
+
534
+ :param contents: Content to be added to the email
535
+ :type contents: Content
536
+ :param mime_type: Override the mime type
537
+ :type mime_type: MimeType, str
538
+ """
539
+ if isinstance(content, str):
540
+ content = Content(mime_type, content)
541
+ # Content of mime type text/plain must always come first, followed by text/x-amp-html and then text/html
542
+ if content.mime_type == MimeType.text:
543
+ self._contents = self._ensure_insert(content, self._contents)
544
+ elif content.mime_type == MimeType.amp:
545
+ if self._contents:
546
+ for _content in self._contents:
547
+ # this is written in the context that plain text content will always come earlier than the html content
548
+ if _content.mime_type == MimeType.text:
549
+ index = 1
550
+ break
551
+ elif _content.mime_type == MimeType.html:
552
+ index = 0
553
+ break
554
+ else:
555
+ index = 0
556
+ self._contents = self._ensure_append(
557
+ content, self._contents, index=index)
558
+ else:
559
+ if self._contents:
560
+ index = len(self._contents)
561
+ else:
562
+ index = 0
563
+ self._contents = self._ensure_append(
564
+ content, self._contents, index=index)
565
+ ```
566
+
567
+ ### Add Attachment
568
+
569
+ ```python
570
+ def add_attachment(self, attachment):
571
+ """Add an attachment to this email
572
+
573
+ :param attachment: Add an attachment to this email
574
+ :type attachment: Attachment
575
+ """
576
+ self._attachments = self._ensure_append(attachment, self._attachments)
577
+ ```
578
+
579
+ ## Template Usage Example
580
+
581
+ ```python
582
+ message = Mail(
583
+ from_email='from_email@example.com',
584
+ to_emails='to@example.com',
585
+ html_content='<strong>and easy to do anywhere, even with Python</strong>')
586
+ message.dynamic_template_data = {
587
+ 'subject': 'Testing Templates',
588
+ 'name': 'Some One',
589
+ 'city': 'Denver'
590
+ }
591
+ message.template_id = 'd-f43daeeaef504760851f727007e0b5d0'
592
+ try:
593
+ sendgrid_client = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
594
+ response = sendgrid_client.send(message)
595
+ print(response.status_code)
596
+ print(response.body)
597
+ print(response.headers)
598
+ except Exception as e:
599
+ print(e.message)
600
+ ```
601
+
602
+ ## SendGridAPIClient Methods
603
+
604
+ ### Send Method
605
+
606
+ ```python
607
+ def send(self, message):
608
+ """Make a Twilio SendGrid v3 API request with the request body generated by
609
+ the Mail object
610
+
611
+ :param message: The Twilio SendGrid v3 API request body generated by the Mail
612
+ object
613
+ :type message: Mail
614
+ """
615
+ if not isinstance(message, dict):
616
+ message = message.get()
617
+
618
+ return self.client.mail.send.post(request_body=message)
619
+ ```
620
+
621
+ ### Data Residency Method
622
+
623
+ ```python
624
+ def set_sendgrid_data_residency(self, region):
625
+ """
626
+ Client libraries contain setters for specifying region/edge.
627
+ This supports global and eu regions only. This set will likely expand in the future.
628
+ Global is the default residency (or region)
629
+ Global region means the message will be sent through https://api.sendgrid.com
630
+ EU region means the message will be sent through https://api.eu.sendgrid.com
631
+ :param region: string
632
+ :return:
633
+ """
634
+ if region in region_host_dict.keys():
635
+ self.host = region_host_dict[region]
636
+ if self._default_headers is not None:
637
+ self.client = python_http_client.Client(
638
+ host=self.host,
639
+ request_headers=self._default_headers,
640
+ version=3)
641
+ else:
642
+ raise ValueError("region can only be \"eu\" or \"global\"")
643
+ ```
644
+
645
+ ## Final Error Handling Example
646
+
647
+ ```python
648
+ try:
649
+ sendgrid_client = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
650
+ response = sendgrid_client.send(message)
651
+ print(response.status_code)
652
+ print(response.body)
653
+ print(response.headers)
654
+ except Exception as e:
655
+ print(e)
656
+ ```